Merge "Don't allow userID changes on upgrade" into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index 70348b2..53738dc 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3578,6 +3578,7 @@
method public final deprecated void removeDialog(int);
method public void reportFullyDrawn();
method public android.view.DropPermissions requestDropPermissions(android.view.DragEvent);
+ method public final void requestKeyboardShortcutsHelper();
method public final void requestPermissions(java.lang.String[], int);
method public boolean requestVisibleBehind(boolean);
method public final boolean requestWindowFeature(int);
@@ -4915,6 +4916,7 @@
field public static final int DEFAULT_LIGHTS = 4; // 0x4
field public static final int DEFAULT_SOUND = 1; // 0x1
field public static final int DEFAULT_VIBRATE = 2; // 0x2
+ field public static final java.lang.String EXTRA_ALLOW_GENERATED_REPLIES = "android.allowGeneratedReplies";
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";
@@ -4923,12 +4925,14 @@
field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon";
field public static final java.lang.String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big";
field public static final java.lang.String EXTRA_MEDIA_SESSION = "android.mediaSession";
+ field public static final java.lang.String EXTRA_MESSAGES = "android.messages";
field public static final java.lang.String EXTRA_PEOPLE = "android.people";
field public static final java.lang.String EXTRA_PICTURE = "android.picture";
field public static final java.lang.String EXTRA_PROGRESS = "android.progress";
field public static final java.lang.String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
field public static final java.lang.String EXTRA_PROGRESS_MAX = "android.progressMax";
field public static final java.lang.String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory";
+ field public static final java.lang.String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
field public static final java.lang.String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
field public static final java.lang.String EXTRA_SHOW_WHEN = "android.showWhen";
field public static final java.lang.String EXTRA_SMALL_ICON = "android.icon";
@@ -4937,6 +4941,7 @@
field public static final java.lang.String EXTRA_TEMPLATE = "android.template";
field public static final java.lang.String EXTRA_TEXT = "android.text";
field public static final java.lang.String EXTRA_TEXT_LINES = "android.textLines";
+ field public static final java.lang.String EXTRA_THREAD_TITLE = "android.threadTitle";
field public static final java.lang.String EXTRA_TITLE = "android.title";
field public static final java.lang.String EXTRA_TITLE_BIG = "android.title.big";
field public static final int FLAG_AUTO_CANCEL = 16; // 0x10
@@ -5026,11 +5031,13 @@
method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Builder);
method public java.lang.CharSequence getCancelLabel();
method public java.lang.CharSequence getConfirmLabel();
+ method public boolean getHintContentIntentLaunchesActivity();
method public java.lang.CharSequence getInProgressLabel();
method public boolean isAvailableOffline();
method public android.app.Notification.Action.WearableExtender setAvailableOffline(boolean);
method public android.app.Notification.Action.WearableExtender setCancelLabel(java.lang.CharSequence);
method public android.app.Notification.Action.WearableExtender setConfirmLabel(java.lang.CharSequence);
+ method public android.app.Notification.Action.WearableExtender setHintContentIntentLaunchesActivity(boolean);
method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence);
}
@@ -5174,6 +5181,32 @@
method public android.app.Notification.MediaStyle setShowActionsInCompactView(int...);
}
+ public static class Notification.MessagingStyle extends android.app.Notification.Style {
+ ctor public Notification.MessagingStyle(java.lang.CharSequence);
+ method public android.app.Notification.MessagingStyle addMessage(java.lang.CharSequence, long, java.lang.CharSequence);
+ method public android.app.Notification.MessagingStyle addMessage(android.app.Notification.MessagingStyle.Message);
+ method public boolean getAllowGeneratedReplies();
+ method public java.lang.CharSequence getConversationTitle();
+ method public java.util.List<android.app.Notification.MessagingStyle.Message> getMessages();
+ method public java.lang.CharSequence getUserDisplayName();
+ method public android.app.Notification.MessagingStyle setAllowGeneratedReplies(boolean);
+ method public android.app.Notification.MessagingStyle setConversationTitle(java.lang.CharSequence);
+ field public static final int MAXIMUM_RETAINED_MESSAGES = 25; // 0x19
+ }
+
+ public static final class Notification.MessagingStyle.Message implements android.os.Parcelable {
+ ctor public Notification.MessagingStyle.Message(java.lang.CharSequence, long, java.lang.CharSequence);
+ method public int describeContents();
+ method public java.lang.String getDataMimeType();
+ method public android.net.Uri getDataUri();
+ method public java.lang.CharSequence getSender();
+ method public java.lang.CharSequence getText();
+ method public long getTimestamp();
+ method public android.app.Notification.MessagingStyle.Message setData(java.lang.String, android.net.Uri);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.Notification.MessagingStyle.Message> CREATOR;
+ }
+
public static abstract class Notification.Style {
ctor public Notification.Style();
method public android.app.Notification build();
@@ -5207,6 +5240,7 @@
method public android.app.PendingIntent getDisplayIntent();
method public int getGravity();
method public boolean getHintAvoidBackgroundClipping();
+ method public boolean getHintContentIntentLaunchesActivity();
method public boolean getHintHideIcon();
method public int getHintScreenTimeout();
method public boolean getHintShowBackgroundOnly();
@@ -5222,6 +5256,7 @@
method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent);
method public android.app.Notification.WearableExtender setGravity(int);
method public android.app.Notification.WearableExtender setHintAvoidBackgroundClipping(boolean);
+ method public android.app.Notification.WearableExtender setHintContentIntentLaunchesActivity(boolean);
method public android.app.Notification.WearableExtender setHintHideIcon(boolean);
method public android.app.Notification.WearableExtender setHintScreenTimeout(int);
method public android.app.Notification.WearableExtender setHintShowBackgroundOnly(boolean);
@@ -7669,8 +7704,6 @@
method public void setExtras(android.os.PersistableBundle);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.ClipDescription> CREATOR;
- field public static final java.lang.String EXTRA_TARGET_COMPONENT_NAME = "android.content.extra.TARGET_COMPONENT_NAME";
- field public static final java.lang.String EXTRA_USER_SERIAL_NUMBER = "android.content.extra.USER_SERIAL_NUMBER";
field public static final java.lang.String MIMETYPE_TEXT_HTML = "text/html";
field public static final java.lang.String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent";
field public static final java.lang.String MIMETYPE_TEXT_PLAIN = "text/plain";
@@ -8653,6 +8686,7 @@
field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
field public static final java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
field public static final java.lang.String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER = "android.intent.extra.CHOOSER_REFINEMENT_INTENT_SENDER";
+ field public static final java.lang.String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER";
field public static final java.lang.String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED";
@@ -8664,6 +8698,7 @@
field public static final int EXTRA_DOCK_STATE_UNDOCKED = 0; // 0x0
field public static final java.lang.String EXTRA_DONT_KILL_APP = "android.intent.extra.DONT_KILL_APP";
field public static final java.lang.String EXTRA_EMAIL = "android.intent.extra.EMAIL";
+ field public static final java.lang.String EXTRA_EXCLUDE_COMPONENTS = "android.intent.extra.EXCLUDE_COMPONENTS";
field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
field public static final java.lang.String EXTRA_INDEX = "android.intent.extra.INDEX";
field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
@@ -9463,9 +9498,10 @@
public class LauncherApps {
method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
- method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo, android.os.UserHandle);
- method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
- method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
+ method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo);
+ method public android.os.ParcelFileDescriptor getShortcutIconFd(java.lang.String, java.lang.String, android.os.UserHandle);
+ method public int getShortcutIconResId(android.content.pm.ShortcutInfo);
+ method public int getShortcutIconResId(java.lang.String, java.lang.String, android.os.UserHandle);
method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
method public boolean hasShortcutHostPermission();
method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
@@ -9477,6 +9513,7 @@
method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
method public boolean startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
+ method public boolean startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle);
method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
}
@@ -9498,6 +9535,7 @@
method public void setChangedSince(long);
method public void setPackage(java.lang.String);
method public void setQueryFlags(int);
+ method public void setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_DYNAMIC = 1; // 0x1
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
field public static final int FLAG_GET_PINNED = 2; // 0x2
@@ -10011,6 +10049,7 @@
method public java.lang.String getPackageName();
method public java.lang.String getText();
method public java.lang.String getTitle();
+ method public android.os.UserHandle getUserHandle();
method public int getWeight();
method public boolean hasIconFile();
method public boolean hasIconResource();
@@ -13891,11 +13930,11 @@
method public abstract void close();
method public abstract android.hardware.camera2.CaptureRequest.Builder createCaptureRequest(int) throws android.hardware.camera2.CameraAccessException;
method public abstract void createCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
- method public abstract void createCaptureSessionByOutputConfiguration(java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+ method public abstract void createCaptureSessionByOutputConfigurations(java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract void createConstrainedHighSpeedCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract android.hardware.camera2.CaptureRequest.Builder createReprocessCaptureRequest(android.hardware.camera2.TotalCaptureResult) throws android.hardware.camera2.CameraAccessException;
method public abstract void createReprocessableCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
- method public abstract void createReprocessableCaptureSessionWithConfigurations(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+ method public abstract void createReprocessableCaptureSessionByConfigurations(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract java.lang.String getId();
field public static final int TEMPLATE_MANUAL = 6; // 0x6
field public static final int TEMPLATE_PREVIEW = 1; // 0x1
@@ -19217,7 +19256,7 @@
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 int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
- field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+ field public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2; // 0x2
field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
field public static final int STATE_BDS_D2_BIT_SYNC = 256; // 0x100
field public static final int STATE_BDS_D2_SUBFRAME_SYNC = 512; // 0x200
@@ -19237,21 +19276,20 @@
}
public final class GnssMeasurementsEvent implements android.os.Parcelable {
- ctor public GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]);
method public int describeContents();
method public android.location.GnssClock getClock();
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_GNSS_LOCATION_DISABLED = 2; // 0x2
- field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field public static final int STATUS_READY = 1; // 0x1
}
public static abstract class GnssMeasurementsEvent.Callback {
ctor public GnssMeasurementsEvent.Callback();
method public void onGnssMeasurementsReceived(android.location.GnssMeasurementsEvent);
method public void onStatusChanged(int);
+ field public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+ field public static final int STATUS_READY = 1; // 0x1
}
public final class GnssNavigationMessage implements android.os.Parcelable {
@@ -19279,36 +19317,24 @@
field public static final int TYPE_UNKNOWN = 0; // 0x0
}
- public final class GnssNavigationMessageEvent implements android.os.Parcelable {
- ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
- method public int describeContents();
- 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_GNSS_LOCATION_DISABLED = 2; // 0x2
+ public static abstract class GnssNavigationMessage.Callback {
+ ctor public GnssNavigationMessage.Callback();
+ method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessage);
+ method public void onStatusChanged(int);
+ field public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
field public static final int STATUS_READY = 1; // 0x1
}
- public static abstract class GnssNavigationMessageEvent.Callback {
- ctor public GnssNavigationMessageEvent.Callback();
- method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
- method public void onStatusChanged(int);
- }
-
- public abstract interface GnssNmeaListener {
- method public abstract void onNmeaReceived(long, java.lang.String);
- }
-
public final class GnssStatus {
method public float getAzimuthDegrees(int);
method public float getCn0DbHz(int);
method public int getConstellationType(int);
method public float getElevationDegrees(int);
- method public int getNumSatellites();
+ method public int getSatelliteCount();
method public int getSvid(int);
- method public boolean hasAlmanac(int);
- method public boolean hasEphemeris(int);
+ method public boolean hasAlmanacData(int);
+ method public boolean hasEphemerisData(int);
method public boolean usedInFix(int);
field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
field public static final int CONSTELLATION_GALILEO = 6; // 0x6
@@ -19319,15 +19345,15 @@
field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
}
- public abstract class GnssStatusCallback {
- ctor public GnssStatusCallback();
+ public static abstract class GnssStatus.Callback {
+ ctor public GnssStatus.Callback();
method public void onFirstFix(int);
method public void onSatelliteStatusChanged(android.location.GnssStatus);
method public void onStarted();
method public void onStopped();
}
- public final class GpsSatellite {
+ public final deprecated class GpsSatellite {
method public float getAzimuth();
method public float getElevation();
method public int getPrn();
@@ -19337,7 +19363,7 @@
method public boolean usedInFix();
}
- public final class GpsStatus {
+ public final deprecated class GpsStatus {
method public int getMaxSatellites();
method public java.lang.Iterable<android.location.GpsSatellite> getSatellites();
method public int getTimeToFirstFix();
@@ -19347,11 +19373,11 @@
field public static final int GPS_EVENT_STOPPED = 2; // 0x2
}
- public static abstract interface GpsStatus.Listener {
+ public static abstract deprecated interface GpsStatus.Listener {
method public abstract void onGpsStatusChanged(int);
}
- public static abstract interface GpsStatus.NmeaListener {
+ public static abstract deprecated interface GpsStatus.NmeaListener {
method public abstract void onNmeaReceived(long, java.lang.String);
}
@@ -19413,8 +19439,8 @@
public class LocationManager {
method public deprecated boolean addGpsStatusListener(android.location.GpsStatus.Listener);
method public deprecated boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
- method public boolean addNmeaListener(android.location.GnssNmeaListener);
- method public boolean addNmeaListener(android.location.GnssNmeaListener, android.os.Handler);
+ method public boolean addNmeaListener(android.location.OnNmeaMessageListener);
+ method public boolean addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler);
method public void addProximityAlert(double, double, float, long, android.app.PendingIntent);
method public void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
method public void clearTestProviderEnabled(java.lang.String);
@@ -19430,13 +19456,13 @@
method public boolean isProviderEnabled(java.lang.String);
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);
- method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
+ method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
+ method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback, android.os.Handler);
+ method public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback);
+ method public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback, android.os.Handler);
method public deprecated void removeGpsStatusListener(android.location.GpsStatus.Listener);
method public deprecated void removeNmeaListener(android.location.GpsStatus.NmeaListener);
- method public void removeNmeaListener(android.location.GnssNmeaListener);
+ method public void removeNmeaListener(android.location.OnNmeaMessageListener);
method public void removeProximityAlert(android.app.PendingIntent);
method public void removeTestProvider(java.lang.String);
method public void removeUpdates(android.location.LocationListener);
@@ -19455,8 +19481,8 @@
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 unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
- method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
- method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
+ method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
+ method public void unregisterGnssStatusCallback(android.location.GnssStatus.Callback);
field public static final java.lang.String GPS_PROVIDER = "gps";
field public static final java.lang.String KEY_LOCATION_CHANGED = "location";
field public static final java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled";
@@ -19485,6 +19511,10 @@
field public static final int TEMPORARILY_UNAVAILABLE = 1; // 0x1
}
+ public abstract interface OnNmeaMessageListener {
+ method public abstract void onNmeaMessage(java.lang.String, long);
+ }
+
public abstract class SettingInjectorService extends android.app.Service {
ctor public SettingInjectorService(java.lang.String);
method public final android.os.IBinder onBind(android.content.Intent);
@@ -34688,6 +34718,7 @@
method public android.os.IBinder onBind(android.content.Intent);
method public void onInterruptionFilterChanged(int);
method public void onListenerConnected();
+ method public void onListenerDisconnected();
method public void onListenerHintsChanged(int);
method public void onNotificationPosted(android.service.notification.StatusBarNotification);
method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
@@ -34699,7 +34730,9 @@
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 int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
+ field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
field public static final int INTERRUPTION_FILTER_ALARMS = 4; // 0x4
field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
@@ -34715,6 +34748,7 @@
method public int getImportance();
method public java.lang.CharSequence getImportanceExplanation();
method public java.lang.String getKey();
+ method public java.lang.String getOverrideGroupKey();
method public int getRank();
method public int getSuppressedVisualEffects();
method public boolean isAmbient();
@@ -34745,13 +34779,16 @@
method public int getId();
method public java.lang.String getKey();
method public android.app.Notification getNotification();
+ method public java.lang.String getOverrideGroupKey();
method public java.lang.String getPackageName();
method public long getPostTime();
method public java.lang.String getTag();
method public android.os.UserHandle getUser();
method public deprecated int getUserId();
method public boolean isClearable();
+ method public boolean isGroup();
method public boolean isOngoing();
+ method public void setOverrideGroupKey(java.lang.String);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.notification.StatusBarNotification> CREATOR;
}
@@ -34787,7 +34824,7 @@
method public void onClick();
method public void onStartListening();
method public void onStopListening();
- method public int onTileAdded();
+ method public void onTileAdded();
method public void onTileRemoved();
method public static final void requestListeningState(android.content.Context, android.content.ComponentName);
method public final void showDialog(android.app.Dialog);
@@ -34795,8 +34832,7 @@
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
+ field public static final java.lang.String META_DATA_ACTIVE_TILE = "android.service.quicksettings.ACTIVE_TILE";
}
}
@@ -46438,21 +46474,21 @@
ctor public DatePicker(android.content.Context, android.util.AttributeSet);
ctor public DatePicker(android.content.Context, android.util.AttributeSet, int);
ctor public DatePicker(android.content.Context, android.util.AttributeSet, int, int);
- method public android.widget.CalendarView getCalendarView();
- method public boolean getCalendarViewShown();
+ method public deprecated android.widget.CalendarView getCalendarView();
+ method public deprecated boolean getCalendarViewShown();
method public int getDayOfMonth();
method public int getFirstDayOfWeek();
method public long getMaxDate();
method public long getMinDate();
method public int getMonth();
- method public boolean getSpinnersShown();
+ method public deprecated boolean getSpinnersShown();
method public int getYear();
method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener);
- method public void setCalendarViewShown(boolean);
+ method public deprecated void setCalendarViewShown(boolean);
method public void setFirstDayOfWeek(int);
method public void setMaxDate(long);
method public void setMinDate(long);
- method public void setSpinnersShown(boolean);
+ method public deprecated void setSpinnersShown(boolean);
method public void updateDate(int, int, int);
}
@@ -50025,6 +50061,9 @@
method public int compareTo(java.lang.Boolean);
method public static boolean getBoolean(java.lang.String);
method public static int hashCode(boolean);
+ method public static boolean logicalAnd(boolean, boolean);
+ method public static boolean logicalOr(boolean, boolean);
+ method public static boolean logicalXor(boolean, boolean);
method public static boolean parseBoolean(java.lang.String);
method public static java.lang.String toString(boolean);
method public static java.lang.Boolean valueOf(boolean);
@@ -50988,6 +51027,8 @@
method public static float abs(float);
method public static double abs(double);
method public static double acos(double);
+ method public static int addExact(int, int);
+ method public static long addExact(long, long);
method public static double asin(double);
method public static double atan(double);
method public static double atan2(double, double);
@@ -50997,12 +51038,20 @@
method public static float copySign(float, float);
method public static double cos(double);
method public static double cosh(double);
+ method public static int decrementExact(int);
+ method public static long decrementExact(long);
method public static double exp(double);
method public static double expm1(double);
method public static double floor(double);
+ method public static int floorDiv(int, int);
+ method public static long floorDiv(long, long);
+ method public static int floorMod(int, int);
+ method public static long floorMod(long, long);
method public static int getExponent(float);
method public static int getExponent(double);
method public static double hypot(double, double);
+ method public static int incrementExact(int);
+ method public static long incrementExact(long);
method public static double log(double);
method public static double log10(double);
method public static double log1p(double);
@@ -51014,8 +51063,14 @@
method public static long min(long, long);
method public static float min(float, float);
method public static double min(double, double);
+ method public static int multiplyExact(int, int);
+ method public static long multiplyExact(long, long);
+ method public static int negateExact(int);
+ method public static long negateExact(long);
method public static double nextAfter(double, double);
method public static float nextAfter(float, double);
+ method public static double nextDown(double);
+ method public static float nextDown(float);
method public static double nextUp(double);
method public static float nextUp(float);
method public static double pow(double, double);
@@ -51030,9 +51085,12 @@
method public static double sin(double);
method public static double sinh(double);
method public static double sqrt(double);
+ method public static int subtractExact(int, int);
+ method public static long subtractExact(long, long);
method public static double tan(double);
method public static double tanh(double);
method public static double toDegrees(double);
+ method public static int toIntExact(long);
method public static double toRadians(double);
method public static double ulp(double);
method public static float ulp(float);
@@ -51316,6 +51374,8 @@
method public static float abs(float);
method public static double abs(double);
method public static double acos(double);
+ method public static int addExact(int, int);
+ method public static long addExact(long, long);
method public static double asin(double);
method public static double atan(double);
method public static double atan2(double, double);
@@ -51328,6 +51388,10 @@
method public static double exp(double);
method public static double expm1(double);
method public static double floor(double);
+ method public static int floorDiv(int, int);
+ method public static long floorDiv(long, long);
+ method public static int floorMod(int, int);
+ method public static long floorMod(long, long);
method public static int getExponent(float);
method public static int getExponent(double);
method public static double hypot(double, double);
@@ -51342,8 +51406,12 @@
method public static long min(long, long);
method public static float min(float, float);
method public static double min(double, double);
+ method public static int multiplyExact(int, int);
+ method public static long multiplyExact(long, long);
method public static double nextAfter(double, double);
method public static float nextAfter(float, double);
+ method public static double nextDown(double);
+ method public static float nextDown(float);
method public static double nextUp(double);
method public static float nextUp(float);
method public static double pow(double, double);
@@ -51358,9 +51426,12 @@
method public static double sin(double);
method public static double sinh(double);
method public static double sqrt(double);
+ method public static int subtractExact(int, int);
+ method public static long subtractExact(long, long);
method public static double tan(double);
method public static double tanh(double);
method public static double toDegrees(double);
+ method public static int toIntExact(long);
method public static double toRadians(double);
method public static double ulp(double);
method public static float ulp(float);
@@ -51918,7 +51989,6 @@
public final class Method extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
method public boolean equals(java.lang.Object);
method public A getAnnotation(java.lang.Class<A>);
- method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public java.lang.Class<?> getDeclaringClass();
method public java.lang.Object getDefaultValue();
method public java.lang.Class<?>[] getExceptionTypes();
@@ -51932,7 +52002,6 @@
method public java.lang.Class<?> getReturnType();
method public java.lang.reflect.TypeVariable<java.lang.reflect.Method>[] getTypeParameters();
method public java.lang.Object invoke(java.lang.Object, java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
- method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
method public boolean isBridge();
method public boolean isDefault();
method public boolean isSynthetic();
@@ -57408,6 +57477,14 @@
method public static int hashCode(float[]);
method public static int hashCode(double[]);
method public static int hashCode(java.lang.Object[]);
+ method public static void parallelPrefix(T[], java.util.function.BinaryOperator<T>);
+ method public static void parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>);
+ method public static void parallelPrefix(long[], java.util.function.LongBinaryOperator);
+ method public static void parallelPrefix(long[], int, int, java.util.function.LongBinaryOperator);
+ method public static void parallelPrefix(double[], java.util.function.DoubleBinaryOperator);
+ method public static void parallelPrefix(double[], int, int, java.util.function.DoubleBinaryOperator);
+ method public static void parallelPrefix(int[], java.util.function.IntBinaryOperator);
+ method public static void parallelPrefix(int[], int, int, java.util.function.IntBinaryOperator);
method public static void parallelSetAll(T[], java.util.function.IntFunction<? extends T>);
method public static void parallelSetAll(int[], java.util.function.IntUnaryOperator);
method public static void parallelSetAll(long[], java.util.function.IntToLongFunction);
diff --git a/api/removed.txt b/api/removed.txt
index 3f16bca..8c6abdc 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -84,6 +84,67 @@
}
+package android.location {
+
+ public final class GnssMeasurement implements android.os.Parcelable {
+ field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+ }
+
+ public final class GnssMeasurementsEvent implements android.os.Parcelable {
+ 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
+ }
+
+ public final class GnssNavigationMessageEvent implements android.os.Parcelable {
+ ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
+ method public int describeContents();
+ 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_GNSS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+ field public static final int STATUS_READY = 1; // 0x1
+ }
+
+ public static abstract class GnssNavigationMessageEvent.Callback {
+ ctor public GnssNavigationMessageEvent.Callback();
+ method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
+ method public void onStatusChanged(int);
+ }
+
+ public abstract interface GnssNmeaListener {
+ method public abstract void onNmeaReceived(long, java.lang.String);
+ }
+
+ public final class GnssStatus {
+ method public int getNumSatellites();
+ method public boolean hasAlmanac(int);
+ method public boolean hasEphemeris(int);
+ }
+
+ public abstract class GnssStatusCallback {
+ ctor public GnssStatusCallback();
+ method public void onFirstFix(int);
+ method public void onSatelliteStatusChanged(android.location.GnssStatus);
+ method public void onStarted();
+ method public void onStopped();
+ }
+
+ public class LocationManager {
+ method public boolean addNmeaListener(android.location.GnssNmeaListener);
+ method public boolean addNmeaListener(android.location.GnssNmeaListener, 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);
+ method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
+ method public void removeNmeaListener(android.location.GnssNmeaListener);
+ method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
+ method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
+ }
+
+}
+
package android.media {
public final class AudioFormat implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index d6154b5..0e9baa6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3696,6 +3696,7 @@
method public final deprecated void removeDialog(int);
method public void reportFullyDrawn();
method public android.view.DropPermissions requestDropPermissions(android.view.DragEvent);
+ method public final void requestKeyboardShortcutsHelper();
method public final void requestPermissions(java.lang.String[], int);
method public boolean requestVisibleBehind(boolean);
method public final boolean requestWindowFeature(int);
@@ -5048,6 +5049,7 @@
field public static final int DEFAULT_LIGHTS = 4; // 0x4
field public static final int DEFAULT_SOUND = 1; // 0x1
field public static final int DEFAULT_VIBRATE = 2; // 0x2
+ field public static final java.lang.String EXTRA_ALLOW_GENERATED_REPLIES = "android.allowGeneratedReplies";
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";
@@ -5056,12 +5058,14 @@
field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon";
field public static final java.lang.String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big";
field public static final java.lang.String EXTRA_MEDIA_SESSION = "android.mediaSession";
+ field public static final java.lang.String EXTRA_MESSAGES = "android.messages";
field public static final java.lang.String EXTRA_PEOPLE = "android.people";
field public static final java.lang.String EXTRA_PICTURE = "android.picture";
field public static final java.lang.String EXTRA_PROGRESS = "android.progress";
field public static final java.lang.String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
field public static final java.lang.String EXTRA_PROGRESS_MAX = "android.progressMax";
field public static final java.lang.String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory";
+ field public static final java.lang.String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
field public static final java.lang.String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
field public static final java.lang.String EXTRA_SHOW_WHEN = "android.showWhen";
field public static final java.lang.String EXTRA_SMALL_ICON = "android.icon";
@@ -5070,8 +5074,10 @@
field public static final java.lang.String EXTRA_TEMPLATE = "android.template";
field public static final java.lang.String EXTRA_TEXT = "android.text";
field public static final java.lang.String EXTRA_TEXT_LINES = "android.textLines";
+ field public static final java.lang.String EXTRA_THREAD_TITLE = "android.threadTitle";
field public static final java.lang.String EXTRA_TITLE = "android.title";
field public static final java.lang.String EXTRA_TITLE_BIG = "android.title.big";
+ field public static final int FLAG_AUTOGROUP_SUMMARY = 1024; // 0x400
field public static final int FLAG_AUTO_CANCEL = 16; // 0x10
field public static final int FLAG_FOREGROUND_SERVICE = 64; // 0x40
field public static final int FLAG_GROUP_SUMMARY = 512; // 0x200
@@ -5159,11 +5165,13 @@
method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Builder);
method public java.lang.CharSequence getCancelLabel();
method public java.lang.CharSequence getConfirmLabel();
+ method public boolean getHintContentIntentLaunchesActivity();
method public java.lang.CharSequence getInProgressLabel();
method public boolean isAvailableOffline();
method public android.app.Notification.Action.WearableExtender setAvailableOffline(boolean);
method public android.app.Notification.Action.WearableExtender setCancelLabel(java.lang.CharSequence);
method public android.app.Notification.Action.WearableExtender setConfirmLabel(java.lang.CharSequence);
+ method public android.app.Notification.Action.WearableExtender setHintContentIntentLaunchesActivity(boolean);
method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence);
}
@@ -5307,6 +5315,32 @@
method public android.app.Notification.MediaStyle setShowActionsInCompactView(int...);
}
+ public static class Notification.MessagingStyle extends android.app.Notification.Style {
+ ctor public Notification.MessagingStyle(java.lang.CharSequence);
+ method public android.app.Notification.MessagingStyle addMessage(java.lang.CharSequence, long, java.lang.CharSequence);
+ method public android.app.Notification.MessagingStyle addMessage(android.app.Notification.MessagingStyle.Message);
+ method public boolean getAllowGeneratedReplies();
+ method public java.lang.CharSequence getConversationTitle();
+ method public java.util.List<android.app.Notification.MessagingStyle.Message> getMessages();
+ method public java.lang.CharSequence getUserDisplayName();
+ method public android.app.Notification.MessagingStyle setAllowGeneratedReplies(boolean);
+ method public android.app.Notification.MessagingStyle setConversationTitle(java.lang.CharSequence);
+ field public static final int MAXIMUM_RETAINED_MESSAGES = 25; // 0x19
+ }
+
+ public static final class Notification.MessagingStyle.Message implements android.os.Parcelable {
+ ctor public Notification.MessagingStyle.Message(java.lang.CharSequence, long, java.lang.CharSequence);
+ method public int describeContents();
+ method public java.lang.String getDataMimeType();
+ method public android.net.Uri getDataUri();
+ method public java.lang.CharSequence getSender();
+ method public java.lang.CharSequence getText();
+ method public long getTimestamp();
+ method public android.app.Notification.MessagingStyle.Message setData(java.lang.String, android.net.Uri);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.Notification.MessagingStyle.Message> CREATOR;
+ }
+
public static abstract class Notification.Style {
ctor public Notification.Style();
method public android.app.Notification build();
@@ -5340,6 +5374,7 @@
method public android.app.PendingIntent getDisplayIntent();
method public int getGravity();
method public boolean getHintAvoidBackgroundClipping();
+ method public boolean getHintContentIntentLaunchesActivity();
method public boolean getHintHideIcon();
method public int getHintScreenTimeout();
method public boolean getHintShowBackgroundOnly();
@@ -5355,6 +5390,7 @@
method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent);
method public android.app.Notification.WearableExtender setGravity(int);
method public android.app.Notification.WearableExtender setHintAvoidBackgroundClipping(boolean);
+ method public android.app.Notification.WearableExtender setHintContentIntentLaunchesActivity(boolean);
method public android.app.Notification.WearableExtender setHintHideIcon(boolean);
method public android.app.Notification.WearableExtender setHintScreenTimeout(int);
method public android.app.Notification.WearableExtender setHintShowBackgroundOnly(boolean);
@@ -7967,8 +8003,6 @@
method public void setExtras(android.os.PersistableBundle);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.ClipDescription> CREATOR;
- field public static final java.lang.String EXTRA_TARGET_COMPONENT_NAME = "android.content.extra.TARGET_COMPONENT_NAME";
- field public static final java.lang.String EXTRA_USER_SERIAL_NUMBER = "android.content.extra.USER_SERIAL_NUMBER";
field public static final java.lang.String MIMETYPE_TEXT_HTML = "text/html";
field public static final java.lang.String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent";
field public static final java.lang.String MIMETYPE_TEXT_PLAIN = "text/plain";
@@ -8972,6 +9006,7 @@
field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
field public static final java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
field public static final java.lang.String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER = "android.intent.extra.CHOOSER_REFINEMENT_INTENT_SENDER";
+ field public static final java.lang.String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER";
field public static final java.lang.String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED";
@@ -8985,6 +9020,7 @@
field public static final java.lang.String EXTRA_EMAIL = "android.intent.extra.EMAIL";
field public static final java.lang.String EXTRA_EPHEMERAL_FAILURE = "android.intent.extra.EPHEMERAL_FAILURE";
field public static final java.lang.String EXTRA_EPHEMERAL_SUCCESS = "android.intent.extra.EPHEMERAL_SUCCESS";
+ field public static final java.lang.String EXTRA_EXCLUDE_COMPONENTS = "android.intent.extra.EXCLUDE_COMPONENTS";
field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
field public static final java.lang.String EXTRA_INDEX = "android.intent.extra.INDEX";
field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
@@ -9800,9 +9836,10 @@
public class LauncherApps {
method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
- method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo, android.os.UserHandle);
- method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
- method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
+ method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo);
+ method public android.os.ParcelFileDescriptor getShortcutIconFd(java.lang.String, java.lang.String, android.os.UserHandle);
+ method public int getShortcutIconResId(android.content.pm.ShortcutInfo);
+ method public int getShortcutIconResId(java.lang.String, java.lang.String, android.os.UserHandle);
method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
method public boolean hasShortcutHostPermission();
method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
@@ -9814,6 +9851,7 @@
method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
method public boolean startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
+ method public boolean startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle);
method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
}
@@ -9835,6 +9873,7 @@
method public void setChangedSince(long);
method public void setPackage(java.lang.String);
method public void setQueryFlags(int);
+ method public void setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_DYNAMIC = 1; // 0x1
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
field public static final int FLAG_GET_PINNED = 2; // 0x2
@@ -10410,6 +10449,7 @@
method public java.lang.String getPackageName();
method public java.lang.String getText();
method public java.lang.String getTitle();
+ method public android.os.UserHandle getUserHandle();
method public int getWeight();
method public boolean hasIconFile();
method public boolean hasIconResource();
@@ -14298,11 +14338,11 @@
method public abstract void close();
method public abstract android.hardware.camera2.CaptureRequest.Builder createCaptureRequest(int) throws android.hardware.camera2.CameraAccessException;
method public abstract void createCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
- method public abstract void createCaptureSessionByOutputConfiguration(java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+ method public abstract void createCaptureSessionByOutputConfigurations(java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract void createConstrainedHighSpeedCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract android.hardware.camera2.CaptureRequest.Builder createReprocessCaptureRequest(android.hardware.camera2.TotalCaptureResult) throws android.hardware.camera2.CameraAccessException;
method public abstract void createReprocessableCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
- method public abstract void createReprocessableCaptureSessionWithConfigurations(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+ method public abstract void createReprocessableCaptureSessionByConfigurations(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract java.lang.String getId();
field public static final int TEMPLATE_MANUAL = 6; // 0x6
field public static final int TEMPLATE_PREVIEW = 1; // 0x1
@@ -20377,7 +20417,7 @@
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 int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
- field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+ field public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2; // 0x2
field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
field public static final int STATE_BDS_D2_BIT_SYNC = 256; // 0x100
field public static final int STATE_BDS_D2_SUBFRAME_SYNC = 512; // 0x200
@@ -20397,21 +20437,20 @@
}
public final class GnssMeasurementsEvent implements android.os.Parcelable {
- ctor public GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]);
method public int describeContents();
method public android.location.GnssClock getClock();
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_GNSS_LOCATION_DISABLED = 2; // 0x2
- field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field public static final int STATUS_READY = 1; // 0x1
}
public static abstract class GnssMeasurementsEvent.Callback {
ctor public GnssMeasurementsEvent.Callback();
method public void onGnssMeasurementsReceived(android.location.GnssMeasurementsEvent);
method public void onStatusChanged(int);
+ field public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+ field public static final int STATUS_READY = 1; // 0x1
}
public final class GnssNavigationMessage implements android.os.Parcelable {
@@ -20439,36 +20478,24 @@
field public static final int TYPE_UNKNOWN = 0; // 0x0
}
- public final class GnssNavigationMessageEvent implements android.os.Parcelable {
- ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
- method public int describeContents();
- 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_GNSS_LOCATION_DISABLED = 2; // 0x2
+ public static abstract class GnssNavigationMessage.Callback {
+ ctor public GnssNavigationMessage.Callback();
+ method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessage);
+ method public void onStatusChanged(int);
+ field public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
field public static final int STATUS_READY = 1; // 0x1
}
- public static abstract class GnssNavigationMessageEvent.Callback {
- ctor public GnssNavigationMessageEvent.Callback();
- method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
- method public void onStatusChanged(int);
- }
-
- public abstract interface GnssNmeaListener {
- method public abstract void onNmeaReceived(long, java.lang.String);
- }
-
public final class GnssStatus {
method public float getAzimuthDegrees(int);
method public float getCn0DbHz(int);
method public int getConstellationType(int);
method public float getElevationDegrees(int);
- method public int getNumSatellites();
+ method public int getSatelliteCount();
method public int getSvid(int);
- method public boolean hasAlmanac(int);
- method public boolean hasEphemeris(int);
+ method public boolean hasAlmanacData(int);
+ method public boolean hasEphemerisData(int);
method public boolean usedInFix(int);
field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
field public static final int CONSTELLATION_GALILEO = 6; // 0x6
@@ -20479,8 +20506,8 @@
field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
}
- public abstract class GnssStatusCallback {
- ctor public GnssStatusCallback();
+ public static abstract class GnssStatus.Callback {
+ ctor public GnssStatus.Callback();
method public void onFirstFix(int);
method public void onSatelliteStatusChanged(android.location.GnssStatus);
method public void onStarted();
@@ -20712,7 +20739,7 @@
method public abstract void onStatusChanged(int);
}
- public final class GpsSatellite {
+ public final deprecated class GpsSatellite {
method public float getAzimuth();
method public float getElevation();
method public int getPrn();
@@ -20722,7 +20749,7 @@
method public boolean usedInFix();
}
- public final class GpsStatus {
+ public final deprecated class GpsStatus {
method public int getMaxSatellites();
method public java.lang.Iterable<android.location.GpsSatellite> getSatellites();
method public int getTimeToFirstFix();
@@ -20732,11 +20759,11 @@
field public static final int GPS_EVENT_STOPPED = 2; // 0x2
}
- public static abstract interface GpsStatus.Listener {
+ public static abstract deprecated interface GpsStatus.Listener {
method public abstract void onGpsStatusChanged(int);
}
- public static abstract interface GpsStatus.NmeaListener {
+ public static abstract deprecated interface GpsStatus.NmeaListener {
method public abstract void onNmeaReceived(long, java.lang.String);
}
@@ -20820,8 +20847,8 @@
method public deprecated boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
method public deprecated boolean addGpsStatusListener(android.location.GpsStatus.Listener);
method public deprecated boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
- method public boolean addNmeaListener(android.location.GnssNmeaListener);
- method public boolean addNmeaListener(android.location.GnssNmeaListener, android.os.Handler);
+ method public boolean addNmeaListener(android.location.OnNmeaMessageListener);
+ method public boolean addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler);
method public void addProximityAlert(double, double, float, long, android.app.PendingIntent);
method public void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
method public void clearTestProviderEnabled(java.lang.String);
@@ -20837,15 +20864,15 @@
method public boolean isProviderEnabled(java.lang.String);
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);
- method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
+ method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
+ method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback, android.os.Handler);
+ method public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback);
+ method public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback, android.os.Handler);
method public deprecated void removeGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
method public deprecated void removeGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
method public deprecated void removeGpsStatusListener(android.location.GpsStatus.Listener);
method public deprecated void removeNmeaListener(android.location.GpsStatus.NmeaListener);
- method public void removeNmeaListener(android.location.GnssNmeaListener);
+ method public void removeNmeaListener(android.location.OnNmeaMessageListener);
method public void removeProximityAlert(android.app.PendingIntent);
method public void removeTestProvider(java.lang.String);
method public void removeUpdates(android.location.LocationListener);
@@ -20866,8 +20893,8 @@
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 unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
- method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
- method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
+ method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
+ method public void unregisterGnssStatusCallback(android.location.GnssStatus.Callback);
field public static final java.lang.String GPS_PROVIDER = "gps";
field public static final java.lang.String KEY_LOCATION_CHANGED = "location";
field public static final java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled";
@@ -20930,6 +20957,10 @@
field public static final int POWER_NONE = 200; // 0xc8
}
+ public abstract interface OnNmeaMessageListener {
+ method public abstract void onNmeaMessage(java.lang.String, long);
+ }
+
public abstract class SettingInjectorService extends android.app.Service {
ctor public SettingInjectorService(java.lang.String);
method public final android.os.IBinder onBind(android.content.Intent);
@@ -37094,6 +37125,22 @@
package android.service.notification {
+ public final class Adjustment implements android.os.Parcelable {
+ ctor public Adjustment(java.lang.String, java.lang.String, int, android.os.Bundle, java.lang.CharSequence, android.net.Uri);
+ ctor protected Adjustment(android.os.Parcel);
+ method public int describeContents();
+ method public java.lang.CharSequence getExplanation();
+ method public int getImportance();
+ method public java.lang.String getKey();
+ method public java.lang.String getPackage();
+ method public android.net.Uri getReference();
+ method public android.os.Bundle getSignals();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
+ field public static final java.lang.String GROUP_KEY_OVERRIDE_KEY = "group_key_override";
+ field public static final java.lang.String NEEDS_AUTOGROUPING_KEY = "autogroup_needed";
+ }
+
public class Condition implements android.os.Parcelable {
ctor public Condition(android.net.Uri, java.lang.String, int);
ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
@@ -37154,6 +37201,7 @@
method public android.os.IBinder onBind(android.content.Intent);
method public void onInterruptionFilterChanged(int);
method public void onListenerConnected();
+ method public void onListenerDisconnected();
method public void onListenerHintsChanged(int);
method public void onNotificationPosted(android.service.notification.StatusBarNotification);
method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
@@ -37168,7 +37216,9 @@
method public final void setNotificationsShown(java.lang.String[]);
method public final void setOnNotificationPostedTrim(int);
method public void unregisterAsSystemService() throws android.os.RemoteException;
+ field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
+ field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
field public static final int INTERRUPTION_FILTER_ALARMS = 4; // 0x4
field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
@@ -37186,6 +37236,7 @@
method public int getImportance();
method public java.lang.CharSequence getImportanceExplanation();
method public java.lang.String getKey();
+ method public java.lang.String getOverrideGroupKey();
method public int getRank();
method public int getSuppressedVisualEffects();
method public boolean isAmbient();
@@ -37209,11 +37260,12 @@
public abstract class NotificationRankerService extends android.service.notification.NotificationListenerService {
ctor public NotificationRankerService();
- method public final void adjustImportance(java.lang.String, android.service.notification.NotificationRankerService.Adjustment);
+ method public final void adjustNotification(android.service.notification.Adjustment);
+ method public final void adjustNotifications(java.util.List<android.service.notification.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.NotificationRankerService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+ method public abstract android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
method public void onNotificationRemoved(java.lang.String, long, int);
method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
field public static final int REASON_APP_CANCEL = 8; // 0x8
@@ -37230,14 +37282,11 @@
field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
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_UNAUTOBUNDLED = 16; // 0x10
field public static final int REASON_USER_STOPPED = 6; // 0x6
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationRankerService";
}
- public class NotificationRankerService.Adjustment {
- ctor public NotificationRankerService.Adjustment(int, java.lang.CharSequence, android.net.Uri);
- }
-
public class StatusBarNotification implements android.os.Parcelable {
ctor public StatusBarNotification(java.lang.String, java.lang.String, int, java.lang.String, int, int, int, android.app.Notification, android.os.UserHandle, long);
ctor public StatusBarNotification(android.os.Parcel);
@@ -37247,13 +37296,16 @@
method public int getId();
method public java.lang.String getKey();
method public android.app.Notification getNotification();
+ method public java.lang.String getOverrideGroupKey();
method public java.lang.String getPackageName();
method public long getPostTime();
method public java.lang.String getTag();
method public android.os.UserHandle getUser();
method public deprecated int getUserId();
method public boolean isClearable();
+ method public boolean isGroup();
method public boolean isOngoing();
+ method public void setOverrideGroupKey(java.lang.String);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.notification.StatusBarNotification> CREATOR;
}
@@ -37322,7 +37374,7 @@
method public void onClick();
method public void onStartListening();
method public void onStopListening();
- method public int onTileAdded();
+ method public void onTileAdded();
method public void onTileRemoved();
method public static final void requestListeningState(android.content.Context, android.content.ComponentName);
method public final void setStatusIcon(android.graphics.drawable.Icon, java.lang.String);
@@ -37331,8 +37383,7 @@
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
+ field public static final java.lang.String META_DATA_ACTIVE_TILE = "android.service.quicksettings.ACTIVE_TILE";
}
}
@@ -49535,21 +49586,21 @@
ctor public DatePicker(android.content.Context, android.util.AttributeSet);
ctor public DatePicker(android.content.Context, android.util.AttributeSet, int);
ctor public DatePicker(android.content.Context, android.util.AttributeSet, int, int);
- method public android.widget.CalendarView getCalendarView();
- method public boolean getCalendarViewShown();
+ method public deprecated android.widget.CalendarView getCalendarView();
+ method public deprecated boolean getCalendarViewShown();
method public int getDayOfMonth();
method public int getFirstDayOfWeek();
method public long getMaxDate();
method public long getMinDate();
method public int getMonth();
- method public boolean getSpinnersShown();
+ method public deprecated boolean getSpinnersShown();
method public int getYear();
method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener);
- method public void setCalendarViewShown(boolean);
+ method public deprecated void setCalendarViewShown(boolean);
method public void setFirstDayOfWeek(int);
method public void setMaxDate(long);
method public void setMinDate(long);
- method public void setSpinnersShown(boolean);
+ method public deprecated void setSpinnersShown(boolean);
method public void updateDate(int, int, int);
}
@@ -53122,6 +53173,9 @@
method public int compareTo(java.lang.Boolean);
method public static boolean getBoolean(java.lang.String);
method public static int hashCode(boolean);
+ method public static boolean logicalAnd(boolean, boolean);
+ method public static boolean logicalOr(boolean, boolean);
+ method public static boolean logicalXor(boolean, boolean);
method public static boolean parseBoolean(java.lang.String);
method public static java.lang.String toString(boolean);
method public static java.lang.Boolean valueOf(boolean);
@@ -54085,6 +54139,8 @@
method public static float abs(float);
method public static double abs(double);
method public static double acos(double);
+ method public static int addExact(int, int);
+ method public static long addExact(long, long);
method public static double asin(double);
method public static double atan(double);
method public static double atan2(double, double);
@@ -54094,12 +54150,20 @@
method public static float copySign(float, float);
method public static double cos(double);
method public static double cosh(double);
+ method public static int decrementExact(int);
+ method public static long decrementExact(long);
method public static double exp(double);
method public static double expm1(double);
method public static double floor(double);
+ method public static int floorDiv(int, int);
+ method public static long floorDiv(long, long);
+ method public static int floorMod(int, int);
+ method public static long floorMod(long, long);
method public static int getExponent(float);
method public static int getExponent(double);
method public static double hypot(double, double);
+ method public static int incrementExact(int);
+ method public static long incrementExact(long);
method public static double log(double);
method public static double log10(double);
method public static double log1p(double);
@@ -54111,8 +54175,14 @@
method public static long min(long, long);
method public static float min(float, float);
method public static double min(double, double);
+ method public static int multiplyExact(int, int);
+ method public static long multiplyExact(long, long);
+ method public static int negateExact(int);
+ method public static long negateExact(long);
method public static double nextAfter(double, double);
method public static float nextAfter(float, double);
+ method public static double nextDown(double);
+ method public static float nextDown(float);
method public static double nextUp(double);
method public static float nextUp(float);
method public static double pow(double, double);
@@ -54127,9 +54197,12 @@
method public static double sin(double);
method public static double sinh(double);
method public static double sqrt(double);
+ method public static int subtractExact(int, int);
+ method public static long subtractExact(long, long);
method public static double tan(double);
method public static double tanh(double);
method public static double toDegrees(double);
+ method public static int toIntExact(long);
method public static double toRadians(double);
method public static double ulp(double);
method public static float ulp(float);
@@ -54413,6 +54486,8 @@
method public static float abs(float);
method public static double abs(double);
method public static double acos(double);
+ method public static int addExact(int, int);
+ method public static long addExact(long, long);
method public static double asin(double);
method public static double atan(double);
method public static double atan2(double, double);
@@ -54425,6 +54500,10 @@
method public static double exp(double);
method public static double expm1(double);
method public static double floor(double);
+ method public static int floorDiv(int, int);
+ method public static long floorDiv(long, long);
+ method public static int floorMod(int, int);
+ method public static long floorMod(long, long);
method public static int getExponent(float);
method public static int getExponent(double);
method public static double hypot(double, double);
@@ -54439,8 +54518,12 @@
method public static long min(long, long);
method public static float min(float, float);
method public static double min(double, double);
+ method public static int multiplyExact(int, int);
+ method public static long multiplyExact(long, long);
method public static double nextAfter(double, double);
method public static float nextAfter(float, double);
+ method public static double nextDown(double);
+ method public static float nextDown(float);
method public static double nextUp(double);
method public static float nextUp(float);
method public static double pow(double, double);
@@ -54455,9 +54538,12 @@
method public static double sin(double);
method public static double sinh(double);
method public static double sqrt(double);
+ method public static int subtractExact(int, int);
+ method public static long subtractExact(long, long);
method public static double tan(double);
method public static double tanh(double);
method public static double toDegrees(double);
+ method public static int toIntExact(long);
method public static double toRadians(double);
method public static double ulp(double);
method public static float ulp(float);
@@ -55015,7 +55101,6 @@
public final class Method extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
method public boolean equals(java.lang.Object);
method public A getAnnotation(java.lang.Class<A>);
- method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public java.lang.Class<?> getDeclaringClass();
method public java.lang.Object getDefaultValue();
method public java.lang.Class<?>[] getExceptionTypes();
@@ -55029,7 +55114,6 @@
method public java.lang.Class<?> getReturnType();
method public java.lang.reflect.TypeVariable<java.lang.reflect.Method>[] getTypeParameters();
method public java.lang.Object invoke(java.lang.Object, java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
- method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
method public boolean isBridge();
method public boolean isDefault();
method public boolean isSynthetic();
@@ -60505,6 +60589,14 @@
method public static int hashCode(float[]);
method public static int hashCode(double[]);
method public static int hashCode(java.lang.Object[]);
+ method public static void parallelPrefix(T[], java.util.function.BinaryOperator<T>);
+ method public static void parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>);
+ method public static void parallelPrefix(long[], java.util.function.LongBinaryOperator);
+ method public static void parallelPrefix(long[], int, int, java.util.function.LongBinaryOperator);
+ method public static void parallelPrefix(double[], java.util.function.DoubleBinaryOperator);
+ method public static void parallelPrefix(double[], int, int, java.util.function.DoubleBinaryOperator);
+ method public static void parallelPrefix(int[], java.util.function.IntBinaryOperator);
+ method public static void parallelPrefix(int[], int, int, java.util.function.IntBinaryOperator);
method public static void parallelSetAll(T[], java.util.function.IntFunction<? extends T>);
method public static void parallelSetAll(int[], java.util.function.IntUnaryOperator);
method public static void parallelSetAll(long[], java.util.function.IntToLongFunction);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 03cf8b0..95734c1 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -82,6 +82,67 @@
}
+package android.location {
+
+ public final class GnssMeasurement implements android.os.Parcelable {
+ field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+ }
+
+ public final class GnssMeasurementsEvent implements android.os.Parcelable {
+ 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
+ }
+
+ public final class GnssNavigationMessageEvent implements android.os.Parcelable {
+ ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
+ method public int describeContents();
+ 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_GNSS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+ field public static final int STATUS_READY = 1; // 0x1
+ }
+
+ public static abstract class GnssNavigationMessageEvent.Callback {
+ ctor public GnssNavigationMessageEvent.Callback();
+ method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
+ method public void onStatusChanged(int);
+ }
+
+ public abstract interface GnssNmeaListener {
+ method public abstract void onNmeaReceived(long, java.lang.String);
+ }
+
+ public final class GnssStatus {
+ method public int getNumSatellites();
+ method public boolean hasAlmanac(int);
+ method public boolean hasEphemeris(int);
+ }
+
+ public abstract class GnssStatusCallback {
+ ctor public GnssStatusCallback();
+ method public void onFirstFix(int);
+ method public void onSatelliteStatusChanged(android.location.GnssStatus);
+ method public void onStarted();
+ method public void onStopped();
+ }
+
+ public class LocationManager {
+ method public boolean addNmeaListener(android.location.GnssNmeaListener);
+ method public boolean addNmeaListener(android.location.GnssNmeaListener, 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);
+ method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
+ method public void removeNmeaListener(android.location.GnssNmeaListener);
+ method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
+ method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
+ }
+
+}
+
package android.media {
public final class AudioFormat implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 3a20a04..caf3231 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3578,6 +3578,7 @@
method public final deprecated void removeDialog(int);
method public void reportFullyDrawn();
method public android.view.DropPermissions requestDropPermissions(android.view.DragEvent);
+ method public final void requestKeyboardShortcutsHelper();
method public final void requestPermissions(java.lang.String[], int);
method public boolean requestVisibleBehind(boolean);
method public final boolean requestWindowFeature(int);
@@ -4915,6 +4916,7 @@
field public static final int DEFAULT_LIGHTS = 4; // 0x4
field public static final int DEFAULT_SOUND = 1; // 0x1
field public static final int DEFAULT_VIBRATE = 2; // 0x2
+ field public static final java.lang.String EXTRA_ALLOW_GENERATED_REPLIES = "android.allowGeneratedReplies";
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";
@@ -4923,12 +4925,14 @@
field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon";
field public static final java.lang.String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big";
field public static final java.lang.String EXTRA_MEDIA_SESSION = "android.mediaSession";
+ field public static final java.lang.String EXTRA_MESSAGES = "android.messages";
field public static final java.lang.String EXTRA_PEOPLE = "android.people";
field public static final java.lang.String EXTRA_PICTURE = "android.picture";
field public static final java.lang.String EXTRA_PROGRESS = "android.progress";
field public static final java.lang.String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
field public static final java.lang.String EXTRA_PROGRESS_MAX = "android.progressMax";
field public static final java.lang.String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory";
+ field public static final java.lang.String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
field public static final java.lang.String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
field public static final java.lang.String EXTRA_SHOW_WHEN = "android.showWhen";
field public static final java.lang.String EXTRA_SMALL_ICON = "android.icon";
@@ -4937,6 +4941,7 @@
field public static final java.lang.String EXTRA_TEMPLATE = "android.template";
field public static final java.lang.String EXTRA_TEXT = "android.text";
field public static final java.lang.String EXTRA_TEXT_LINES = "android.textLines";
+ field public static final java.lang.String EXTRA_THREAD_TITLE = "android.threadTitle";
field public static final java.lang.String EXTRA_TITLE = "android.title";
field public static final java.lang.String EXTRA_TITLE_BIG = "android.title.big";
field public static final int FLAG_AUTO_CANCEL = 16; // 0x10
@@ -5026,11 +5031,13 @@
method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Builder);
method public java.lang.CharSequence getCancelLabel();
method public java.lang.CharSequence getConfirmLabel();
+ method public boolean getHintContentIntentLaunchesActivity();
method public java.lang.CharSequence getInProgressLabel();
method public boolean isAvailableOffline();
method public android.app.Notification.Action.WearableExtender setAvailableOffline(boolean);
method public android.app.Notification.Action.WearableExtender setCancelLabel(java.lang.CharSequence);
method public android.app.Notification.Action.WearableExtender setConfirmLabel(java.lang.CharSequence);
+ method public android.app.Notification.Action.WearableExtender setHintContentIntentLaunchesActivity(boolean);
method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence);
}
@@ -5174,6 +5181,32 @@
method public android.app.Notification.MediaStyle setShowActionsInCompactView(int...);
}
+ public static class Notification.MessagingStyle extends android.app.Notification.Style {
+ ctor public Notification.MessagingStyle(java.lang.CharSequence);
+ method public android.app.Notification.MessagingStyle addMessage(java.lang.CharSequence, long, java.lang.CharSequence);
+ method public android.app.Notification.MessagingStyle addMessage(android.app.Notification.MessagingStyle.Message);
+ method public boolean getAllowGeneratedReplies();
+ method public java.lang.CharSequence getConversationTitle();
+ method public java.util.List<android.app.Notification.MessagingStyle.Message> getMessages();
+ method public java.lang.CharSequence getUserDisplayName();
+ method public android.app.Notification.MessagingStyle setAllowGeneratedReplies(boolean);
+ method public android.app.Notification.MessagingStyle setConversationTitle(java.lang.CharSequence);
+ field public static final int MAXIMUM_RETAINED_MESSAGES = 25; // 0x19
+ }
+
+ public static final class Notification.MessagingStyle.Message implements android.os.Parcelable {
+ ctor public Notification.MessagingStyle.Message(java.lang.CharSequence, long, java.lang.CharSequence);
+ method public int describeContents();
+ method public java.lang.String getDataMimeType();
+ method public android.net.Uri getDataUri();
+ method public java.lang.CharSequence getSender();
+ method public java.lang.CharSequence getText();
+ method public long getTimestamp();
+ method public android.app.Notification.MessagingStyle.Message setData(java.lang.String, android.net.Uri);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.Notification.MessagingStyle.Message> CREATOR;
+ }
+
public static abstract class Notification.Style {
ctor public Notification.Style();
method public android.app.Notification build();
@@ -5207,6 +5240,7 @@
method public android.app.PendingIntent getDisplayIntent();
method public int getGravity();
method public boolean getHintAvoidBackgroundClipping();
+ method public boolean getHintContentIntentLaunchesActivity();
method public boolean getHintHideIcon();
method public int getHintScreenTimeout();
method public boolean getHintShowBackgroundOnly();
@@ -5222,6 +5256,7 @@
method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent);
method public android.app.Notification.WearableExtender setGravity(int);
method public android.app.Notification.WearableExtender setHintAvoidBackgroundClipping(boolean);
+ method public android.app.Notification.WearableExtender setHintContentIntentLaunchesActivity(boolean);
method public android.app.Notification.WearableExtender setHintHideIcon(boolean);
method public android.app.Notification.WearableExtender setHintScreenTimeout(int);
method public android.app.Notification.WearableExtender setHintShowBackgroundOnly(boolean);
@@ -7673,8 +7708,6 @@
method public void setExtras(android.os.PersistableBundle);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.ClipDescription> CREATOR;
- field public static final java.lang.String EXTRA_TARGET_COMPONENT_NAME = "android.content.extra.TARGET_COMPONENT_NAME";
- field public static final java.lang.String EXTRA_USER_SERIAL_NUMBER = "android.content.extra.USER_SERIAL_NUMBER";
field public static final java.lang.String MIMETYPE_TEXT_HTML = "text/html";
field public static final java.lang.String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent";
field public static final java.lang.String MIMETYPE_TEXT_PLAIN = "text/plain";
@@ -8660,6 +8693,7 @@
field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
field public static final java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
field public static final java.lang.String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER = "android.intent.extra.CHOOSER_REFINEMENT_INTENT_SENDER";
+ field public static final java.lang.String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER";
field public static final java.lang.String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED";
@@ -8671,6 +8705,7 @@
field public static final int EXTRA_DOCK_STATE_UNDOCKED = 0; // 0x0
field public static final java.lang.String EXTRA_DONT_KILL_APP = "android.intent.extra.DONT_KILL_APP";
field public static final java.lang.String EXTRA_EMAIL = "android.intent.extra.EMAIL";
+ field public static final java.lang.String EXTRA_EXCLUDE_COMPONENTS = "android.intent.extra.EXCLUDE_COMPONENTS";
field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
field public static final java.lang.String EXTRA_INDEX = "android.intent.extra.INDEX";
field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
@@ -9472,9 +9507,10 @@
public class LauncherApps {
method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
- method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo, android.os.UserHandle);
- method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
- method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
+ method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo);
+ method public android.os.ParcelFileDescriptor getShortcutIconFd(java.lang.String, java.lang.String, android.os.UserHandle);
+ method public int getShortcutIconResId(android.content.pm.ShortcutInfo);
+ method public int getShortcutIconResId(java.lang.String, java.lang.String, android.os.UserHandle);
method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
method public boolean hasShortcutHostPermission();
method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
@@ -9486,6 +9522,7 @@
method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
method public boolean startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
+ method public boolean startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle);
method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
}
@@ -9507,6 +9544,7 @@
method public void setChangedSince(long);
method public void setPackage(java.lang.String);
method public void setQueryFlags(int);
+ method public void setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_DYNAMIC = 1; // 0x1
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
field public static final int FLAG_GET_PINNED = 2; // 0x2
@@ -10021,6 +10059,7 @@
method public java.lang.String getPackageName();
method public java.lang.String getText();
method public java.lang.String getTitle();
+ method public android.os.UserHandle getUserHandle();
method public int getWeight();
method public boolean hasIconFile();
method public boolean hasIconResource();
@@ -13901,11 +13940,11 @@
method public abstract void close();
method public abstract android.hardware.camera2.CaptureRequest.Builder createCaptureRequest(int) throws android.hardware.camera2.CameraAccessException;
method public abstract void createCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
- method public abstract void createCaptureSessionByOutputConfiguration(java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+ method public abstract void createCaptureSessionByOutputConfigurations(java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract void createConstrainedHighSpeedCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract android.hardware.camera2.CaptureRequest.Builder createReprocessCaptureRequest(android.hardware.camera2.TotalCaptureResult) throws android.hardware.camera2.CameraAccessException;
method public abstract void createReprocessableCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
- method public abstract void createReprocessableCaptureSessionWithConfigurations(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+ method public abstract void createReprocessableCaptureSessionByConfigurations(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract java.lang.String getId();
field public static final int TEMPLATE_MANUAL = 6; // 0x6
field public static final int TEMPLATE_PREVIEW = 1; // 0x1
@@ -19272,7 +19311,7 @@
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 int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
- field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+ field public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2; // 0x2
field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
field public static final int STATE_BDS_D2_BIT_SYNC = 256; // 0x100
field public static final int STATE_BDS_D2_SUBFRAME_SYNC = 512; // 0x200
@@ -19298,15 +19337,15 @@
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_GNSS_LOCATION_DISABLED = 2; // 0x2
- field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
- field public static final int STATUS_READY = 1; // 0x1
}
public static abstract class GnssMeasurementsEvent.Callback {
ctor public GnssMeasurementsEvent.Callback();
method public void onGnssMeasurementsReceived(android.location.GnssMeasurementsEvent);
method public void onStatusChanged(int);
+ field public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+ field public static final int STATUS_READY = 1; // 0x1
}
public final class GnssNavigationMessage implements android.os.Parcelable {
@@ -19343,36 +19382,24 @@
field public static final int TYPE_UNKNOWN = 0; // 0x0
}
- public final class GnssNavigationMessageEvent implements android.os.Parcelable {
- ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
- method public int describeContents();
- 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_GNSS_LOCATION_DISABLED = 2; // 0x2
+ public static abstract class GnssNavigationMessage.Callback {
+ ctor public GnssNavigationMessage.Callback();
+ method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessage);
+ method public void onStatusChanged(int);
+ field public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
field public static final int STATUS_READY = 1; // 0x1
}
- public static abstract class GnssNavigationMessageEvent.Callback {
- ctor public GnssNavigationMessageEvent.Callback();
- method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
- method public void onStatusChanged(int);
- }
-
- public abstract interface GnssNmeaListener {
- method public abstract void onNmeaReceived(long, java.lang.String);
- }
-
public final class GnssStatus {
method public float getAzimuthDegrees(int);
method public float getCn0DbHz(int);
method public int getConstellationType(int);
method public float getElevationDegrees(int);
- method public int getNumSatellites();
+ method public int getSatelliteCount();
method public int getSvid(int);
- method public boolean hasAlmanac(int);
- method public boolean hasEphemeris(int);
+ method public boolean hasAlmanacData(int);
+ method public boolean hasEphemerisData(int);
method public boolean usedInFix(int);
field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
field public static final int CONSTELLATION_GALILEO = 6; // 0x6
@@ -19383,15 +19410,15 @@
field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
}
- public abstract class GnssStatusCallback {
- ctor public GnssStatusCallback();
+ public static abstract class GnssStatus.Callback {
+ ctor public GnssStatus.Callback();
method public void onFirstFix(int);
method public void onSatelliteStatusChanged(android.location.GnssStatus);
method public void onStarted();
method public void onStopped();
}
- public final class GpsSatellite {
+ public final deprecated class GpsSatellite {
method public float getAzimuth();
method public float getElevation();
method public int getPrn();
@@ -19401,7 +19428,7 @@
method public boolean usedInFix();
}
- public final class GpsStatus {
+ public final deprecated class GpsStatus {
method public int getMaxSatellites();
method public java.lang.Iterable<android.location.GpsSatellite> getSatellites();
method public int getTimeToFirstFix();
@@ -19411,11 +19438,11 @@
field public static final int GPS_EVENT_STOPPED = 2; // 0x2
}
- public static abstract interface GpsStatus.Listener {
+ public static abstract deprecated interface GpsStatus.Listener {
method public abstract void onGpsStatusChanged(int);
}
- public static abstract interface GpsStatus.NmeaListener {
+ public static abstract deprecated interface GpsStatus.NmeaListener {
method public abstract void onNmeaReceived(long, java.lang.String);
}
@@ -19477,8 +19504,8 @@
public class LocationManager {
method public deprecated boolean addGpsStatusListener(android.location.GpsStatus.Listener);
method public deprecated boolean addNmeaListener(android.location.GpsStatus.NmeaListener);
- method public boolean addNmeaListener(android.location.GnssNmeaListener);
- method public boolean addNmeaListener(android.location.GnssNmeaListener, android.os.Handler);
+ method public boolean addNmeaListener(android.location.OnNmeaMessageListener);
+ method public boolean addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler);
method public void addProximityAlert(double, double, float, long, android.app.PendingIntent);
method public void addTestProvider(java.lang.String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
method public void clearTestProviderEnabled(java.lang.String);
@@ -19495,13 +19522,13 @@
method public boolean isProviderEnabled(java.lang.String);
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);
- method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
+ method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
+ method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback, android.os.Handler);
+ method public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback);
+ method public boolean registerGnssStatusCallback(android.location.GnssStatus.Callback, android.os.Handler);
method public deprecated void removeGpsStatusListener(android.location.GpsStatus.Listener);
method public deprecated void removeNmeaListener(android.location.GpsStatus.NmeaListener);
- method public void removeNmeaListener(android.location.GnssNmeaListener);
+ method public void removeNmeaListener(android.location.OnNmeaMessageListener);
method public void removeProximityAlert(android.app.PendingIntent);
method public void removeTestProvider(java.lang.String);
method public void removeUpdates(android.location.LocationListener);
@@ -19520,8 +19547,8 @@
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 unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
- method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
- method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
+ method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessage.Callback);
+ method public void unregisterGnssStatusCallback(android.location.GnssStatus.Callback);
field public static final java.lang.String GPS_PROVIDER = "gps";
field public static final java.lang.String KEY_LOCATION_CHANGED = "location";
field public static final java.lang.String KEY_PROVIDER_ENABLED = "providerEnabled";
@@ -19550,6 +19577,10 @@
field public static final int TEMPORARILY_UNAVAILABLE = 1; // 0x1
}
+ public abstract interface OnNmeaMessageListener {
+ method public abstract void onNmeaMessage(java.lang.String, long);
+ }
+
public abstract class SettingInjectorService extends android.app.Service {
ctor public SettingInjectorService(java.lang.String);
method public final android.os.IBinder onBind(android.content.Intent);
@@ -34760,6 +34791,7 @@
method public android.os.IBinder onBind(android.content.Intent);
method public void onInterruptionFilterChanged(int);
method public void onListenerConnected();
+ method public void onListenerDisconnected();
method public void onListenerHintsChanged(int);
method public void onNotificationPosted(android.service.notification.StatusBarNotification);
method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
@@ -34771,7 +34803,9 @@
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 int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
+ field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
field public static final int INTERRUPTION_FILTER_ALARMS = 4; // 0x4
field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
@@ -34787,6 +34821,7 @@
method public int getImportance();
method public java.lang.CharSequence getImportanceExplanation();
method public java.lang.String getKey();
+ method public java.lang.String getOverrideGroupKey();
method public int getRank();
method public int getSuppressedVisualEffects();
method public boolean isAmbient();
@@ -34817,13 +34852,16 @@
method public int getId();
method public java.lang.String getKey();
method public android.app.Notification getNotification();
+ method public java.lang.String getOverrideGroupKey();
method public java.lang.String getPackageName();
method public long getPostTime();
method public java.lang.String getTag();
method public android.os.UserHandle getUser();
method public deprecated int getUserId();
method public boolean isClearable();
+ method public boolean isGroup();
method public boolean isOngoing();
+ method public void setOverrideGroupKey(java.lang.String);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.notification.StatusBarNotification> CREATOR;
}
@@ -34859,7 +34897,7 @@
method public void onClick();
method public void onStartListening();
method public void onStopListening();
- method public int onTileAdded();
+ method public void onTileAdded();
method public void onTileRemoved();
method public static final void requestListeningState(android.content.Context, android.content.ComponentName);
method public final void showDialog(android.app.Dialog);
@@ -34867,8 +34905,7 @@
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
+ field public static final java.lang.String META_DATA_ACTIVE_TILE = "android.service.quicksettings.ACTIVE_TILE";
}
}
@@ -46512,21 +46549,21 @@
ctor public DatePicker(android.content.Context, android.util.AttributeSet);
ctor public DatePicker(android.content.Context, android.util.AttributeSet, int);
ctor public DatePicker(android.content.Context, android.util.AttributeSet, int, int);
- method public android.widget.CalendarView getCalendarView();
- method public boolean getCalendarViewShown();
+ method public deprecated android.widget.CalendarView getCalendarView();
+ method public deprecated boolean getCalendarViewShown();
method public int getDayOfMonth();
method public int getFirstDayOfWeek();
method public long getMaxDate();
method public long getMinDate();
method public int getMonth();
- method public boolean getSpinnersShown();
+ method public deprecated boolean getSpinnersShown();
method public int getYear();
method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener);
- method public void setCalendarViewShown(boolean);
+ method public deprecated void setCalendarViewShown(boolean);
method public void setFirstDayOfWeek(int);
method public void setMaxDate(long);
method public void setMinDate(long);
- method public void setSpinnersShown(boolean);
+ method public deprecated void setSpinnersShown(boolean);
method public void updateDate(int, int, int);
}
@@ -50100,6 +50137,9 @@
method public int compareTo(java.lang.Boolean);
method public static boolean getBoolean(java.lang.String);
method public static int hashCode(boolean);
+ method public static boolean logicalAnd(boolean, boolean);
+ method public static boolean logicalOr(boolean, boolean);
+ method public static boolean logicalXor(boolean, boolean);
method public static boolean parseBoolean(java.lang.String);
method public static java.lang.String toString(boolean);
method public static java.lang.Boolean valueOf(boolean);
@@ -51063,6 +51103,8 @@
method public static float abs(float);
method public static double abs(double);
method public static double acos(double);
+ method public static int addExact(int, int);
+ method public static long addExact(long, long);
method public static double asin(double);
method public static double atan(double);
method public static double atan2(double, double);
@@ -51072,12 +51114,20 @@
method public static float copySign(float, float);
method public static double cos(double);
method public static double cosh(double);
+ method public static int decrementExact(int);
+ method public static long decrementExact(long);
method public static double exp(double);
method public static double expm1(double);
method public static double floor(double);
+ method public static int floorDiv(int, int);
+ method public static long floorDiv(long, long);
+ method public static int floorMod(int, int);
+ method public static long floorMod(long, long);
method public static int getExponent(float);
method public static int getExponent(double);
method public static double hypot(double, double);
+ method public static int incrementExact(int);
+ method public static long incrementExact(long);
method public static double log(double);
method public static double log10(double);
method public static double log1p(double);
@@ -51089,8 +51139,14 @@
method public static long min(long, long);
method public static float min(float, float);
method public static double min(double, double);
+ method public static int multiplyExact(int, int);
+ method public static long multiplyExact(long, long);
+ method public static int negateExact(int);
+ method public static long negateExact(long);
method public static double nextAfter(double, double);
method public static float nextAfter(float, double);
+ method public static double nextDown(double);
+ method public static float nextDown(float);
method public static double nextUp(double);
method public static float nextUp(float);
method public static double pow(double, double);
@@ -51105,9 +51161,12 @@
method public static double sin(double);
method public static double sinh(double);
method public static double sqrt(double);
+ method public static int subtractExact(int, int);
+ method public static long subtractExact(long, long);
method public static double tan(double);
method public static double tanh(double);
method public static double toDegrees(double);
+ method public static int toIntExact(long);
method public static double toRadians(double);
method public static double ulp(double);
method public static float ulp(float);
@@ -51391,6 +51450,8 @@
method public static float abs(float);
method public static double abs(double);
method public static double acos(double);
+ method public static int addExact(int, int);
+ method public static long addExact(long, long);
method public static double asin(double);
method public static double atan(double);
method public static double atan2(double, double);
@@ -51403,6 +51464,10 @@
method public static double exp(double);
method public static double expm1(double);
method public static double floor(double);
+ method public static int floorDiv(int, int);
+ method public static long floorDiv(long, long);
+ method public static int floorMod(int, int);
+ method public static long floorMod(long, long);
method public static int getExponent(float);
method public static int getExponent(double);
method public static double hypot(double, double);
@@ -51417,8 +51482,12 @@
method public static long min(long, long);
method public static float min(float, float);
method public static double min(double, double);
+ method public static int multiplyExact(int, int);
+ method public static long multiplyExact(long, long);
method public static double nextAfter(double, double);
method public static float nextAfter(float, double);
+ method public static double nextDown(double);
+ method public static float nextDown(float);
method public static double nextUp(double);
method public static float nextUp(float);
method public static double pow(double, double);
@@ -51433,9 +51502,12 @@
method public static double sin(double);
method public static double sinh(double);
method public static double sqrt(double);
+ method public static int subtractExact(int, int);
+ method public static long subtractExact(long, long);
method public static double tan(double);
method public static double tanh(double);
method public static double toDegrees(double);
+ method public static int toIntExact(long);
method public static double toRadians(double);
method public static double ulp(double);
method public static float ulp(float);
@@ -51993,7 +52065,6 @@
public final class Method extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
method public boolean equals(java.lang.Object);
method public A getAnnotation(java.lang.Class<A>);
- method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public java.lang.Class<?> getDeclaringClass();
method public java.lang.Object getDefaultValue();
method public java.lang.Class<?>[] getExceptionTypes();
@@ -52007,7 +52078,6 @@
method public java.lang.Class<?> getReturnType();
method public java.lang.reflect.TypeVariable<java.lang.reflect.Method>[] getTypeParameters();
method public java.lang.Object invoke(java.lang.Object, java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
- method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
method public boolean isBridge();
method public boolean isDefault();
method public boolean isSynthetic();
@@ -57483,6 +57553,14 @@
method public static int hashCode(float[]);
method public static int hashCode(double[]);
method public static int hashCode(java.lang.Object[]);
+ method public static void parallelPrefix(T[], java.util.function.BinaryOperator<T>);
+ method public static void parallelPrefix(T[], int, int, java.util.function.BinaryOperator<T>);
+ method public static void parallelPrefix(long[], java.util.function.LongBinaryOperator);
+ method public static void parallelPrefix(long[], int, int, java.util.function.LongBinaryOperator);
+ method public static void parallelPrefix(double[], java.util.function.DoubleBinaryOperator);
+ method public static void parallelPrefix(double[], int, int, java.util.function.DoubleBinaryOperator);
+ method public static void parallelPrefix(int[], java.util.function.IntBinaryOperator);
+ method public static void parallelPrefix(int[], int, int, java.util.function.IntBinaryOperator);
method public static void parallelSetAll(T[], java.util.function.IntFunction<? extends T>);
method public static void parallelSetAll(int[], java.util.function.IntUnaryOperator);
method public static void parallelSetAll(long[], java.util.function.IntToLongFunction);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 3f16bca..8c6abdc 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -84,6 +84,67 @@
}
+package android.location {
+
+ public final class GnssMeasurement implements android.os.Parcelable {
+ field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+ }
+
+ public final class GnssMeasurementsEvent implements android.os.Parcelable {
+ 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
+ }
+
+ public final class GnssNavigationMessageEvent implements android.os.Parcelable {
+ ctor public GnssNavigationMessageEvent(android.location.GnssNavigationMessage);
+ method public int describeContents();
+ 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_GNSS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
+ field public static final int STATUS_READY = 1; // 0x1
+ }
+
+ public static abstract class GnssNavigationMessageEvent.Callback {
+ ctor public GnssNavigationMessageEvent.Callback();
+ method public void onGnssNavigationMessageReceived(android.location.GnssNavigationMessageEvent);
+ method public void onStatusChanged(int);
+ }
+
+ public abstract interface GnssNmeaListener {
+ method public abstract void onNmeaReceived(long, java.lang.String);
+ }
+
+ public final class GnssStatus {
+ method public int getNumSatellites();
+ method public boolean hasAlmanac(int);
+ method public boolean hasEphemeris(int);
+ }
+
+ public abstract class GnssStatusCallback {
+ ctor public GnssStatusCallback();
+ method public void onFirstFix(int);
+ method public void onSatelliteStatusChanged(android.location.GnssStatus);
+ method public void onStarted();
+ method public void onStopped();
+ }
+
+ public class LocationManager {
+ method public boolean addNmeaListener(android.location.GnssNmeaListener);
+ method public boolean addNmeaListener(android.location.GnssNmeaListener, 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);
+ method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback, android.os.Handler);
+ method public void removeNmeaListener(android.location.GnssNmeaListener);
+ method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
+ method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
+ }
+
+}
+
package android.media {
public final class AudioFormat implements android.os.Parcelable {
diff --git a/cmds/sm/src/com/android/commands/sm/Sm.java b/cmds/sm/src/com/android/commands/sm/Sm.java
index 0e674c8..d527ad7 100644
--- a/cmds/sm/src/com/android/commands/sm/Sm.java
+++ b/cmds/sm/src/com/android/commands/sm/Sm.java
@@ -74,6 +74,8 @@
runGetPrimaryStorageUuid();
} else if ("set-force-adoptable".equals(op)) {
runSetForceAdoptable();
+ } else if ("set-sdcardfs".equals(op)) {
+ runSetSdcardfs();
} else if ("partition".equals(op)) {
runPartition();
} else if ("mount".equals(op)) {
@@ -141,6 +143,22 @@
StorageManager.DEBUG_FORCE_ADOPTABLE);
}
+ public void runSetSdcardfs() throws RemoteException {
+ final int mask = StorageManager.DEBUG_SDCARDFS_FORCE_ON
+ | StorageManager.DEBUG_SDCARDFS_FORCE_OFF;
+ switch (nextArg()) {
+ case "on":
+ mSm.setDebugFlags(StorageManager.DEBUG_SDCARDFS_FORCE_ON, mask);
+ break;
+ case "off":
+ mSm.setDebugFlags(StorageManager.DEBUG_SDCARDFS_FORCE_OFF, mask);
+ break;
+ case "default":
+ mSm.setDebugFlags(0, mask);
+ break;
+ }
+ }
+
public void runSetEmulateFbe() throws RemoteException {
final boolean emulateFbe = Boolean.parseBoolean(nextArg());
mSm.setDebugFlags(emulateFbe ? StorageManager.DEBUG_EMULATE_FBE : 0,
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index bf823f8..56728ad 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -600,11 +600,16 @@
* Dispatch a gesture to the touch screen. Any gestures currently in progress, whether from
* the user, this service, or another service, will be cancelled.
* <p>
+ * The gesture will be dispatched as if it were performed directly on the screen by a user, so
+ * the events may be affected by features such as magnification and explore by touch.
+ * </p>
+ * <p>
* <strong>Note:</strong> In order to dispatch gestures, your service
* must declare the capability by setting the
* {@link android.R.styleable#AccessibilityService_canPerformGestures}
* property in its meta-data. For more information, see
* {@link #SERVICE_META_DATA}.
+ * </p>
*
* @param gesture The gesture to dispatch
* @param callback The object to call back when the status of the gesture is known. If
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 0410a6e..7652766 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1343,20 +1343,21 @@
* {@link #getVoiceInteractor()}.
*/
public void onLocalVoiceInteractionStarted() {
- Log.i(TAG, "onLocalVoiceInteractionStarted! " + getVoiceInteractor());
}
/**
- * Callback to indicate that the local voice interaction has stopped for some
- * reason.
+ * Callback to indicate that the local voice interaction has stopped either
+ * because it was requested through a call to {@link #stopLocalVoiceInteraction()}
+ * or because it was canceled by the user. The previously acquired {@link VoiceInteractor}
+ * is no longer valid after this.
*/
public void onLocalVoiceInteractionStopped() {
- Log.i(TAG, "onLocalVoiceInteractionStopped :( " + getVoiceInteractor());
}
/**
* Request to terminate the current voice interaction that was previously started
- * using {@link #startLocalVoiceInteraction(Bundle)}.
+ * using {@link #startLocalVoiceInteraction(Bundle)}. When the interaction is
+ * terminated, {@link #onLocalVoiceInteractionStopped()} will be called.
*/
public void stopLocalVoiceInteraction() {
try {
@@ -1675,6 +1676,17 @@
public void onProvideAssistContent(AssistContent outContent) {
}
+ /**
+ * Request the Keyboard Shortcuts screen to show up. If it succeeds, this will trigger
+ * {@link #onProvideKeyboardShortcuts} to retrieve the shortcuts for the foreground activity.
+ */
+ public final void requestKeyboardShortcutsHelper() {
+ Intent intent = new Intent(Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS);
+ intent.setComponent(new ComponentName("com.android.systemui",
+ "com.android.systemui.statusbar.KeyboardShortcutsReceiver"));
+ sendBroadcast(intent);
+ }
+
@Override
public void onProvideKeyboardShortcuts(
List<KeyboardShortcutGroup> data, Menu menu, int deviceId) {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 14c4fc6..36e962e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1526,7 +1526,7 @@
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case CREATE_SERVICE:
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
@@ -1541,7 +1541,7 @@
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SERVICE_ARGS:
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStart");
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceStart: " + String.valueOf(msg.obj)));
handleServiceArgs((ServiceArgsData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
@@ -4727,8 +4727,16 @@
if (callbacks != null) {
final int N = callbacks.size();
for (int i=0; i<N; i++) {
- performConfigurationChanged(callbacks.get(i), null, config, null,
- REPORT_TO_ACTIVITY);
+ ComponentCallbacks2 cb = callbacks.get(i);
+ if (cb instanceof Activity) {
+ // If callback is an Activity - call corresponding method to consider override
+ // config and avoid onConfigurationChanged if it hasn't changed.
+ Activity a = (Activity) cb;
+ performConfigurationChangedForActivity(mActivities.get(a.getActivityToken()),
+ config, REPORT_TO_ACTIVITY);
+ } else {
+ performConfigurationChanged(cb, null, config, null, REPORT_TO_ACTIVITY);
+ }
}
}
}
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 7a69c62..ee80ec3 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -25,6 +25,7 @@
import android.content.pm.ParceledListSlice;
import android.net.Uri;
import android.os.Bundle;
+import android.service.notification.Adjustment;
import android.service.notification.Condition;
import android.service.notification.IConditionListener;
import android.service.notification.IConditionProvider;
@@ -80,7 +81,8 @@
void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim);
void setInterruptionFilter(String pkg, int interruptionFilter);
- void setImportanceFromRankerService(in INotificationListener token, String key, int importance, CharSequence explanation);
+ void applyAdjustmentFromRankerService(in INotificationListener token, in Adjustment adjustment);
+ void applyAdjustmentsFromRankerService(in INotificationListener token, in List<Adjustment> adjustments);
ComponentName getEffectsSuppressor();
boolean matchesCallFilter(in Bundle extras);
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index fa67529..496ca6f 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -40,4 +40,9 @@
* Called when we launched an activity that we forced to be resizable.
*/
void onActivityForcedResizable(String packageName, int taskId);
+
+ /**
+ * Callen when we launched an activity that is dismissed the docked stack.
+ */
+ void onActivityDismissingDockedStack();
}
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 13e8e75..4fca69a 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -206,7 +206,7 @@
}
results.putAll(mPerfMetrics);
}
- if (mUiAutomation != null) {
+ if ((mUiAutomation != null) && !mUiAutomation.isDestroyed()) {
mUiAutomation.disconnect();
mUiAutomation = null;
}
@@ -1834,7 +1834,7 @@
}
/**
- * Gets the {@link UiAutomation} instance.
+ * Gets the {@link UiAutomation} instance with no flags set.
* <p>
* <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
* work across application boundaries while the APIs exposed by the instrumentation
@@ -1848,25 +1848,21 @@
* {@link Instrumentation} APIs. Using both APIs at the same time is not
* a mistake by itself but a client has to be aware of the APIs limitations.
* </p>
- * @return The UI automation instance. If none exists, a new one is created with no flags set.
+ * <p>
+ * Equivalent to {@code getUiAutomation(0)}. If a {@link UiAutomation} exists with different
+ * flags, the flags on that instance will be changed, and then it will be returned.
+ * </p>
+ * @return The UI automation instance.
*
* @see UiAutomation
*/
public UiAutomation getUiAutomation() {
- if ((mUiAutomation == null) || (mUiAutomation.isDestroyed())) {
- return getUiAutomation(0);
- }
- return mUiAutomation;
+ return getUiAutomation(0);
}
/**
* Gets the {@link UiAutomation} instance with flags set.
* <p>
- * <strong>Note:</strong> Only one UiAutomation can be obtained. Calling this method
- * twice with different flags will fail unless the UiAutomation obtained in the first call
- * is released with {@link UiAutomation#destroy()}.
- * </p>
- * <p>
* <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
* work across application boundaries while the APIs exposed by the instrumentation
* do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
@@ -1879,6 +1875,10 @@
* {@link Instrumentation} APIs. Using both APIs at the same time is not
* a mistake by itself but a client has to be aware of the APIs limitations.
* </p>
+ * <p>
+ * If a {@link UiAutomation} exists with different flags, the flags on that instance will be
+ * changed, and then it will be returned.
+ * </p>
*
* @param flags The flags to be passed to the UiAutomation, for example
* {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}.
@@ -1888,17 +1888,19 @@
* @see UiAutomation
*/
public UiAutomation getUiAutomation(@UiAutomationFlags int flags) {
+ boolean mustCreateNewAutomation = (mUiAutomation == null) || (mUiAutomation.isDestroyed());
+
if (mUiAutomationConnection != null) {
- if ((mUiAutomation == null) || (mUiAutomation.isDestroyed())) {
+ if (!mustCreateNewAutomation && (mUiAutomation.getFlags() == flags)) {
+ return mUiAutomation;
+ }
+ if (mustCreateNewAutomation) {
mUiAutomation = new UiAutomation(getTargetContext().getMainLooper(),
mUiAutomationConnection);
- mUiAutomation.connect(flags);
} else {
- if (mUiAutomation.getFlags() != flags) {
- throw new RuntimeException(
- "Cannot get a UiAutomation with different flags from the existing one");
- }
+ mUiAutomation.disconnect();
}
+ mUiAutomation.connect(flags);
return mUiAutomation;
}
return null;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 65e9f10..4bf1aa3 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -21,6 +21,7 @@
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;
@@ -496,6 +497,15 @@
*/
public static final int FLAG_GROUP_SUMMARY = 0x00000200;
+ /**
+ * Bit to be bitswise-ored into the {@link #flags} field that should be
+ * set if this notification is the group summary for an auto-group of notifications.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int FLAG_AUTOGROUP_SUMMARY = 0x00000400;
+
public int flags;
/** @hide */
@@ -904,6 +914,34 @@
public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions";
/**
+ * {@link #extras} key: the username to be displayed for all messages sent by the user including
+ * direct replies
+ * {@link android.app.Notification.MessagingStyle} notification.
+ */
+ public static final String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
+
+ /**
+ * {@link #extras} key: a boolean describing whether the platform should automatically
+ * generate possible replies to
+ * {@link android.app.Notification.MessagingStyle.Message} objects provided by a
+ * {@link android.app.Notification.MessagingStyle} notification.
+ */
+ public static final String EXTRA_ALLOW_GENERATED_REPLIES = "android.allowGeneratedReplies";
+
+ /**
+ * {@link #extras} key: a {@link String} to be displayed as the title to a thread represented by
+ * a {@link android.app.Notification.MessagingStyle}
+ */
+ public static final String EXTRA_THREAD_TITLE = "android.threadTitle";
+
+ /**
+ * {@link #extras} key: an array of {@link android.app.Notification.MessagingStyle.Message}
+ * bundles provided by a
+ * {@link android.app.Notification.MessagingStyle} notification.
+ */
+ public static final String EXTRA_MESSAGES = "android.messages";
+
+ /**
* {@link #extras} key: the user that built the notification.
*
* @hide
@@ -1210,6 +1248,7 @@
// Flags bitwise-ored to mFlags
private static final int FLAG_AVAILABLE_OFFLINE = 0x1;
+ private static final int FLAG_HINT_LAUNCHES_ACTIVITY = 1 << 1;
// Default value for flags integer
private static final int DEFAULT_FLAGS = FLAG_AVAILABLE_OFFLINE;
@@ -1372,6 +1411,30 @@
public CharSequence getCancelLabel() {
return mCancelLabel;
}
+
+ /**
+ * Set a hint that this Action will launch an {@link Activity} directly, telling the
+ * platform that it can generate the appropriate transitions.
+ * @param hintLaunchesActivity {@code true} if the content intent will launch
+ * an activity and transitions should be generated, false otherwise.
+ * @return this object for method chaining
+ */
+ public WearableExtender setHintContentIntentLaunchesActivity(
+ boolean hintLaunchesActivity) {
+ setFlag(FLAG_HINT_LAUNCHES_ACTIVITY, hintLaunchesActivity);
+ return this;
+ }
+
+ /**
+ * Get a hint that this Action will launch an {@link Activity} directly, telling the
+ * platform that it can generate the appropriate transitions
+ * @return {@code true} if the content intent will launch an activity and transitions
+ * should be generated, false otherwise. The default value is {@code false} if this was
+ * never set.
+ */
+ public boolean getHintContentIntentLaunchesActivity() {
+ return (mFlags & FLAG_HINT_LAUNCHES_ACTIVITY) != 0;
+ }
}
}
@@ -1892,13 +1955,9 @@
* @hide
*/
public static void addFieldsFromContext(Context context, Notification notification) {
- if (notification.extras.getParcelable(EXTRA_BUILDER_APPLICATION_INFO) == null) {
- notification.extras.putParcelable(EXTRA_BUILDER_APPLICATION_INFO,
- context.getApplicationInfo());
- }
- if (!notification.extras.containsKey(EXTRA_ORIGINATING_USERID)) {
- notification.extras.putInt(EXTRA_ORIGINATING_USERID, context.getUserId());
- }
+ notification.extras.putParcelable(EXTRA_BUILDER_APPLICATION_INFO,
+ context.getApplicationInfo());
+ notification.extras.putInt(EXTRA_ORIGINATING_USERID, context.getUserId());
}
@Override
@@ -2967,12 +3026,13 @@
/**
* @hide
*/
- public void setFlag(int mask, boolean value) {
+ public Builder setFlag(int mask, boolean value) {
if (value) {
mN.flags |= mask;
} else {
mN.flags &= ~mask;
}
+ return this;
}
/**
@@ -3535,7 +3595,8 @@
private static Class<? extends Style> getNotificationStyleClass(String templateClass) {
Class<? extends Style>[] classes = new Class[] {
BigTextStyle.class, BigPictureStyle.class, InboxStyle.class, MediaStyle.class,
- DecoratedCustomViewStyle.class, DecoratedMediaCustomViewStyle.class };
+ DecoratedCustomViewStyle.class, DecoratedMediaCustomViewStyle.class,
+ MessagingStyle.class };
for (Class<? extends Style> innerClass : classes) {
if (templateClass.equals(innerClass.getName())) {
return innerClass;
@@ -4132,6 +4193,350 @@
}
/**
+ * Helper class for generating large-format notifications that include multiple back-and-forth
+ * messages of varying types between any number of people.
+ *
+ * <br>
+ * If the platform does not provide large-format notifications, this method has no effect. The
+ * user will always see the normal notification view.
+ * <br>
+ * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like
+ * so:
+ * <pre class="prettyprint">
+ *
+ * Notification noti = new Notification.Builder()
+ * .setContentTitle("2 new messages wtih " + sender.toString())
+ * .setContentText(subject)
+ * .setSmallIcon(R.drawable.new_message)
+ * .setLargeIcon(aBitmap)
+ * .setStyle(new Notification.MessagingStyle(resources.getString(R.string.reply_name))
+ * .addMessage(messages[0].getText(), messages[0].getTime(), messages[0].getSender())
+ * .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getSender()))
+ * .build();
+ * </pre>
+ */
+ public static class MessagingStyle extends Style {
+
+ /**
+ * The maximum number of messages that will be retained in the Notification itself (the
+ * number displayed is up to the platform).
+ */
+ public static final int MAXIMUM_RETAINED_MESSAGES = 25;
+
+ CharSequence mUserDisplayName;
+ CharSequence mConversationTitle;
+ boolean mAllowGeneratedReplies = true;
+ ArrayList<Message> mMessages = new ArrayList<>();
+
+ MessagingStyle() {
+ }
+
+ /**
+ * @param userDisplayName the name to be displayed for any replies sent by the user before the
+ * posting app reposts the notification with those messages after they've been actually
+ * sent and in previous messages sent by the user added in
+ * {@link #addMessage(Notification.MessagingStyle.Message)}
+ */
+ public MessagingStyle(CharSequence userDisplayName) {
+ mUserDisplayName = userDisplayName;
+ }
+
+ /**
+ * Returns the name to be displayed for any replies sent by the user
+ */
+ public CharSequence getUserDisplayName() {
+ return mUserDisplayName;
+ }
+
+ /**
+ * Set whether the platform should automatically generate possible replies from messages.
+ * @param allowGeneratedReplies {@code true} to allow generated replies, {@code false}
+ * otherwise
+ * @return this object for method chaining
+ * The default value is {@code true}
+ */
+ public MessagingStyle setAllowGeneratedReplies(boolean allowGeneratedReplies) {
+ mAllowGeneratedReplies = allowGeneratedReplies;
+ return this;
+ }
+
+ /**
+ * Return whether the platform should automatically generate possible replies from messages.
+ */
+ public boolean getAllowGeneratedReplies() {
+ return mAllowGeneratedReplies;
+ }
+
+ /**
+ * Sets the title to be displayed on this conversation. This should only be used for
+ * group messaging and left unset for one-on-one conversations.
+ * @param conversationTitle
+ * @return this object for method chaining.
+ */
+ public MessagingStyle setConversationTitle(CharSequence conversationTitle) {
+ mConversationTitle = conversationTitle;
+ return this;
+ }
+
+ /**
+ * Return the title to be displayed on this conversation. Can be <code>null</code> and
+ * should be for one-on-one conversations
+ */
+ public CharSequence getConversationTitle() {
+ return mConversationTitle;
+ }
+
+ /**
+ * Adds a message for display by this notification. Convenience call for a simple
+ * {@link Message} in {@link #addMessage(Notification.MessagingStyle.Message)}.
+ * @param text A {@link CharSequence} to be displayed as the message content
+ * @param timestamp Time at which the message arrived
+ * @param sender A {@link CharSequence} to be used for displaying the name of the
+ * sender. Should be <code>null</code> for messages by the current user, in which case
+ * the platform will insert {@link #getUserDisplayName()}.
+ * Should be unique amongst all individuals in the conversation, and should be
+ * consistent during re-posts of the notification.
+ *
+ * @see Message#Message(CharSequence, long, CharSequence)
+ *
+ * @return this object for method chaining
+ */
+ public MessagingStyle addMessage(CharSequence text, long timestamp, CharSequence sender) {
+ mMessages.add(new Message(text, timestamp, sender));
+ if (mMessages.size() > MAXIMUM_RETAINED_MESSAGES) {
+ mMessages.remove(0);
+ }
+ return this;
+ }
+
+ /**
+ * Adds a {@link Message} for display in this notification.
+ * @param message The {@link Message} to be displayed
+ * @return this object for method chaining
+ */
+ public MessagingStyle addMessage(Message message) {
+ mMessages.add(message);
+ if (mMessages.size() > MAXIMUM_RETAINED_MESSAGES) {
+ mMessages.remove(0);
+ }
+ return this;
+ }
+
+ /**
+ * Gets the list of {@code Message} objects that represent the notification
+ */
+ public List<Message> getMessages() {
+ return mMessages;
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void addExtras(Bundle extras) {
+ super.addExtras(extras);
+ if (mUserDisplayName != null) {
+ extras.putCharSequence(EXTRA_SELF_DISPLAY_NAME, mUserDisplayName);
+ }
+ if (mConversationTitle != null) {
+ extras.putCharSequence(EXTRA_THREAD_TITLE, mConversationTitle);
+ }
+ extras.putBoolean(EXTRA_ALLOW_GENERATED_REPLIES, mAllowGeneratedReplies);
+ if (!mMessages.isEmpty()) {
+ extras.putParcelableArrayList(EXTRA_MESSAGES, mMessages);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ protected void restoreFromExtras(Bundle extras) {
+ super.restoreFromExtras(extras);
+
+ mMessages.clear();
+ mUserDisplayName = extras.getString(EXTRA_SELF_DISPLAY_NAME);
+ mConversationTitle = extras.getString(EXTRA_THREAD_TITLE);
+ mAllowGeneratedReplies = extras.getBoolean(EXTRA_ALLOW_GENERATED_REPLIES,
+ mAllowGeneratedReplies);
+ List<Message> messages = extras.getParcelableArrayList(EXTRA_MESSAGES);
+ if (messages != null) {
+ mMessages.addAll(messages);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public RemoteViews makeBigContentView() {
+ // TODO handset to write implementation
+ RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource());
+
+ return contentView;
+ }
+
+ public static final class Message implements Parcelable {
+
+ private final CharSequence mText;
+ private final long mTimestamp;
+ private final CharSequence mSender;
+
+ private String mDataMimeType;
+ private Uri mDataUri;
+
+ /**
+ * Constructor
+ * @param text A {@link CharSequence} to be displayed as the message content
+ * @param timestamp Time at which the message arrived
+ * @param sender A {@link CharSequence} to be used for displaying the name of the
+ * sender. Should be <code>null</code> for messages by the current user, in which case
+ * the platform will insert {@link MessagingStyle#getUserDisplayName()}.
+ * Should be unique amongst all individuals in the conversation, and should be
+ * consistent during re-posts of the notification.
+ */
+ public Message(CharSequence text, long timestamp, CharSequence sender){
+ mText = text;
+ mTimestamp = timestamp;
+ mSender = sender;
+ }
+
+ /**
+ * Sets a binary blob of data and an associated MIME type for a message. In the case
+ * where the platform doesn't support the MIME type, the original text provided in the
+ * constructor will be used.
+ * @param dataMimeType The MIME type of the content. See
+ * <a href="{@docRoot}notifications/messaging.html"> for the list of supported MIME
+ * types on Android and Android Wear.
+ * @param dataUri The uri containing the content whose type is given by the MIME type.
+ * <p class="note">
+ * <ol>
+ * <li>Notification Listeners including the System UI need permission to access the
+ * data the Uri points to. The recommended ways to do this are:</li>
+ * <li>Store the data in your own ContentProvider, making sure that other apps have
+ * the correct permission to access your provider. The preferred mechanism for
+ * providing access is to use per-URI permissions which are temporary and only
+ * grant access to the receiving application. An easy way to create a
+ * ContentProvider like this is to use the FileProvider helper class.</li>
+ * <li>Use the system MediaStore. The MediaStore is primarily aimed at video, audio
+ * and image MIME types, however beginning with Android 3.0 (API level 11) it can
+ * also store non-media types (see MediaStore.Files for more info). Files can be
+ * inserted into the MediaStore using scanFile() after which a content:// style
+ * Uri suitable for sharing is passed to the provided onScanCompleted() callback.
+ * Note that once added to the system MediaStore the content is accessible to any
+ * app on the device.</li>
+ * </ol>
+ * @return this object for method chaining
+ */
+ public Message setData(String dataMimeType, Uri dataUri) {
+ mDataMimeType = dataMimeType;
+ mDataUri = dataUri;
+ return this;
+ }
+
+ private Message(Parcel in) {
+ if (in.readInt() != 0) {
+ mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ } else {
+ mText = null;
+ }
+ mTimestamp = in.readLong();
+ if (in.readInt() != 0) {
+ mSender = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ } else {
+ mSender = null;
+ }
+ if (in.readInt() != 0) {
+ mDataMimeType = in.readString();
+ }
+ if (in.readInt() != 0) {
+ mDataUri = in.readParcelable(Uri.class.getClassLoader());
+ }
+ }
+
+ /**
+ * Get the text to be used for this message, or the fallback text if a type and content
+ * Uri have been set
+ */
+ public CharSequence getText() {
+ return mText;
+ }
+
+ /**
+ * Get the time at which this message arrived
+ */
+ public long getTimestamp() {
+ return mTimestamp;
+ }
+
+ /**
+ * Get the text used to display the contact's name in the messaging experience
+ */
+ public CharSequence getSender() {
+ return mSender;
+ }
+
+ /**
+ * Get the MIME type of the data pointed to by the Uri
+ */
+ public String getDataMimeType() {
+ return mDataMimeType;
+ }
+
+ /**
+ * Get the the Uri pointing to the content of the message. Can be null, in which case
+ * {@see #getText()} is used.
+ */
+ public Uri getDataUri() {
+ return mDataUri;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ if (mText != null) {
+ out.writeInt(1);
+ TextUtils.writeToParcel(mText, out, flags);
+ } else {
+ out.writeInt(0);
+ }
+ out.writeLong(mTimestamp);
+ if (mSender != null) {
+ out.writeInt(1);
+ TextUtils.writeToParcel(mSender, out, flags);
+ } else {
+ out.writeInt(0);
+ }
+ if (mDataMimeType != null) {
+ out.writeInt(1);
+ out.writeString(mDataMimeType);
+ } else {
+ out.writeInt(0);
+ }
+ if (mDataUri != null) {
+ out.writeInt(1);
+ out.writeParcelable(mDataUri, flags);
+ } else {
+ out.writeInt(0);
+ }
+ }
+
+ public static final Parcelable.Creator<Message> CREATOR =
+ new Parcelable.Creator<Message>() {
+ public Message createFromParcel(Parcel in) {
+ return new Message(in);
+ }
+ public Message[] newArray(int size) {
+ return new Message[size];
+ }
+ };
+ }
+ }
+
+ /**
* Helper class for generating large-format notifications that include a list of (up to 5) strings.
*
* Here's how you'd set the <code>InboxStyle</code> on a notification:
@@ -4869,6 +5274,7 @@
private static final int FLAG_HINT_SHOW_BACKGROUND_ONLY = 1 << 2;
private static final int FLAG_START_SCROLL_BOTTOM = 1 << 3;
private static final int FLAG_HINT_AVOID_BACKGROUND_CLIPPING = 1 << 4;
+ private static final int FLAG_HINT_CONTENT_INTENT_LAUNCHES_ACTIVITY = 1 << 6;
// Default value for flags integer
private static final int DEFAULT_FLAGS = FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE;
@@ -5435,6 +5841,29 @@
return mHintScreenTimeout;
}
+ /**
+ * Set a hint that this notification's content intent will launch an {@link Activity}
+ * directly, telling the platform that it can generate the appropriate transitions.
+ * @param hintContentIntentLaunchesActivity {@code true} if the content intent will launch
+ * an activity and transitions should be generated, false otherwise.
+ * @return this object for method chaining
+ */
+ public WearableExtender setHintContentIntentLaunchesActivity(
+ boolean hintContentIntentLaunchesActivity) {
+ setFlag(FLAG_HINT_CONTENT_INTENT_LAUNCHES_ACTIVITY, hintContentIntentLaunchesActivity);
+ return this;
+ }
+
+ /**
+ * Get a hint that this notification's content intent will launch an {@link Activity}
+ * directly, telling the platform that it can generate the appropriate transitions
+ * @return {@code true} if the content intent will launch an activity and transitions should
+ * be generated, false otherwise. The default value is {@code false} if this was never set.
+ */
+ public boolean getHintContentIntentLaunchesActivity() {
+ return (mFlags & FLAG_HINT_CONTENT_INTENT_LAUNCHES_ACTIVITY) != 0;
+ }
+
private void setFlag(int mask, boolean value) {
if (value) {
mFlags |= mask;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index f15b8fe..96757bb 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2288,6 +2288,23 @@
}
/**
+ * Returns maximum time to lock that applied by all profiles in this user. We do this because we
+ * do not have a separate timeout to lock for work challenge only.
+ *
+ * @hide
+ */
+ public long getMaximumTimeToLockForUserAndProfiles(int userHandle) {
+ if (mService != null) {
+ try {
+ return mService.getMaximumTimeToLockForUserAndProfiles(userHandle);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ return 0;
+ }
+
+ /**
* Make the device lock immediately, as if the lock screen timeout has expired at the point of
* this call.
* <p>
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 1fb2283..6df1038 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -80,6 +80,7 @@
void setMaximumTimeToLock(in ComponentName who, long timeMs, boolean parent);
long getMaximumTimeToLock(in ComponentName who, int userHandle, boolean parent);
+ long getMaximumTimeToLockForUserAndProfiles(int userHandle);
void lockNow(boolean parent);
diff --git a/core/java/android/app/job/JobService.java b/core/java/android/app/job/JobService.java
index 95a8ccf..77307b7 100644
--- a/core/java/android/app/job/JobService.java
+++ b/core/java/android/app/job/JobService.java
@@ -27,6 +27,8 @@
import com.android.internal.annotations.GuardedBy;
+import java.lang.ref.WeakReference;
+
/**
* <p>Entry point for the callback from the {@link android.app.job.JobScheduler}.</p>
* <p>This is the base class that handles asynchronous requests that were previously scheduled. You
@@ -62,15 +64,15 @@
* Identifier for a message that will result in a call to
* {@link #onStartJob(android.app.job.JobParameters)}.
*/
- private final int MSG_EXECUTE_JOB = 0;
+ private static final int MSG_EXECUTE_JOB = 0;
/**
* Message that will result in a call to {@link #onStopJob(android.app.job.JobParameters)}.
*/
- private final int MSG_STOP_JOB = 1;
+ private static final int MSG_STOP_JOB = 1;
/**
* Message that the client has completed execution of this job.
*/
- private final int MSG_JOB_FINISHED = 2;
+ private static final int MSG_JOB_FINISHED = 2;
/** Lock object for {@link #mHandler}. */
private final Object mHandlerLock = new Object();
@@ -82,21 +84,36 @@
@GuardedBy("mHandlerLock")
JobHandler mHandler;
- /** Binder for this service. */
- IJobService mBinder = new IJobService.Stub() {
- @Override
- public void startJob(JobParameters jobParams) {
- ensureHandler();
- Message m = Message.obtain(mHandler, MSG_EXECUTE_JOB, jobParams);
- m.sendToTarget();
+ static final class JobInterface extends IJobService.Stub {
+ final WeakReference<JobService> mService;
+
+ JobInterface(JobService service) {
+ mService = new WeakReference<>(service);
}
+
@Override
- public void stopJob(JobParameters jobParams) {
- ensureHandler();
- Message m = Message.obtain(mHandler, MSG_STOP_JOB, jobParams);
- m.sendToTarget();
+ public void startJob(JobParameters jobParams) throws RemoteException {
+ JobService service = mService.get();
+ if (service != null) {
+ service.ensureHandler();
+ Message m = Message.obtain(service.mHandler, MSG_EXECUTE_JOB, jobParams);
+ m.sendToTarget();
+ }
}
- };
+
+ @Override
+ public void stopJob(JobParameters jobParams) throws RemoteException {
+ JobService service = mService.get();
+ if (service != null) {
+ service.ensureHandler();
+ Message m = Message.obtain(service.mHandler, MSG_STOP_JOB, jobParams);
+ m.sendToTarget();
+ }
+
+ }
+ }
+
+ IJobService mBinder;
/** @hide */
void ensureHandler() {
@@ -194,6 +211,9 @@
/** @hide */
public final IBinder onBind(Intent intent) {
+ if (mBinder == null) {
+ mBinder = new JobInterface(this);
+ }
return mBinder.asBinder();
}
diff --git a/core/java/android/content/ClipDescription.java b/core/java/android/content/ClipDescription.java
index 1b024e2..461d1e0 100644
--- a/core/java/android/content/ClipDescription.java
+++ b/core/java/android/content/ClipDescription.java
@@ -71,6 +71,7 @@
* and {@link ComponentName#flattenToString()} to convert the extra value
* to/from {@link ComponentName}.
* </p>
+ * @hide
*/
public static final String EXTRA_TARGET_COMPONENT_NAME =
"android.content.extra.TARGET_COMPONENT_NAME";
@@ -81,6 +82,7 @@
* <p>
* Type: long
* </p>
+ * @hide
*/
public static final String EXTRA_USER_SERIAL_NUMBER =
"android.content.extra.USER_SERIAL_NUMBER";
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 30f2c94..7e67e8d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1404,6 +1404,16 @@
public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP";
/**
+ * Activity Action: Start the Keyboard Shortcuts Helper screen.
+ * <p>Input: Nothing.
+ * <p>Output: Nothing.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_SHOW_KEYBOARD_SHORTCUTS =
+ "android.intent.action.SHOW_KEYBOARD_SHORTCUTS";
+
+ /**
* Activity Action: Show settings for managing network data usage of a
* specific application. Applications should define an activity that offers
* options to control data usage.
@@ -3730,6 +3740,31 @@
public static final String EXTRA_ALTERNATE_INTENTS = "android.intent.extra.ALTERNATE_INTENTS";
/**
+ * A {@link ComponentName ComponentName[]} describing components that should be filtered out
+ * and omitted from a list of components presented to the user.
+ *
+ * <p>When used with {@link #ACTION_CHOOSER}, the chooser will omit any of the components
+ * in this array if it otherwise would have shown them. Useful for omitting specific targets
+ * from your own package or other apps from your organization if the idea of sending to those
+ * targets would be redundant with other app functionality. Filtered components will not
+ * be able to present targets from an associated <code>ChooserTargetService</code>.</p>
+ */
+ public static final String EXTRA_EXCLUDE_COMPONENTS
+ = "android.intent.extra.EXCLUDE_COMPONENTS";
+
+ /**
+ * A {@link android.service.chooser.ChooserTarget ChooserTarget[]} for {@link #ACTION_CHOOSER}
+ * describing additional high-priority deep-link targets for the chooser to present to the user.
+ *
+ * <p>Targets provided in this way will be presented inline with all other targets provided
+ * by services from other apps. They will be prioritized before other service targets, but
+ * after those targets provided by sources that the user has manually pinned to the front.</p>
+ *
+ * @see #ACTION_CHOOSER
+ */
+ public static final String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS";
+
+ /**
* An {@link IntentSender} for an Activity that will be invoked when the user makes a selection
* from the chooser activity presented by {@link #ACTION_CHOOSER}.
*
diff --git a/core/java/android/content/pm/FeatureInfo.java b/core/java/android/content/pm/FeatureInfo.java
index 7671f72..9ee6fa2 100644
--- a/core/java/android/content/pm/FeatureInfo.java
+++ b/core/java/android/content/pm/FeatureInfo.java
@@ -48,6 +48,9 @@
* <p>
* If this object represents a feature requested by an app, this is the
* minimum version of the feature required by the app.
+ * <p>
+ * When a feature version is undefined by a device, it's assumed to be
+ * version 0.
*/
public int version;
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 6b3d4f1..46321a4 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -47,17 +47,16 @@
ApplicationInfo getApplicationInfo(String packageName, int flags, in UserHandle user);
ParceledListSlice getShortcuts(String callingPackage, long changedSince, String packageName,
- in ComponentName componentName, int flags, in UserHandle user);
- ParceledListSlice getShortcutInfo(String callingPackage, String packageName, in List<String> ids,
- in UserHandle user);
+ in List shortcutIds, in ComponentName componentName, int flags, in UserHandle user);
void pinShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
in UserHandle user);
boolean startShortcut(String callingPackage, String packageName, String id,
- in Rect sourceBounds, in Bundle startActivityOptions, in UserHandle user);
+ in Rect sourceBounds, in Bundle startActivityOptions, int userId);
- int getShortcutIconResId(String callingPackage, in ShortcutInfo shortcut, in UserHandle user);
- ParcelFileDescriptor getShortcutIconFd(String callingPackage, in ShortcutInfo shortcut,
- in UserHandle user);
+ int getShortcutIconResId(String callingPackage, String packageName, String id,
+ int userId);
+ ParcelFileDescriptor getShortcutIconFd(String callingPackage, String packageName, String id,
+ int userId);
boolean hasShortcutHostPermission(String callingPackage);
}
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index d865f345..abe1aaf 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -205,6 +205,9 @@
String mPackage;
@Nullable
+ List<String> mShortcutIds;
+
+ @Nullable
ComponentName mActivity;
@QueryFlags
@@ -229,6 +232,14 @@
}
/**
+ * If non-null, return only the specified shortcuts by ID. When setting this field,
+ * a packange name must also be set with {@link #setPackage}.
+ */
+ public void setShortcutIds(@Nullable List<String> shortcutIds) {
+ mShortcutIds = shortcutIds;
+ }
+
+ /**
* If non-null, returns only shortcuts associated with the activity.
*/
public void setActivity(@Nullable ComponentName activity) {
@@ -429,7 +440,8 @@
@NonNull UserHandle user) {
try {
return mService.getShortcuts(mContext.getPackageName(),
- query.mChangedSince, query.mPackage, query.mActivity, query.mQueryFlags, user)
+ query.mChangedSince, query.mPackage, query.mShortcutIds, query.mActivity,
+ query.mQueryFlags, user)
.getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -437,29 +449,18 @@
}
/**
- * Returns {@link ShortcutInfo}s with the given IDs from a package.
- *
- * <p>Callers must be allowed to access the shortcut information, as defined in {@link
- * #hasShortcutHostPermission()}.
- *
- * @param packageName The target package.
- * @param ids IDs of the shortcuts to retrieve.
- * @param user The UserHandle of the profile.
- *
- * @return list of {@link ShortcutInfo} associated with the package.
+ * @hide // No longer used. Use getShortcuts() instead. Kept for unit tests.
*/
@Nullable
public List<ShortcutInfo> getShortcutInfo(@NonNull String packageName,
@NonNull List<String> ids, @NonNull UserHandle user) {
- try {
- return mService.getShortcutInfo(mContext.getPackageName(), packageName, ids, user)
- .getList();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ final ShortcutQuery q = new ShortcutQuery();
+ q.setPackage(packageName);
+ q.setShortcutIds(ids);
+ q.setQueryFlags(ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
+ return getShortcuts(q, user);
}
-
/**
* Pin shortcuts on a package.
*
@@ -490,11 +491,33 @@
* #hasShortcutHostPermission()}.
*
* @param shortcut The target shortcut.
+ */
+ public int getShortcutIconResId(@NonNull ShortcutInfo shortcut) {
+ return getShortcutIconResId(shortcut.getPackageName(), shortcut.getId(),
+ shortcut.getUserId());
+ }
+
+ /**
+ * Return the icon resource ID, if {@code shortcut} has one
+ * (i.e. when {@link ShortcutInfo#hasIconResource()} returns {@code true}).
+ *
+ * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+ * #hasShortcutHostPermission()}.
+ *
+ * @param packageName The target package name.
+ * @param shortcutId The ID of the shortcut to lad rom.
* @param user The UserHandle of the profile.
*/
- public int getShortcutIconResId(@NonNull ShortcutInfo shortcut, @NonNull UserHandle user) {
+ public int getShortcutIconResId(@NonNull String packageName, @NonNull String shortcutId,
+ @NonNull UserHandle user) {
+ return getShortcutIconResId(packageName, shortcutId, user.getIdentifier());
+ }
+
+ private int getShortcutIconResId(@NonNull String packageName, @NonNull String shortcutId,
+ int userId) {
try {
- return mService.getShortcutIconResId(mContext.getPackageName(), shortcut, user);
+ return mService.getShortcutIconResId(mContext.getPackageName(),
+ packageName, shortcutId, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -508,12 +531,34 @@
* #hasShortcutHostPermission()}.
*
* @param shortcut The target shortcut.
+ */
+ public ParcelFileDescriptor getShortcutIconFd(
+ @NonNull ShortcutInfo shortcut) {
+ return getShortcutIconFd(shortcut.getPackageName(), shortcut.getId(),
+ shortcut.getUserId());
+ }
+
+ /**
+ * Return the icon as {@link ParcelFileDescriptor}, when it's stored as a file
+ * (i.e. when {@link ShortcutInfo#hasIconFile()} returns {@code true}).
+ *
+ * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+ * #hasShortcutHostPermission()}.
+ *
+ * @param packageName The target package name.
+ * @param shortcutId The ID of the shortcut to lad rom.
* @param user The UserHandle of the profile.
*/
public ParcelFileDescriptor getShortcutIconFd(
- @NonNull ShortcutInfo shortcut, @NonNull UserHandle user) {
+ @NonNull String packageName, @NonNull String shortcutId, @NonNull UserHandle user) {
+ return getShortcutIconFd(packageName, shortcutId, user.getIdentifier());
+ }
+
+ private ParcelFileDescriptor getShortcutIconFd(
+ @NonNull String packageName, @NonNull String shortcutId, int userId) {
try {
- return mService.getShortcutIconFd(mContext.getPackageName(), shortcut, user);
+ return mService.getShortcutIconFd(mContext.getPackageName(),
+ packageName, shortcutId, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -536,9 +581,35 @@
public boolean startShortcut(@NonNull String packageName, @NonNull String shortcutId,
@Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
@NonNull UserHandle user) {
+ return startShortcut(packageName, shortcutId, sourceBounds, startActivityOptions,
+ user.getIdentifier());
+ }
+
+ /**
+ * Launches a shortcut.
+ *
+ * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+ * #hasShortcutHostPermission()}.
+ *
+ * @param shortcut The target shortcut.
+ * @param sourceBounds The Rect containing the source bounds of the clicked icon.
+ * @param startActivityOptions Options to pass to startActivity.
+ * @return {@code false} when the shortcut is no longer valid (e.g. the creator application
+ * has been uninstalled). {@code true} when the shortcut is still valid.
+ */
+ public boolean startShortcut(@NonNull ShortcutInfo shortcut,
+ @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions) {
+ return startShortcut(shortcut.getPackageName(), shortcut.getId(),
+ sourceBounds, startActivityOptions,
+ shortcut.getUserId());
+ }
+
+ private boolean startShortcut(@NonNull String packageName, @NonNull String shortcutId,
+ @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
+ int userId) {
try {
return mService.startShortcut(mContext.getPackageName(), packageName, shortcutId,
- sourceBounds, startActivityOptions, user);
+ sourceBounds, startActivityOptions, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index fe8db9f..aa1e372 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -385,6 +385,7 @@
public final int installLocation;
public final VerifierInfo[] verifiers;
public final Signature[] signatures;
+ public final Certificate[][] certificates;
public final boolean coreApp;
public final boolean multiArch;
public final boolean use32bitAbi;
@@ -392,8 +393,8 @@
public ApkLite(String codePath, String packageName, String splitName, int versionCode,
int revisionCode, int installLocation, List<VerifierInfo> verifiers,
- Signature[] signatures, boolean coreApp, boolean multiArch, boolean use32bitAbi,
- boolean extractNativeLibs) {
+ Signature[] signatures, Certificate[][] certificates, boolean coreApp,
+ boolean multiArch, boolean use32bitAbi, boolean extractNativeLibs) {
this.codePath = codePath;
this.packageName = packageName;
this.splitName = splitName;
@@ -402,6 +403,7 @@
this.installLocation = installLocation;
this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
this.signatures = signatures;
+ this.certificates = certificates;
this.coreApp = coreApp;
this.multiArch = multiArch;
this.use32bitAbi = use32bitAbi;
@@ -1074,6 +1076,43 @@
}
/**
+ * Populates the correct packages fields with the given certificates.
+ * <p>
+ * This is useful when we've already processed the certificates [such as during package
+ * installation through an installer session]. We don't re-process the archive and
+ * simply populate the correct fields.
+ */
+ public static void populateCertificates(Package pkg, Certificate[][] certificates)
+ throws PackageParserException {
+ pkg.mCertificates = null;
+ pkg.mSignatures = null;
+ pkg.mSigningKeys = null;
+
+ pkg.mCertificates = certificates;
+ try {
+ pkg.mSignatures = convertToSignatures(certificates);
+ } catch (CertificateEncodingException e) {
+ // certificates weren't encoded properly; something went wrong
+ throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
+ "Failed to collect certificates from " + pkg.baseCodePath, e);
+ }
+ pkg.mSigningKeys = new ArraySet<>(certificates.length);
+ for (int i = 0; i < certificates.length; i++) {
+ Certificate[] signerCerts = certificates[i];
+ Certificate signerCert = signerCerts[0];
+ pkg.mSigningKeys.add(signerCert.getPublicKey());
+ }
+ // add signatures to child packages
+ final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+ for (int i = 0; i < childCount; i++) {
+ Package childPkg = pkg.childPackages.get(i);
+ childPkg.mCertificates = pkg.mCertificates;
+ childPkg.mSignatures = pkg.mSignatures;
+ childPkg.mSigningKeys = pkg.mSigningKeys;
+ }
+ }
+
+ /**
* 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.
@@ -1304,6 +1343,7 @@
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final Signature[] signatures;
+ final Certificate[][] certificates;
if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
// TODO: factor signature related items out of Package object
final Package tempPkg = new Package(null);
@@ -1314,12 +1354,14 @@
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
signatures = tempPkg.mSignatures;
+ certificates = tempPkg.mCertificates;
} else {
signatures = null;
+ certificates = null;
}
final AttributeSet attrs = parser;
- return parseApkLite(apkPath, res, parser, attrs, flags, signatures);
+ return parseApkLite(apkPath, res, parser, attrs, flags, signatures, certificates);
} catch (XmlPullParserException | IOException | RuntimeException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
@@ -1405,8 +1447,8 @@
}
private static ApkLite parseApkLite(String codePath, Resources res, XmlPullParser parser,
- AttributeSet attrs, int flags, Signature[] signatures) throws IOException,
- XmlPullParserException, PackageParserException {
+ AttributeSet attrs, int flags, Signature[] signatures, Certificate[][] certificates)
+ throws IOException, XmlPullParserException, PackageParserException {
final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);
int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
@@ -1466,8 +1508,8 @@
}
return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
- revisionCode, installLocation, verifiers, signatures, coreApp, multiArch,
- use32bitAbi, extractNativeLibs);
+ revisionCode, installLocation, verifiers, signatures, certificates, coreApp,
+ multiArch, use32bitAbi, extractNativeLibs);
}
/**
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index e85311d..8236f55 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -36,22 +36,21 @@
* @hide
*/
public class PackageUserState {
+ public long ceDataInode;
+ public boolean installed;
public boolean stopped;
public boolean notLaunched;
- public boolean installed;
public boolean hidden; // Is the app restricted by owner / admin
public boolean suspended;
- public int enabled;
public boolean blockUninstall;
-
+ public int enabled;
public String lastDisableAppCaller;
+ public int domainVerificationStatus;
+ public int appLinkGeneration;
public ArraySet<String> disabledComponents;
public ArraySet<String> enabledComponents;
- public int domainVerificationStatus;
- public int appLinkGeneration;
-
public PackageUserState() {
installed = true;
hidden = false;
@@ -62,18 +61,19 @@
}
public PackageUserState(PackageUserState o) {
+ ceDataInode = o.ceDataInode;
installed = o.installed;
stopped = o.stopped;
notLaunched = o.notLaunched;
- enabled = o.enabled;
hidden = o.hidden;
suspended = o.suspended;
- lastDisableAppCaller = o.lastDisableAppCaller;
- disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
- enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
blockUninstall = o.blockUninstall;
+ enabled = o.enabled;
+ lastDisableAppCaller = o.lastDisableAppCaller;
domainVerificationStatus = o.domainVerificationStatus;
appLinkGeneration = o.appLinkGeneration;
+ disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
+ enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
}
/**
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 1812575a..7a807c4 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -153,7 +154,11 @@
@Nullable
private String mBitmapPath;
+ private final int mUserId;
+
private ShortcutInfo(Builder b) {
+ mUserId = b.mContext.getUserId();
+
mId = Preconditions.checkStringNotEmpty(b.mId, "Shortcut ID must be provided");
// Note we can't do other null checks here because SM.updateShortcuts() takes partial
@@ -191,6 +196,7 @@
* Copy constructor.
*/
private ShortcutInfo(ShortcutInfo source, @CloneFlags int cloneFlags) {
+ mUserId = source.mUserId;
mId = source.mId;
mPackageName = source.mPackageName;
mFlags = source.mFlags;
@@ -238,6 +244,7 @@
* @hide
*/
public void copyNonNullFieldsFrom(ShortcutInfo source) {
+ Preconditions.checkState(mUserId == source.mUserId, "Owner User ID must match");
Preconditions.checkState(mId.equals(source.mId), "ID must match");
Preconditions.checkState(mPackageName.equals(source.mPackageName),
"Package name must match");
@@ -362,8 +369,8 @@
*
* <p>For performance reasons, icons will <b>NOT</b> be available on instances
* returned by {@link ShortcutManager} or {@link LauncherApps}. Launcher applications
- * need to use {@link LauncherApps#getShortcutIconFd(ShortcutInfo, UserHandle)}
- * and {@link LauncherApps#getShortcutIconResId(ShortcutInfo, UserHandle)}.
+ * need to use {@link LauncherApps#getShortcutIconFd(ShortcutInfo)}
+ * and {@link LauncherApps#getShortcutIconResId(ShortcutInfo)}.
*/
@NonNull
public Builder setIcon(Icon icon) {
@@ -544,6 +551,18 @@
return mExtras;
}
+ /** @hide */
+ public int getUserId() {
+ return mUserId;
+ }
+
+ /**
+ * {@link UserHandle} on which the publisher created shortcuts.
+ */
+ public UserHandle getUserHandle() {
+ return UserHandle.of(mUserId);
+ }
+
/**
* Last time when any of the fields was updated.
*/
@@ -590,7 +609,7 @@
/**
* Return whether a shortcut's icon is a resource in the owning package.
*
- * @see LauncherApps#getShortcutIconResId(ShortcutInfo, UserHandle)
+ * @see LauncherApps#getShortcutIconResId(ShortcutInfo)
*/
public boolean hasIconResource() {
return hasFlags(FLAG_HAS_ICON_RES);
@@ -599,7 +618,7 @@
/**
* Return whether a shortcut's icon is stored as a file.
*
- * @see LauncherApps#getShortcutIconFd(ShortcutInfo, UserHandle)
+ * @see LauncherApps#getShortcutIconFd(ShortcutInfo)
*/
public boolean hasIconFile() {
return hasFlags(FLAG_HAS_ICON_FILE);
@@ -661,6 +680,7 @@
private ShortcutInfo(Parcel source) {
final ClassLoader cl = getClass().getClassLoader();
+ mUserId = source.readInt();
mId = source.readString();
mPackageName = source.readString();
mActivityComponent = source.readParcelable(cl);
@@ -679,6 +699,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mUserId);
dest.writeString(mId);
dest.writeString(mPackageName);
dest.writeParcelable(mActivityComponent, flags);
@@ -784,11 +805,13 @@
}
/** @hide */
- public ShortcutInfo(String id, String packageName, ComponentName activityComponent,
+ public ShortcutInfo(
+ @UserIdInt int userId, String id, String packageName, ComponentName activityComponent,
Icon icon, String title, String text, Intent intent,
PersistableBundle intentPersistableExtras,
int weight, PersistableBundle extras, long lastChangedTimestamp,
int flags, int iconResId, String bitmapPath) {
+ mUserId = userId;
mId = id;
mPackageName = packageName;
mActivityComponent = activityComponent;
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index d57f2e6e..dc3d317 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -42,15 +42,10 @@
public abstract List<ShortcutInfo>
getShortcuts(int launcherUserId,
@NonNull String callingPackage, long changedSince,
- @Nullable String packageName, @Nullable ComponentName componentName,
- @ShortcutQuery.QueryFlags int flags,
+ @Nullable String packageName, @Nullable List<String> shortcutIds,
+ @Nullable ComponentName componentName, @ShortcutQuery.QueryFlags int flags,
int userId);
- public abstract List<ShortcutInfo>
- getShortcutInfo(int launcherUserId, @NonNull String callingPackage,
- @NonNull String packageName, @Nullable List<String> ids, int userId);
-
-
public abstract boolean
isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
@NonNull String packageName, @NonNull String id, int userId);
@@ -65,11 +60,11 @@
public abstract void addListener(@NonNull ShortcutChangeListener listener);
public abstract int getShortcutIconResId(int launcherUserId, @NonNull String callingPackage,
- @NonNull ShortcutInfo shortcut, int userId);
+ @NonNull String packageName, @NonNull String shortcutId, int userId);
public abstract ParcelFileDescriptor getShortcutIconFd(int launcherUserId,
@NonNull String callingPackage,
- @NonNull ShortcutInfo shortcut, int userId);
+ @NonNull String packageName, @NonNull String shortcutId, int userId);
public abstract boolean hasShortcutHostPermission(int launcherUserId,
@NonNull String callingPackage);
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index a762f59..34a9523 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -26,6 +26,7 @@
import android.os.CancellationSignal;
import android.os.OperationCanceledException;
import android.os.ParcelFileDescriptor;
+import android.os.SystemClock;
import android.os.Trace;
import android.util.Log;
import android.util.LruCache;
@@ -1311,7 +1312,8 @@
operation.mBindArgs.clear();
}
}
- operation.mStartTime = System.currentTimeMillis();
+ operation.mStartWallTime = System.currentTimeMillis();
+ operation.mStartTime = SystemClock.uptimeMillis();
operation.mKind = kind;
operation.mSql = sql;
if (bindArgs != null) {
@@ -1376,7 +1378,7 @@
Trace.asyncTraceEnd(Trace.TRACE_TAG_DATABASE, operation.getTraceMethodName(),
operation.mCookie);
}
- operation.mEndTime = System.currentTimeMillis();
+ operation.mEndTime = SystemClock.uptimeMillis();
operation.mFinished = true;
return SQLiteDebug.DEBUG_LOG_SLOW_QUERIES && SQLiteDebug.shouldLogSlowQuery(
operation.mEndTime - operation.mStartTime);
@@ -1454,8 +1456,9 @@
// marker for us, potentially losing metadata in the process).
private static final int MAX_TRACE_METHOD_NAME_LEN = 256;
- public long mStartTime;
- public long mEndTime;
+ public long mStartWallTime; // in System.currentTimeMillis()
+ public long mStartTime; // in SystemClock.uptimeMillis();
+ public long mEndTime; // in SystemClock.uptimeMillis();
public String mKind;
public String mSql;
public ArrayList<Object> mBindArgs;
@@ -1468,7 +1471,7 @@
if (mFinished) {
msg.append(" took ").append(mEndTime - mStartTime).append("ms");
} else {
- msg.append(" started ").append(System.currentTimeMillis() - mStartTime)
+ msg.append(" started ").append(System.currentTimeMillis() - mStartWallTime)
.append("ms ago");
}
msg.append(" - ").append(getStatus());
@@ -1519,7 +1522,7 @@
// relatively expensive to create during preloading. This method is only used
// when dumping a connection, which is a rare (mainly error) case. So:
// DO NOT CACHE.
- return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(mStartTime));
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(mStartWallTime));
}
}
}
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 6aacc9c..c54d1e1 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -438,7 +438,7 @@
* @see #createCaptureSession
* @see OutputConfiguration
*/
- public abstract void createCaptureSessionByOutputConfiguration(
+ public abstract void createCaptureSessionByOutputConfigurations(
List<OutputConfiguration> outputConfigurations,
CameraCaptureSession.StateCallback callback, Handler handler)
throws CameraAccessException;
@@ -627,7 +627,7 @@
* @see OutputConfiguration
*
*/
- public abstract void createReprocessableCaptureSessionWithConfigurations(
+ public abstract void createReprocessableCaptureSessionByConfigurations(
@NonNull InputConfiguration inputConfig,
@NonNull List<OutputConfiguration> outputs,
@NonNull CameraCaptureSession.StateCallback callback,
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index d2e820e..18a155d 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -493,7 +493,7 @@
}
@Override
- public void createCaptureSessionByOutputConfiguration(
+ public void createCaptureSessionByOutputConfigurations(
List<OutputConfiguration> outputConfigurations,
CameraCaptureSession.StateCallback callback, Handler handler)
throws CameraAccessException {
@@ -532,7 +532,7 @@
}
@Override
- public void createReprocessableCaptureSessionWithConfigurations(InputConfiguration inputConfig,
+ public void createReprocessableCaptureSessionByConfigurations(InputConfiguration inputConfig,
List<OutputConfiguration> outputs,
android.hardware.camera2.CameraCaptureSession.StateCallback callback, Handler handler)
throws CameraAccessException {
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index b8088f3..4756b372 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -815,7 +815,8 @@
if (groupId != reqGroupId) {
Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
}
- mRemovalCallback.onRemovalSucceeded(mRemovalFingerprint);
+ mRemovalCallback.onRemovalSucceeded(new Fingerprint(null, groupId, fingerId,
+ deviceId));
}
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index fbac58c..47440de 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -16,9 +16,7 @@
package android.hardware.input;
-import com.android.internal.inputmethod.InputMethodSubtypeHandle;
import com.android.internal.os.SomeArgs;
-import com.android.internal.util.ArrayUtils;
import android.annotation.IntDef;
import android.annotation.SdkConstant;
diff --git a/core/java/android/hardware/input/InputManagerInternal.java b/core/java/android/hardware/input/InputManagerInternal.java
index 014e73f..10fc8e6 100644
--- a/core/java/android/hardware/input/InputManagerInternal.java
+++ b/core/java/android/hardware/input/InputManagerInternal.java
@@ -52,4 +52,11 @@
*/
public abstract void onInputMethodSubtypeChanged(int userId,
@Nullable InputMethodInfo inputMethodInfo, @Nullable InputMethodSubtype subtype);
+
+ /**
+ * Toggles Caps Lock state for input device with specific id.
+ *
+ * @param deviceId The id of input device.
+ */
+ public abstract void toggleCapsLock(int deviceId);
}
diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java
index ae44f1d..194b9ee 100644
--- a/core/java/android/hardware/location/ContextHubInfo.java
+++ b/core/java/android/hardware/location/ContextHubInfo.java
@@ -345,6 +345,24 @@
mMemoryRegions = Arrays.copyOf(memoryRegions, memoryRegions.length);
}
+ @Override
+ public String toString() {
+ String retVal = "";
+ retVal += "Id : " + mId;
+ retVal += ", Name : " + mName;
+ retVal += "\n\tVendor : " + mVendor;
+ retVal += ", ToolChain : " + mToolchain;
+ retVal += "\n\tPlatformVersion : " + mPlatformVersion;
+ retVal += ", StaticSwVersion : " + mStaticSwVersion;
+ retVal += "\n\tPeakMips : " + mPeakMips;
+ retVal += ", StoppedPowerDraw : " + mStoppedPowerDrawMw + " mW";
+ retVal += ", PeakPowerDraw : " + mPeakPowerDrawMw + " mW";
+ retVal += "\n\tSupported sensors : " + Arrays.toString(mSupportedSensors);
+ retVal += "\n\tMemory Regions : " + Arrays.toString(mMemoryRegions);
+
+ return retVal;
+ }
+
private ContextHubInfo(Parcel in) {
mId = in.readInt();
mName = in.readString();
diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java
index 3e6cb63..2b9b974 100644
--- a/core/java/android/hardware/location/ContextHubService.java
+++ b/core/java/android/hardware/location/ContextHubService.java
@@ -18,9 +18,12 @@
import android.Manifest;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.util.Log;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
@@ -28,13 +31,12 @@
* @hide
*/
public class ContextHubService extends IContextHubService.Stub {
-
public static final String CONTEXTHUB_SERVICE = "contexthub_service";
private static final String TAG = "ContextHubService";
private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
- + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
+ + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
public static final int ANY_HUB = -1;
@@ -78,8 +80,8 @@
@Override
public int registerCallback(IContextHubCallback callback) throws RemoteException {
checkPermissions();
- synchronized(this) {
- mCallback = callback;
+ synchronized (this) {
+ mCallback = callback;
}
return 0;
}
@@ -87,10 +89,10 @@
@Override
public int[] getContextHubHandles() throws RemoteException {
checkPermissions();
- int [] returnArray = new int[mContextHubInfo.length];
+ int[] returnArray = new int[mContextHubInfo.length];
for (int i = 0; i < returnArray.length; ++i) {
- returnArray[i] = i + 1; //valid handles from 1...n
+ returnArray[i] = i;
Log.d(TAG, String.format("Hub %s is mapped to %d",
mContextHubInfo[i].getName(), returnArray[i]));
}
@@ -101,7 +103,6 @@
@Override
public ContextHubInfo getContextHubInfo(int contextHubHandle) throws RemoteException {
checkPermissions();
- contextHubHandle -= 1;
if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
return null; // null means fail
}
@@ -112,13 +113,12 @@
@Override
public int loadNanoApp(int contextHubHandle, NanoApp app) throws RemoteException {
checkPermissions();
- contextHubHandle -= 1;
if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
- return -1; // negative handle are invalid, means failed
+ Log.e(TAG, "Invalid contextHubhandle " + contextHubHandle);
+ return -1;
}
- // Call Native interface here
int[] msgHeader = new int[MSG_HEADER_SIZE];
msgHeader[MSG_FIELD_HUB_HANDLE] = contextHubHandle;
msgHeader[MSG_FIELD_APP_INSTANCE] = OS_APP_INSTANCE;
@@ -147,7 +147,7 @@
msgHeader[MSG_FIELD_VERSION] = 0;
msgHeader[MSG_FIELD_TYPE] = MSG_UNLOAD_NANO_APP;
- if(nativeSendMessage(msgHeader, null) != 0) {
+ if (nativeSendMessage(msgHeader, null) != 0) {
return -1;
}
@@ -157,7 +157,7 @@
@Override
public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle)
- throws RemoteException {
+ throws RemoteException {
checkPermissions();
// This assumes that all the nanoAppInfo is current. This is reasonable
// for the use cases for tightly controlled nanoApps.
@@ -173,10 +173,10 @@
checkPermissions();
ArrayList<Integer> foundInstances = new ArrayList<Integer>();
- for(Integer nanoAppInstance : mNanoAppHash.keySet()) {
+ for (Integer nanoAppInstance: mNanoAppHash.keySet()) {
NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstance);
- if (filter.testMatch(info)){
+ if (filter.testMatch(info)) {
foundInstances.add(nanoAppInstance);
}
}
@@ -191,7 +191,7 @@
@Override
public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg)
- throws RemoteException {
+ throws RemoteException {
checkPermissions();
int[] msgHeader = new int[MSG_HEADER_SIZE];
@@ -203,6 +203,32 @@
return nativeSendMessage(msgHeader, msg.getData());
}
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump contexthub_service");
+ return;
+ }
+
+ pw.println("Dumping ContextHub Service");
+
+ pw.println("");
+ // dump ContextHubInfo
+ pw.println("=================== CONTEXT HUBS ====================");
+ for (int i = 0; i < mContextHubInfo.length; i++) {
+ pw.println("Handle " + i + " : " + mContextHubInfo[i].toString());
+ }
+ pw.println("");
+ pw.println("=================== NANOAPPS ====================");
+ // Dump nanoAppHash
+ for (Integer nanoAppInstance: mNanoAppHash.keySet()) {
+ pw.println(nanoAppInstance + " : " + mNanoAppHash.get(nanoAppInstance).toString());
+ }
+
+ // dump eventLog
+ }
+
private void checkPermissions() {
mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
}
@@ -212,16 +238,16 @@
return -1;
}
- synchronized(this) {
+ synchronized (this) {
if (mCallback != null) {
ContextHubMessage msg = new ContextHubMessage(header[MSG_FIELD_TYPE],
- header[MSG_FIELD_VERSION],
- data);
+ header[MSG_FIELD_VERSION],
+ data);
try {
mCallback.onMessageReceipt(header[MSG_FIELD_HUB_HANDLE],
- header[MSG_FIELD_APP_INSTANCE],
- msg);
+ header[MSG_FIELD_APP_INSTANCE],
+ msg);
} catch (Exception e) {
Log.w(TAG, "Exception " + e + " when calling remote callback");
return -1;
diff --git a/core/java/android/hardware/location/MemoryRegion.java b/core/java/android/hardware/location/MemoryRegion.java
index d100de2..857434e 100644
--- a/core/java/android/hardware/location/MemoryRegion.java
+++ b/core/java/android/hardware/location/MemoryRegion.java
@@ -79,6 +79,33 @@
}
@Override
+ public String toString() {
+ String mask = "";
+
+ if (isReadable()) {
+ mask += "r";
+ } else {
+ mask += "-";
+ }
+
+ if (isWritable()) {
+ mask += "w";
+ } else {
+ mask += "-";
+ }
+
+ if (isExecutable()) {
+ mask += "x";
+ } else {
+ mask += "-";
+ }
+
+ String retVal = "[ " + mSizeBytesFree + "/ " + mSizeBytes + " ] : " + mask;
+
+ return retVal;
+ }
+
+ @Override
public int describeContents() {
return 0;
}
diff --git a/core/java/android/hardware/location/NanoApp.java b/core/java/android/hardware/location/NanoApp.java
index b447b62..c8f3439 100644
--- a/core/java/android/hardware/location/NanoApp.java
+++ b/core/java/android/hardware/location/NanoApp.java
@@ -284,4 +284,14 @@
return new NanoApp[size];
}
};
+
+ @Override
+ public String toString() {
+ String retVal = "Id : " + mAppId;
+ retVal += ", Version : " + mAppVersion;
+ retVal += ", Name : " + mName;
+ retVal += ", Publisher : " + mPublisher;
+
+ return retVal;
+ }
}
diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.java b/core/java/android/hardware/location/NanoAppInstanceInfo.java
index 977f645..e842ec6 100644
--- a/core/java/android/hardware/location/NanoAppInstanceInfo.java
+++ b/core/java/android/hardware/location/NanoAppInstanceInfo.java
@@ -320,4 +320,15 @@
return new NanoAppInstanceInfo[size];
}
};
+
+ @Override
+ public String toString() {
+ String retVal = "handle : " + mHandle;
+ retVal += ", Id : 0x" + Long.toHexString(mAppId);
+ retVal += ", Version : " + mAppVersion;
+ retVal += ", Name : " + mName;
+ retVal += ", Publisher : " + mPublisher;
+
+ return retVal;
+ }
}
diff --git a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
index cc018e9..458c584 100644
--- a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
+++ b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
@@ -35,9 +35,11 @@
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
-import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
/**
* Enrollment information about the different available keyphrases.
@@ -82,8 +84,16 @@
public static final String EXTRA_VOICE_KEYPHRASE_LOCALE =
"com.android.intent.extra.VOICE_KEYPHRASE_LOCALE";
- private KeyphraseMetadata[] mKeyphrases;
- private String mEnrollmentPackage;
+ /**
+ * List of available keyphrases.
+ */
+ final private KeyphraseMetadata[] mKeyphrases;
+
+ /**
+ * Map between KeyphraseMetadata and the package name of the enrollment app that provides it.
+ */
+ final private Map<KeyphraseMetadata, String> mKeyphrasePackageMap;
+
private String mParseError;
public KeyphraseEnrollmentInfo(PackageManager pm) {
@@ -94,15 +104,17 @@
new Intent(ACTION_MANAGE_VOICE_KEYPHRASES), PackageManager.MATCH_DEFAULT_ONLY);
if (ris == null || ris.isEmpty()) {
// No application capable of enrolling for voice keyphrases is present.
- mParseError = "No enrollment application found";
+ mParseError = "No enrollment applications found";
+ mKeyphrasePackageMap = null;
+ mKeyphrases = null;
return;
}
- boolean found = false;
- ApplicationInfo ai = null;
+ List<String> parseErrors = new LinkedList<String>();
+ mKeyphrasePackageMap = new HashMap<KeyphraseMetadata, String>();
for (ResolveInfo ri : ris) {
try {
- ai = pm.getApplicationInfo(
+ ApplicationInfo ai = pm.getApplicationInfo(
ri.activityInfo.packageName, PackageManager.GET_META_DATA);
if ((ai.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) == 0) {
// The application isn't privileged (/system/priv-app).
@@ -116,27 +128,45 @@
Slog.w(TAG, ai.packageName + " does not require MANAGE_VOICE_KEYPHRASES");
continue;
}
- mEnrollmentPackage = ai.packageName;
- found = true;
- break;
+
+ mKeyphrasePackageMap.put(
+ getKeyphraseMetadataFromApplicationInfo(pm, ai, parseErrors),
+ ai.packageName);
} catch (PackageManager.NameNotFoundException e) {
- Slog.w(TAG, "error parsing voice enrollment meta-data", e);
+ String error = "error parsing voice enrollment meta-data for "
+ + ri.activityInfo.packageName;
+ parseErrors.add(error + ": " + e);
+ Slog.w(TAG, error, e);
}
}
- if (!found) {
+ if (mKeyphrasePackageMap.isEmpty()) {
+ String error = "No suitable enrollment application found";
+ parseErrors.add(error);
+ Slog.w(TAG, error);
mKeyphrases = null;
- mParseError = "No suitable enrollment application found";
- return;
+ } else {
+ mKeyphrases = mKeyphrasePackageMap.keySet().toArray(
+ new KeyphraseMetadata[mKeyphrasePackageMap.size()]);
}
+ if (!parseErrors.isEmpty()) {
+ mParseError = TextUtils.join("\n", parseErrors);
+ }
+ }
+
+ private KeyphraseMetadata getKeyphraseMetadataFromApplicationInfo(PackageManager pm,
+ ApplicationInfo ai, List<String> parseErrors) {
XmlResourceParser parser = null;
+ String packageName = ai.packageName;
+ KeyphraseMetadata keyphraseMetadata = null;
try {
parser = ai.loadXmlMetaData(pm, VOICE_KEYPHRASE_META_DATA);
if (parser == null) {
- mParseError = "No " + VOICE_KEYPHRASE_META_DATA + " meta-data for "
- + ai.packageName;
- return;
+ String error = "No " + VOICE_KEYPHRASE_META_DATA + " meta-data for " + packageName;
+ parseErrors.add(error);
+ Slog.w(TAG, error);
+ return null;
}
Resources res = pm.getResourcesForApplication(ai);
@@ -149,48 +179,55 @@
String nodeName = parser.getName();
if (!"voice-enrollment-application".equals(nodeName)) {
- mParseError = "Meta-data does not start with voice-enrollment-application tag";
- return;
+ String error = "Meta-data does not start with voice-enrollment-application tag for "
+ + packageName;
+ parseErrors.add(error);
+ Slog.w(TAG, error);
+ return null;
}
TypedArray array = res.obtainAttributes(attrs,
com.android.internal.R.styleable.VoiceEnrollmentApplication);
- initializeKeyphrasesFromTypedArray(array);
+ keyphraseMetadata = getKeyphraseFromTypedArray(array, packageName, parseErrors);
array.recycle();
} catch (XmlPullParserException e) {
- mParseError = "Error parsing keyphrase enrollment meta-data: " + e;
- Slog.w(TAG, "error parsing keyphrase enrollment meta-data", e);
- return;
+ String error = "Error parsing keyphrase enrollment meta-data for " + packageName;
+ parseErrors.add(error + ": " + e);
+ Slog.w(TAG, error, e);
} catch (IOException e) {
- mParseError = "Error parsing keyphrase enrollment meta-data: " + e;
- Slog.w(TAG, "error parsing keyphrase enrollment meta-data", e);
- return;
+ String error = "Error parsing keyphrase enrollment meta-data for " + packageName;
+ parseErrors.add(error + ": " + e);
+ Slog.w(TAG, error, e);
} catch (PackageManager.NameNotFoundException e) {
- mParseError = "Error parsing keyphrase enrollment meta-data: " + e;
- Slog.w(TAG, "error parsing keyphrase enrollment meta-data", e);
- return;
+ String error = "Error parsing keyphrase enrollment meta-data for " + packageName;
+ parseErrors.add(error + ": " + e);
+ Slog.w(TAG, error, e);
} finally {
if (parser != null) parser.close();
}
+ return keyphraseMetadata;
}
- private void initializeKeyphrasesFromTypedArray(TypedArray array) {
+ private KeyphraseMetadata getKeyphraseFromTypedArray(TypedArray array, String packageName,
+ List<String> parseErrors) {
// Get the keyphrase ID.
int searchKeyphraseId = array.getInt(
com.android.internal.R.styleable.VoiceEnrollmentApplication_searchKeyphraseId, -1);
if (searchKeyphraseId <= 0) {
- mParseError = "No valid searchKeyphraseId specified in meta-data";
- Slog.w(TAG, mParseError);
- return;
+ String error = "No valid searchKeyphraseId specified in meta-data for " + packageName;
+ parseErrors.add(error);
+ Slog.w(TAG, error);
+ return null;
}
// Get the keyphrase text.
String searchKeyphrase = array.getString(
com.android.internal.R.styleable.VoiceEnrollmentApplication_searchKeyphrase);
if (searchKeyphrase == null) {
- mParseError = "No valid searchKeyphrase specified in meta-data";
- Slog.w(TAG, mParseError);
- return;
+ String error = "No valid searchKeyphrase specified in meta-data for " + packageName;
+ parseErrors.add(error);
+ Slog.w(TAG, error);
+ return null;
}
// Get the supported locales.
@@ -198,9 +235,11 @@
com.android.internal.R.styleable
.VoiceEnrollmentApplication_searchKeyphraseSupportedLocales);
if (searchKeyphraseSupportedLocales == null) {
- mParseError = "No valid searchKeyphraseSupportedLocales specified in meta-data";
- Slog.w(TAG, mParseError);
- return;
+ String error = "No valid searchKeyphraseSupportedLocales specified in meta-data for "
+ + packageName;
+ parseErrors.add(error);
+ Slog.w(TAG, error);
+ return null;
}
ArraySet<Locale> locales = new ArraySet<>();
// Try adding locales if the locale string is non-empty.
@@ -214,9 +253,11 @@
// We catch a generic exception here because we don't want the system service
// to be affected by a malformed metadata because invalid locales were specified
// by the system application.
- mParseError = "Error reading searchKeyphraseSupportedLocales from meta-data";
- Slog.w(TAG, mParseError, ex);
- return;
+ String error = "Error reading searchKeyphraseSupportedLocales from meta-data for "
+ + packageName;
+ parseErrors.add(error);
+ Slog.w(TAG, error);
+ return null;
}
}
@@ -224,13 +265,13 @@
int recognitionModes = array.getInt(com.android.internal.R.styleable
.VoiceEnrollmentApplication_searchKeyphraseRecognitionFlags, -1);
if (recognitionModes < 0) {
- mParseError = "No valid searchKeyphraseRecognitionFlags specified in meta-data";
- Slog.w(TAG, mParseError);
- return;
+ String error = "No valid searchKeyphraseRecognitionFlags specified in meta-data for "
+ + packageName;
+ parseErrors.add(error);
+ Slog.w(TAG, error);
+ return null;
}
- mKeyphrases = new KeyphraseMetadata[1];
- mKeyphrases[0] = new KeyphraseMetadata(searchKeyphraseId, searchKeyphrase, locales,
- recognitionModes);
+ return new KeyphraseMetadata(searchKeyphraseId, searchKeyphrase, locales, recognitionModes);
}
public String getParseError() {
@@ -259,14 +300,15 @@
* given keyphrase/locale combination isn't possible.
*/
public Intent getManageKeyphraseIntent(int action, String keyphrase, Locale locale) {
- if (mEnrollmentPackage == null || mEnrollmentPackage.isEmpty()) {
+ if (mKeyphrasePackageMap == null || mKeyphrasePackageMap.isEmpty()) {
Slog.w(TAG, "No enrollment application exists");
return null;
}
- if (getKeyphraseMetadata(keyphrase, locale) != null) {
+ KeyphraseMetadata keyphraseMetadata = getKeyphraseMetadata(keyphrase, locale);
+ if (keyphraseMetadata != null) {
Intent intent = new Intent(ACTION_MANAGE_VOICE_KEYPHRASES)
- .setPackage(mEnrollmentPackage)
+ .setPackage(mKeyphrasePackageMap.get(keyphraseMetadata))
.putExtra(EXTRA_VOICE_KEYPHRASE_HINT_TEXT, keyphrase)
.putExtra(EXTRA_VOICE_KEYPHRASE_LOCALE, locale.toLanguageTag())
.putExtra(EXTRA_VOICE_KEYPHRASE_ACTION, action);
@@ -298,14 +340,13 @@
return keyphraseMetadata;
}
}
- Slog.w(TAG, "Enrollment application doesn't support the given keyphrase/locale");
+ Slog.w(TAG, "No Enrollment application supports the given keyphrase/locale");
return null;
}
@Override
public String toString() {
- return "KeyphraseEnrollmentInfo [Keyphrases=" + Arrays.toString(mKeyphrases)
- + ", EnrollmentPackage=" + mEnrollmentPackage + ", ParseError=" + mParseError
- + "]";
+ return "KeyphraseEnrollmentInfo [Keyphrases=" + mKeyphrasePackageMap.toString()
+ + ", ParseError=" + mParseError + "]";
}
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index b452341..a025337 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -767,6 +767,28 @@
}
/**
+ * Returns a {@link Network} object corresponding to the currently active
+ * default data network for a specific UID. In the event that the default data
+ * network disconnects, the returned {@code Network} object will no longer
+ * be usable. This will return {@code null} when there is no default
+ * network for the UID.
+ * <p>This method requires the caller to hold the permission
+ * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}.
+ *
+ * @return a {@link Network} object for the current default network for the
+ * given UID or {@code null} if no default network is currently active
+ *
+ * @hide
+ */
+ public Network getActiveNetworkForUid(int uid) {
+ try {
+ return mService.getActiveNetworkForUid(uid);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Configures an always-on VPN connection through a specific application.
* This connection is automatically granted and persisted after a reboot.
*
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 1a9c9ea..c897c45 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -44,6 +44,7 @@
interface IConnectivityManager
{
Network getActiveNetwork();
+ Network getActiveNetworkForUid(int uid);
NetworkInfo getActiveNetworkInfo();
NetworkInfo getActiveNetworkInfoForUid(int uid);
NetworkInfo getNetworkInfo(int networkType);
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index a9de23e..9cd563e 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -55,19 +55,22 @@
final String mSubscriberId;
final String mNetworkId;
final boolean mRoaming;
+ final boolean mMetered;
public NetworkIdentity(
- int type, int subType, String subscriberId, String networkId, boolean roaming) {
+ int type, int subType, String subscriberId, String networkId, boolean roaming,
+ boolean metered) {
mType = type;
mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
mSubscriberId = subscriberId;
mNetworkId = networkId;
mRoaming = roaming;
+ mMetered = metered;
}
@Override
public int hashCode() {
- return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming);
+ return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered);
}
@Override
@@ -76,7 +79,8 @@
final NetworkIdentity ident = (NetworkIdentity) obj;
return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming
&& Objects.equals(mSubscriberId, ident.mSubscriberId)
- && Objects.equals(mNetworkId, ident.mNetworkId);
+ && Objects.equals(mNetworkId, ident.mNetworkId)
+ && mMetered == ident.mMetered;
}
return false;
}
@@ -102,6 +106,7 @@
if (mRoaming) {
builder.append(", ROAMING");
}
+ builder.append(", metered=").append(mMetered);
return builder.append("}").toString();
}
@@ -125,6 +130,10 @@
return mRoaming;
}
+ public boolean getMetered() {
+ return mMetered;
+ }
+
/**
* Scrub given IMSI on production builds.
*/
@@ -162,6 +171,7 @@
String subscriberId = null;
String networkId = null;
boolean roaming = false;
+ boolean metered = false;
if (isNetworkTypeMobile(type)) {
if (state.subscriberId == null) {
@@ -171,6 +181,9 @@
subscriberId = state.subscriberId;
roaming = state.networkInfo.isRoaming();
+ metered = !state.networkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+
} else if (type == TYPE_WIFI) {
if (state.networkId != null) {
networkId = state.networkId;
@@ -182,7 +195,7 @@
}
}
- return new NetworkIdentity(type, subType, subscriberId, networkId, roaming);
+ return new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered);
}
@Override
@@ -200,6 +213,9 @@
if (res == 0) {
res = Boolean.compare(mRoaming, another.mRoaming);
}
+ if (res == 0) {
+ res = Boolean.compare(mMetered, another.mMetered);
+ }
return res;
}
}
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index b32b2cc..caf7982 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -19,6 +19,7 @@
import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_PROXY;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
import static android.net.ConnectivityManager.TYPE_WIMAX;
@@ -30,9 +31,6 @@
import static android.telephony.TelephonyManager.NETWORK_CLASS_UNKNOWN;
import static android.telephony.TelephonyManager.getNetworkClass;
-import static com.android.internal.util.ArrayUtils.contains;
-
-import android.content.res.Resources;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.BackupUtils;
@@ -71,16 +69,6 @@
public static final int MATCH_BLUETOOTH = 8;
public static final int MATCH_PROXY = 9;
- /**
- * Set of {@link NetworkInfo#getType()} that reflect data usage.
- */
- private static final int[] DATA_USAGE_NETWORK_TYPES;
-
- static {
- DATA_USAGE_NETWORK_TYPES = Resources.getSystem().getIntArray(
- com.android.internal.R.array.config_data_usage_network_types);
- }
-
private static boolean sForceAllNetworkTypes = false;
@VisibleForTesting
@@ -318,9 +306,8 @@
// TODO: consider matching against WiMAX subscriber identity
return true;
} else {
- final boolean matchesType = (sForceAllNetworkTypes
- || contains(DATA_USAGE_NETWORK_TYPES, ident.mType));
- return matchesType && !ArrayUtils.isEmpty(mMatchSubscriberIds)
+ return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
+ && !ArrayUtils.isEmpty(mMatchSubscriberIds)
&& ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
}
}
@@ -389,7 +376,7 @@
if (ident.mType == TYPE_WIMAX) {
return true;
} else {
- return sForceAllNetworkTypes || contains(DATA_USAGE_NETWORK_TYPES, ident.mType);
+ return sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered);
}
}
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index e40ebf7..d39968a 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -115,6 +115,13 @@
*/
public static final String EXTRA_MAX_CHARGING_VOLTAGE = "max_charging_voltage";
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * integer containing the charge counter present in the battery.
+ * {@hide}
+ */
+ public static final String EXTRA_CHARGE_COUNTER = "charge_counter";
+
// values for "status" field in the ACTION_BATTERY_CHANGED Intent
public static final int BATTERY_STATUS_UNKNOWN = 1;
public static final int BATTERY_STATUS_CHARGING = 2;
diff --git a/core/java/android/os/BatteryProperties.java b/core/java/android/os/BatteryProperties.java
index c3e0f24..b509d76 100644
--- a/core/java/android/os/BatteryProperties.java
+++ b/core/java/android/os/BatteryProperties.java
@@ -30,6 +30,7 @@
public int batteryLevel;
public int batteryVoltage;
public int batteryTemperature;
+ public int batteryChargeCounter;
public String batteryTechnology;
public BatteryProperties() {
@@ -47,6 +48,7 @@
batteryLevel = other.batteryLevel;
batteryVoltage = other.batteryVoltage;
batteryTemperature = other.batteryTemperature;
+ batteryChargeCounter = other.batteryChargeCounter;
batteryTechnology = other.batteryTechnology;
}
@@ -67,6 +69,7 @@
batteryLevel = p.readInt();
batteryVoltage = p.readInt();
batteryTemperature = p.readInt();
+ batteryChargeCounter = p.readInt();
batteryTechnology = p.readString();
}
@@ -82,6 +85,7 @@
p.writeInt(batteryLevel);
p.writeInt(batteryVoltage);
p.writeInt(batteryTemperature);
+ p.writeInt(batteryChargeCounter);
p.writeString(batteryTechnology);
}
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index 878b7a0..3c7c962 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -231,6 +231,18 @@
mAsynchronous = async;
}
+ /** {@hide} */
+ public String getTraceName(Message message) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(getClass().getName()).append(": ");
+ if (message.callback != null) {
+ sb.append(message.callback.getClass().getName());
+ } else {
+ sb.append("#").append(message.what);
+ }
+ return sb.toString();
+ }
+
/**
* Returns a string representing the name of the specified message.
* The default implementation will either return the class name of the
@@ -739,8 +751,8 @@
message.callback.run();
}
- final MessageQueue mQueue;
final Looper mLooper;
+ final MessageQueue mQueue;
final Callback mCallback;
final boolean mAsynchronous;
IMessenger mMessenger;
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index c38bf3c..67d3959 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -45,6 +45,7 @@
UserInfo getPrimaryUser();
List<UserInfo> getUsers(boolean excludeDying);
List<UserInfo> getProfiles(int userHandle, boolean enabledOnly);
+ int[] getProfileIds(int userId, boolean enabledOnly);
boolean canAddMoreManagedProfiles(int userHandle, boolean allowedToRemoveOne);
UserInfo getProfileParent(int userHandle);
boolean isSameProfileGroup(int userHandle, int otherUserHandle);
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 34c880f..b58ff1f 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -72,6 +72,7 @@
final Thread mThread;
private Printer mLogging;
+ private long mTraceTag;
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
@@ -139,13 +140,23 @@
}
// This must be in a local variable, in case a UI event sets the logger
- Printer logging = me.mLogging;
+ final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
- msg.target.dispatchMessage(msg);
+ final long traceTag = me.mTraceTag;
+ if (traceTag != 0) {
+ Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
+ }
+ try {
+ msg.target.dispatchMessage(msg);
+ } finally {
+ if (traceTag != 0) {
+ Trace.traceEnd(traceTag);
+ }
+ }
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
@@ -208,6 +219,11 @@
mLogging = printer;
}
+ /** {@hide} */
+ public void setTraceTag(long traceTag) {
+ mTraceTag = traceTag;
+ }
+
/**
* Quits the looper.
* <p>
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 707d5f5..d5b3b35 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1590,18 +1590,46 @@
* @return A non-empty list of UserHandles associated with the calling user.
*/
public List<UserHandle> getUserProfiles() {
- ArrayList<UserHandle> profiles = new ArrayList<UserHandle>();
- List<UserInfo> users;
+ int[] userIds = getProfileIds(UserHandle.myUserId(), true /* enabledOnly */);
+ List<UserHandle> result = new ArrayList<>(userIds.length);
+ for (int userId : userIds) {
+ result.add(UserHandle.of(userId));
+ }
+ return result;
+ }
+
+ /**
+ * Returns a list of ids for profiles associated with the specified user including the user
+ * itself.
+ *
+ * @param userId id of the user to return profiles for
+ * @param enabledOnly whether return only {@link UserInfo#isEnabled() enabled} profiles
+ * @return A non-empty list of ids of profiles associated with the specified user.
+ *
+ * @hide
+ */
+ public int[] getProfileIds(@UserIdInt int userId, boolean enabledOnly) {
try {
- users = mService.getProfiles(UserHandle.myUserId(), true /* enabledOnly */);
+ return mService.getProfileIds(userId, enabledOnly);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
- for (UserInfo info : users) {
- UserHandle userHandle = new UserHandle(info.id);
- profiles.add(userHandle);
- }
- return profiles;
+ }
+
+ /**
+ * @see #getProfileIds(int, boolean)
+ * @hide
+ */
+ public int[] getProfileIdsWithDisabled(@UserIdInt int userId) {
+ return getProfileIds(userId, false /* enabledOnly */);
+ }
+
+ /**
+ * @see #getProfileIds(int, boolean)
+ * @hide
+ */
+ public int[] getEnabledProfileIds(@UserIdInt int userId) {
+ return getProfileIds(userId, true /* enabledOnly */);
}
/**
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index f2e316c..ece1228 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -83,6 +83,8 @@
public static final String PROP_FORCE_ADOPTABLE = "persist.fw.force_adoptable";
/** {@hide} */
public static final String PROP_EMULATE_FBE = "persist.sys.emulate_fbe";
+ /** {@hide} */
+ public static final String PROP_SDCARDFS = "persist.sys.sdcardfs";
/** {@hide} */
public static final String UUID_PRIVATE_INTERNAL = null;
@@ -93,6 +95,10 @@
public static final int DEBUG_FORCE_ADOPTABLE = 1 << 0;
/** {@hide} */
public static final int DEBUG_EMULATE_FBE = 1 << 1;
+ /** {@hide} */
+ public static final int DEBUG_SDCARDFS_FORCE_ON = 1 << 2;
+ /** {@hide} */
+ public static final int DEBUG_SDCARDFS_FORCE_OFF = 1 << 3;
// NOTE: keep in sync with installd
/** {@hide} */
@@ -1178,7 +1184,23 @@
/** {@hide} */
public static File maybeTranslateEmulatedPathToInternal(File path) {
- // Disabled now that FUSE has been replaced by sdcardfs
+ final IMountService mountService = IMountService.Stub.asInterface(
+ ServiceManager.getService("mount"));
+ try {
+ final VolumeInfo[] vols = mountService.getVolumes(0);
+ for (VolumeInfo vol : vols) {
+ if ((vol.getType() == VolumeInfo.TYPE_EMULATED
+ || vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.isMountedReadable()) {
+ final File internalPath = FileUtils.rewriteAfterRename(vol.getPath(),
+ vol.getInternalPath(), path);
+ if (internalPath != null && internalPath.exists()) {
+ return internalPath;
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
return path;
}
diff --git a/core/java/android/service/notification/Adjustment.aidl b/core/java/android/service/notification/Adjustment.aidl
new file mode 100644
index 0000000..8bd814a
--- /dev/null
+++ b/core/java/android/service/notification/Adjustment.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.service.notification;
+
+parcelable Adjustment;
\ No newline at end of file
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
new file mode 100644
index 0000000..2e4f48d
--- /dev/null
+++ b/core/java/android/service/notification/Adjustment.java
@@ -0,0 +1,150 @@
+/*
+ * 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.service.notification;
+
+import android.annotation.SystemApi;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Ranking updates from the Ranker.
+ *
+ * @hide
+ */
+@SystemApi
+public final class Adjustment implements Parcelable {
+ private final String mPackage;
+ private final String mKey;
+ private final int mImportance;
+ private final CharSequence mExplanation;
+ private final Uri mReference;
+ private final Bundle mSignals;
+
+ public static final String GROUP_KEY_OVERRIDE_KEY = "group_key_override";
+ public static final String NEEDS_AUTOGROUPING_KEY = "autogroup_needed";
+
+ /**
+ * Create a notification adjustment.
+ *
+ * @param pkg The package of the notification.
+ * @param key The notification key.
+ * @param importance The recommended importance of the notification.
+ * @param signals A bundle of signals that should inform notification grouping and ordering.
+ * @param explanation A human-readable justification for the adjustment.
+ * @param reference A reference to an external object that augments the
+ * explanation, such as a
+ * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI},
+ * or null.
+ */
+ public Adjustment(String pkg, String key, int importance, Bundle signals,
+ CharSequence explanation, Uri reference) {
+ mPackage = pkg;
+ mKey = key;
+ mImportance = importance;
+ mSignals = signals;
+ mExplanation = explanation;
+ mReference = reference;
+ }
+
+ protected Adjustment(Parcel in) {
+ if (in.readInt() == 1) {
+ mPackage = in.readString();
+ } else {
+ mPackage = null;
+ }
+ if (in.readInt() == 1) {
+ mKey = in.readString();
+ } else {
+ mKey = null;
+ }
+ mImportance = in.readInt();
+ if (in.readInt() == 1) {
+ mExplanation = in.readCharSequence();
+ } else {
+ mExplanation = null;
+ }
+ mReference = in.readParcelable(Uri.class.getClassLoader());
+ mSignals = in.readBundle();
+ }
+
+ public static final Creator<Adjustment> CREATOR = new Creator<Adjustment>() {
+ @Override
+ public Adjustment createFromParcel(Parcel in) {
+ return new Adjustment(in);
+ }
+
+ @Override
+ public Adjustment[] newArray(int size) {
+ return new Adjustment[size];
+ }
+ };
+
+ public String getPackage() {
+ return mPackage;
+ }
+
+ public String getKey() {
+ return mKey;
+ }
+
+ public int getImportance() {
+ return mImportance;
+ }
+
+ public CharSequence getExplanation() {
+ return mExplanation;
+ }
+
+ public Uri getReference() {
+ return mReference;
+ }
+
+ public Bundle getSignals() {
+ return mSignals;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (mPackage != null) {
+ dest.writeInt(1);
+ dest.writeString(mPackage);
+ } else {
+ dest.writeInt(0);
+ }
+ if (mKey != null) {
+ dest.writeInt(1);
+ dest.writeString(mKey);
+ } else {
+ dest.writeInt(0);
+ }
+ dest.writeInt(mImportance);
+ if (mExplanation != null) {
+ dest.writeInt(1);
+ dest.writeCharSequence(mExplanation);
+ } else {
+ dest.writeInt(0);
+ }
+ dest.writeParcelable(mReference, flags);
+ dest.writeBundle(mSignals);
+ }
+}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index afdd1d4..e708b0a 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -69,6 +69,12 @@
* <action android:name="android.service.notification.NotificationListenerService" />
* </intent-filter>
* </service></pre>
+ *
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing any operations. The {@link #requestRebind(ComponentName)}
+ * method is the <i>only</i> one that is safe to call before {@link #onListenerConnected()}
+ * or after {@link #onListenerDisconnected()}.
+ * </p>
*/
public abstract class NotificationListenerService extends Service {
// TAG = "NotificationListenerService[MySubclass]"
@@ -117,6 +123,16 @@
* This does not change the interruption filter, only the effects. **/
public static final int HINT_HOST_DISABLE_EFFECTS = 1;
+ /** {@link #getCurrentListenerHints() Listener hints} constant - the primary device UI
+ * should disable notification sound, but not phone calls.
+ * This does not change the interruption filter, only the effects. **/
+ public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 1 << 1;
+
+ /** {@link #getCurrentListenerHints() Listener hints} constant - the primary device UI
+ * should disable phone call sounds, buyt not notification sound.
+ * This does not change the interruption filter, only the effects. **/
+ public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 1 << 2;
+
/**
* Whether notification suppressed by DND should not interruption visually when the screen is
* off.
@@ -164,6 +180,7 @@
/** @hide */
protected NotificationListenerWrapper mWrapper = null;
+ private boolean isConnected = false;
@GuardedBy("mLock")
private RankingMap mRankingMap;
@@ -222,10 +239,10 @@
/**
* Implement this method to learn when notifications are removed.
- * <P>
+ * <p>
* This might occur because the user has dismissed the notification using system UI (or another
* notification listener) or because the app has withdrawn the notification.
- * <P>
+ * <p>
* NOTE: The {@link StatusBarNotification} object you receive will be "light"; that is, the
* result from {@link StatusBarNotification#getNotification} may be missing some heavyweight
* fields such as {@link android.app.Notification#contentView} and
@@ -243,10 +260,10 @@
/**
* Implement this method to learn when notifications are removed.
- * <P>
+ * <p>
* This might occur because the user has dismissed the notification using system UI (or another
* notification listener) or because the app has withdrawn the notification.
- * <P>
+ * <p>
* NOTE: The {@link StatusBarNotification} object you receive will be "light"; that is, the
* result from {@link StatusBarNotification#getNotification} may be missing some heavyweight
* fields such as {@link android.app.Notification#contentView} and
@@ -275,6 +292,15 @@
}
/**
+ * Implement this method to learn about when the listener is disconnected from the
+ * notification manager.You will not receive any events after this call, and may only
+ * call {@link #requestRebind(ComponentName)} at this time.
+ */
+ public void onListenerDisconnected() {
+ // optional
+ }
+
+ /**
* Implement this method to be notified when the notification ranking changes.
*
* @param rankingMap The current ranking map that can be used to retrieve ranking information
@@ -322,12 +348,15 @@
* It should be called after the user dismisses a single notification using your UI;
* upon being informed, the notification manager will actually remove the notification
* and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback.
- * <P>
+ * <p>
* <b>Note:</b> If your listener allows the user to fire a notification's
* {@link android.app.Notification#contentIntent} by tapping/clicking/etc., you should call
* this method at that time <i>if</i> the Notification in question has the
* {@link android.app.Notification#FLAG_AUTO_CANCEL} flag set.
*
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing this operation.
+ *
* @param pkg Package of the notifying app.
* @param tag Tag of the notification as specified by the notifying app in
* {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
@@ -357,12 +386,16 @@
* It should be called after the user dismisses a single notification using your UI;
* upon being informed, the notification manager will actually remove the notification
* and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback.
- * <P>
+ * <p>
* <b>Note:</b> If your listener allows the user to fire a notification's
* {@link android.app.Notification#contentIntent} by tapping/clicking/etc., you should call
* this method at that time <i>if</i> the Notification in question has the
* {@link android.app.Notification#FLAG_AUTO_CANCEL} flag set.
* <p>
+ *
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing this operation.
+ *
* @param key Notification to dismiss from {@link StatusBarNotification#getKey()}.
*/
public final void cancelNotification(String key) {
@@ -384,6 +417,9 @@
* upon being informed, the notification manager will actually remove all active notifications
* and you will get multiple {@link #onNotificationRemoved(StatusBarNotification)} callbacks.
*
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing this operation.
+ *
* {@see #cancelNotification(String, String, int)}
*/
public final void cancelAllNotifications() {
@@ -396,6 +432,9 @@
* Use this if your listener has a user interface that allows the user to dismiss
* multiple notifications at once.
*
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing this operation.
+ *
* @param keys Notifications to dismiss, or {@code null} to dismiss all.
*
* {@see #cancelNotification(String, String, int)}
@@ -414,6 +453,10 @@
* user. This should only be called when there is sufficient confidence that the user is
* looking at the notifications, such as when the notifications appear on the screen due to
* an explicit user interaction.
+ *
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing this operation.
+ *
* @param keys Notifications to mark as seen.
*/
public final void setNotificationsShown(String[] keys) {
@@ -436,6 +479,9 @@
* <p>
* Set to {@link #TRIM_FULL} initially.
*
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing this operation.
+ *
* @hide
*
* @param trim trim of the notifications to be passed via {@link #onNotificationPosted}.
@@ -455,6 +501,9 @@
* Request the list of outstanding notifications (that is, those that are visible to the
* current user). Useful when you don't know what's already been posted.
*
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing this operation.
+ *
* @return An array of active notifications, sorted in natural order.
*/
public StatusBarNotification[] getActiveNotifications() {
@@ -480,6 +529,9 @@
* notifications but didn't want to retain the bits, and now need to go back and extract
* more data out of those notifications.
*
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing this operation.
+ *
* @param keys the keys of the notifications to request
* @return An array of notifications corresponding to the requested keys, in the
* same order as the key list.
@@ -545,6 +597,9 @@
* shared across all listeners or a feature the notification host does not support or refuses
* to grant.
*
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing this operation.
+ *
* @return Zero or more of the HINT_ constants.
*/
public final int getCurrentListenerHints() {
@@ -572,6 +627,9 @@
* <p>
* Listen for updates using {@link #onInterruptionFilterChanged(int)}.
*
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing this operation.
+ *
* @return One of the INTERRUPTION_FILTER_ constants, or INTERRUPTION_FILTER_UNKNOWN when
* unavailable.
*/
@@ -594,6 +652,9 @@
* <p>
* Listen for updates using {@link #onListenerHintsChanged(int)}.
*
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing this operation.
+ *
* @param hints One or more of the HINT_ constants.
*/
public final void requestListenerHints(int hints) {
@@ -614,6 +675,9 @@
* <p>
* Listen for updates using {@link #onInterruptionFilterChanged(int)}.
*
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing this operation.
+ *
* @param interruptionFilter One of the INTERRUPTION_FILTER_ constants.
*/
public final void requestInterruptionFilter(int interruptionFilter) {
@@ -640,6 +704,9 @@
* such events, for example to retrieve the RankingMap right after
* initialization.
*
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing this operation.
+ *
* @return A {@link RankingMap} object providing access to ranking information
*/
public RankingMap getCurrentRanking() {
@@ -648,6 +715,12 @@
}
}
+ /**
+ * This is not the lifecycle event you are looking for.
+ *
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing any operations.
+ */
@Override
public IBinder onBind(Intent intent) {
if (mWrapper == null) {
@@ -665,6 +738,12 @@
return true;
}
+ @Override
+ public void onDestroy() {
+ onListenerDisconnected();
+ super.onDestroy();
+ }
+
/**
* Directly register this service with the Notification Manager.
*
@@ -693,7 +772,7 @@
/**
* Directly unregister this service from the Notification Manager.
*
- * <P>This method will fail for listeners that were not registered
+ * <p>This method will fail for listeners that were not registered
* with (@link registerAsService).
* @hide
*/
@@ -708,11 +787,8 @@
/**
* Request that the listener be rebound, after a previous call to (@link requestUnbind).
*
- * <P>This method will fail for listeners that have
+ * <p>This method will fail for listeners that have
* not been granted the permission by the user.
- *
- * <P>The service should wait for the {@link #onListenerConnected()} event
- * before performing any operations.
*/
public static void requestRebind(ComponentName componentName)
throws RemoteException {
@@ -724,14 +800,19 @@
/**
* Request that the service be unbound.
*
- * <P>This will no longer receive updates until
+ * <p>This will no longer receive updates until
* {@link #requestRebind(ComponentName)} is called.
* The service will likely be kiled by the system after this call.
+ *
+ * <p>The service should wait for the {@link #onListenerConnected()} event
+ * before performing this operation. I know it's tempting, but you must wait.
*/
public final void requestUnbind() throws RemoteException {
if (mWrapper != null) {
INotificationManager noMan = getNotificationInterface();
noMan.requestUnbindListener(mWrapper);
+ // Disable future messages.
+ isConnected = false;
}
}
@@ -842,6 +923,7 @@
synchronized (mLock) {
applyUpdateLocked(update);
}
+ isConnected = true;
mHandler.obtainMessage(MyHandler.MSG_ON_LISTENER_CONNECTED).sendToTarget();
}
@@ -980,6 +1062,8 @@
private int mSuppressedVisualEffects;
private @Importance int mImportance;
private CharSequence mImportanceExplanation;
+ // System specified group key.
+ private String mOverrideGroupKey;
public Ranking() {}
@@ -1058,9 +1142,17 @@
return mImportanceExplanation;
}
+ /**
+ * If the system has overriden the group key, then this will be non-null, and this
+ * key should be used to bundle notifications.
+ */
+ public String getOverrideGroupKey() {
+ return mOverrideGroupKey;
+ }
+
private void populate(String key, int rank, boolean matchesInterruptionFilter,
int visibilityOverride, int suppressedVisualEffects, int importance,
- CharSequence explanation) {
+ CharSequence explanation, String overrideGroupKey) {
mKey = key;
mRank = rank;
mIsAmbient = importance < IMPORTANCE_LOW;
@@ -1069,6 +1161,7 @@
mSuppressedVisualEffects = suppressedVisualEffects;
mImportance = importance;
mImportanceExplanation = explanation;
+ mOverrideGroupKey = overrideGroupKey;
}
/**
@@ -1112,6 +1205,7 @@
private ArrayMap<String, Integer> mSuppressedVisualEffects;
private ArrayMap<String, Integer> mImportance;
private ArrayMap<String, String> mImportanceExplanation;
+ private ArrayMap<String, String> mOverrideGroupKeys;
private RankingMap(NotificationRankingUpdate rankingUpdate) {
mRankingUpdate = rankingUpdate;
@@ -1138,7 +1232,7 @@
int rank = getRank(key);
outRanking.populate(key, rank, !isIntercepted(key),
getVisibilityOverride(key), getSuppressedVisualEffects(key),
- getImportance(key), getImportanceExplanation(key));
+ getImportance(key), getImportanceExplanation(key), getOverrideGroupKey(key));
return rank >= 0;
}
@@ -1209,6 +1303,15 @@
return mImportanceExplanation.get(key);
}
+ private String getOverrideGroupKey(String key) {
+ synchronized (this) {
+ if (mOverrideGroupKeys == null) {
+ buildOverrideGroupKeys();
+ }
+ }
+ return mOverrideGroupKeys.get(key);
+ }
+
// Locked by 'this'
private void buildRanksLocked() {
String[] orderedKeys = mRankingUpdate.getOrderedKeys();
@@ -1263,6 +1366,15 @@
}
}
+ // Locked by 'this'
+ private void buildOverrideGroupKeys() {
+ Bundle overrideGroupKeys = mRankingUpdate.getOverrideGroupKeys();
+ mOverrideGroupKeys = new ArrayMap<>(overrideGroupKeys.size());
+ for (String key: overrideGroupKeys.keySet()) {
+ mOverrideGroupKeys.put(key, overrideGroupKeys.getString(key));
+ }
+ }
+
// ----------- Parcelable
@Override
@@ -1303,6 +1415,9 @@
@Override
public void handleMessage(Message msg) {
+ if (!isConnected) {
+ return;
+ }
switch (msg.what) {
case MSG_ON_NOTIFICATION_POSTED: {
SomeArgs args = (SomeArgs) msg.obj;
diff --git a/core/java/android/service/notification/NotificationRankerService.java b/core/java/android/service/notification/NotificationRankerService.java
index 47fdac6..ee5361a 100644
--- a/core/java/android/service/notification/NotificationRankerService.java
+++ b/core/java/android/service/notification/NotificationRankerService.java
@@ -22,14 +22,19 @@
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.util.Log;
import com.android.internal.os.SomeArgs;
+import java.util.List;
+
/**
* A service that helps the user manage notifications. This class is only used to
* extend the framework service and may not be implemented by non-framework components.
@@ -91,27 +96,8 @@
/** Notification was canceled by the owning managed profile being turned off. */
public static final int REASON_PROFILE_TURNED_OFF = 15;
- public class Adjustment {
- int mImportance;
- CharSequence mExplanation;
- Uri mReference;
-
- /**
- * Create a notification importance adjustment.
- *
- * @param importance The final importance of the notification.
- * @param explanation A human-readable justification for the adjustment.
- * @param reference A reference to an external object that augments the
- * explanation, such as a
- * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI},
- * or null.
- */
- public Adjustment(int importance, CharSequence explanation, Uri reference) {
- mImportance = importance;
- mExplanation = explanation;
- mReference = reference;
- }
- }
+ /** Autobundled summary notification was canceled because its group was unbundled */
+ public static final int REASON_UNAUTOBUNDLED = 16;
private Handler mHandler;
@@ -200,18 +186,32 @@
}
/**
- * Change the importance of an existing notification. N.B. this won’t cause
+ * Updates a notification. N.B. this won’t cause
* an existing notification to alert, but might allow a future update to
* this notification to alert.
*
- * @param key the notification key
- * @param adjustment the new importance with an explanation
+ * @param adjustment the adjustment with an explanation
*/
- public final void adjustImportance(String key, Adjustment adjustment) {
+ public final void adjustNotification(Adjustment adjustment) {
if (!isBound()) return;
try {
- getNotificationInterface().setImportanceFromRankerService(mWrapper, key,
- adjustment.mImportance, adjustment.mExplanation);
+ getNotificationInterface().applyAdjustmentFromRankerService(mWrapper, adjustment);
+ } catch (android.os.RemoteException ex) {
+ Log.v(TAG, "Unable to contact notification manager", ex);
+ }
+ }
+
+ /**
+ * Updates existing notifications. Re-ranking won't occur until all adjustments are applied.
+ * N.B. this won’t cause an existing notification to alert, but might allow a future update to
+ * these notifications to alert.
+ *
+ * @param adjustments a list of adjustments with explanations
+ */
+ public final void adjustNotifications(List<Adjustment> adjustments) {
+ if (!isBound()) return;
+ try {
+ getNotificationInterface().applyAdjustmentsFromRankerService(mWrapper, adjustments);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
}
@@ -299,7 +299,7 @@
args.recycle();
Adjustment adjustment = onNotificationEnqueued(sbn, importance, user);
if (adjustment != null) {
- adjustImportance(sbn.getKey(), adjustment);
+ adjustNotification(adjustment);
}
} break;
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index 79f6fc4..788b5c0 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -30,16 +30,18 @@
private final Bundle mSuppressedVisualEffects;
private final int[] mImportance;
private final Bundle mImportanceExplanation;
+ private final Bundle mOverrideGroupKeys;
public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
Bundle visibilityOverrides, Bundle suppressedVisualEffects,
- int[] importance, Bundle explanation) {
+ int[] importance, Bundle explanation, Bundle overrideGroupKeys) {
mKeys = keys;
mInterceptedKeys = interceptedKeys;
mVisibilityOverrides = visibilityOverrides;
mSuppressedVisualEffects = suppressedVisualEffects;
mImportance = importance;
mImportanceExplanation = explanation;
+ mOverrideGroupKeys = overrideGroupKeys;
}
public NotificationRankingUpdate(Parcel in) {
@@ -50,6 +52,7 @@
mImportance = new int[mKeys.length];
in.readIntArray(mImportance);
mImportanceExplanation = in.readBundle();
+ mOverrideGroupKeys = in.readBundle();
}
@Override
@@ -65,6 +68,7 @@
out.writeBundle(mSuppressedVisualEffects);
out.writeIntArray(mImportance);
out.writeBundle(mImportanceExplanation);
+ out.writeBundle(mOverrideGroupKeys);
}
public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -101,4 +105,8 @@
public Bundle getImportanceExplanation() {
return mImportanceExplanation;
}
+
+ public Bundle getOverrideGroupKeys() {
+ return mOverrideGroupKeys;
+ }
}
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 198e43d..0221b66 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -33,7 +33,8 @@
private final int id;
private final String tag;
private final String key;
- private final String groupKey;
+ private String groupKey;
+ private String overrideGroupKey;
private final int uid;
private final String opPkg;
@@ -51,6 +52,27 @@
System.currentTimeMillis());
}
+ /** @hide */
+ public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid,
+ int initialPid, Notification notification, UserHandle user, String overrideGroupKey,
+ long postTime) {
+ if (pkg == null) throw new NullPointerException();
+ if (notification == null) throw new NullPointerException();
+
+ this.pkg = pkg;
+ this.opPkg = opPkg;
+ this.id = id;
+ this.tag = tag;
+ this.uid = uid;
+ this.initialPid = initialPid;
+ this.notification = notification;
+ this.user = user;
+ this.postTime = postTime;
+ this.overrideGroupKey = overrideGroupKey;
+ this.key = key();
+ this.groupKey = groupKey();
+ }
+
public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid,
int initialPid, int score, Notification notification, UserHandle user,
long postTime) {
@@ -84,15 +106,27 @@
this.notification = new Notification(in);
this.user = UserHandle.readFromParcel(in);
this.postTime = in.readLong();
+ if (in.readInt() != 0) {
+ this.overrideGroupKey = in.readString();
+ } else {
+ this.overrideGroupKey = null;
+ }
this.key = key();
this.groupKey = groupKey();
}
private String key() {
- return user.getIdentifier() + "|" + pkg + "|" + id + "|" + tag + "|" + uid;
+ String sbnKey = user.getIdentifier() + "|" + pkg + "|" + id + "|" + tag + "|" + uid;
+ if (overrideGroupKey != null && getNotification().isGroupSummary()) {
+ sbnKey = sbnKey + "|" + overrideGroupKey;
+ }
+ return sbnKey;
}
private String groupKey() {
+ if (overrideGroupKey != null) {
+ return user.getIdentifier() + "|" + pkg + "|" + "g:" + overrideGroupKey;
+ }
final String group = getNotification().getGroup();
final String sortKey = getNotification().getSortKey();
if (group == null && sortKey == null) {
@@ -105,6 +139,17 @@
: "g:" + group);
}
+ /**
+ * Returns true if this notification is part of a group.
+ */
+ public boolean isGroup() {
+ if (overrideGroupKey != null || getNotification().getGroup() != null
+ || getNotification().getSortKey() != null) {
+ return true;
+ }
+ return false;
+ }
+
public void writeToParcel(Parcel out, int flags) {
out.writeString(this.pkg);
out.writeString(this.opPkg);
@@ -121,6 +166,12 @@
user.writeToParcel(out, flags);
out.writeLong(this.postTime);
+ if (this.overrideGroupKey != null) {
+ out.writeInt(1);
+ out.writeString(this.overrideGroupKey);
+ } else {
+ out.writeInt(0);
+ }
}
public int describeContents() {
@@ -149,22 +200,22 @@
this.notification.cloneInto(no, false); // light copy
return new StatusBarNotification(this.pkg, this.opPkg,
this.id, this.tag, this.uid, this.initialPid,
- 0, no, this.user, this.postTime);
+ no, this.user, this.overrideGroupKey, this.postTime);
}
@Override
public StatusBarNotification clone() {
return new StatusBarNotification(this.pkg, this.opPkg,
this.id, this.tag, this.uid, this.initialPid,
- 0, this.notification.clone(), this.user, this.postTime);
+ this.notification.clone(), this.user, this.overrideGroupKey, this.postTime);
}
@Override
public String toString() {
return String.format(
- "StatusBarNotification(pkg=%s user=%s id=%d tag=%s score=%d key=%s: %s)",
+ "StatusBarNotification(pkg=%s user=%s id=%d tag=%s key=%s: %s)",
this.pkg, this.user, this.id, this.tag,
- 0, this.key, this.notification);
+ this.key, this.notification);
}
/** Convenience method to check the notification's flags for
@@ -258,6 +309,21 @@
}
/**
+ * Sets the override group key.
+ */
+ public void setOverrideGroupKey(String overrideGroupKey) {
+ this.overrideGroupKey = overrideGroupKey;
+ groupKey = groupKey();
+ }
+
+ /**
+ * Returns the override group key.
+ */
+ public String getOverrideGroupKey() {
+ return overrideGroupKey;
+ }
+
+ /**
* @hide
*/
public Context getPackageContext(Context context) {
diff --git a/core/java/android/service/quicksettings/IQSService.aidl b/core/java/android/service/quicksettings/IQSService.aidl
index 5434e2e..747f185 100644
--- a/core/java/android/service/quicksettings/IQSService.aidl
+++ b/core/java/android/service/quicksettings/IQSService.aidl
@@ -28,7 +28,6 @@
String contentDescription);
void onShowDialog(in Tile tile);
void onStartActivity(in Tile tile);
- void setTileMode(in ComponentName component, int mode);
boolean isLocked();
boolean isSecure();
void startUnlockAndRun(in Tile tile);
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index 553d539..4e9a075 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -89,28 +89,24 @@
public static final String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";
/**
- * The tile mode hasn't been set yet.
- * @hide
- */
- public static final int TILE_MODE_UNSET = 0;
-
- /**
- * Constant to be returned by {@link #onTileAdded}.
- * <p>
- * Passive mode is the default mode for tiles. The System will tell the tile
- * when it is most important to update by putting it in the listening state.
- */
- public static final int TILE_MODE_PASSIVE = 1;
-
- /**
- * Constant to be returned by {@link #onTileAdded}.
+ * Meta-data for tile definition to set a tile into active mode.
* <p>
* Active mode is for tiles which already listen and keep track of their state in their
* own process. These tiles may request to send an update to the System while their process
* is alive using {@link #requestListeningState}. The System will only bind these tiles
* on its own when a click needs to occur.
+ *
+ * To make a TileService an active tile, set this meta-data to true on the TileService's
+ * manifest declaration.
+ * <pre class="prettyprint">
+ * {@literal
+ * <meta-data android:name="android.service.quicksettings.ACTIVE_TILE"
+ * android:value="true" />
+ * }
+ * </pre>
*/
- public static final int TILE_MODE_ACTIVE = 2;
+ public static final String META_DATA_ACTIVE_TILE
+ = "android.service.quicksettings.ACTIVE_TILE";
/**
* Used to notify SysUI that Listening has be requested.
@@ -147,12 +143,8 @@
* Note that this is not guaranteed to be called between {@link #onCreate()}
* and {@link #onStartListening()}, it will only be called when the tile is added
* and not on subsequent binds.
- *
- * @see #TILE_MODE_PASSIVE
- * @see #TILE_MODE_ACTIVE
*/
- public int onTileAdded() {
- return TILE_MODE_PASSIVE;
+ public void onTileAdded() {
}
/**
@@ -386,15 +378,7 @@
}
break;
case MSG_TILE_ADDED:
- int mode = TileService.this.onTileAdded();
- if (mService == null) {
- return;
- }
- try {
- mService.setTileMode(new ComponentName(TileService.this,
- TileService.this.getClass()), mode);
- } catch (RemoteException e) {
- }
+ TileService.this.onTileAdded();
break;
case MSG_TILE_REMOVED:
if (mListening) {
@@ -431,8 +415,8 @@
/**
* Requests that a tile be put in the listening state so it can send an update.
*
- * This method is only applicable to tiles that return {@link #TILE_MODE_ACTIVE} from
- * {@link #onTileAdded()}, and will do nothing otherwise.
+ * This method is only applicable to tiles that have {@link #META_DATA_ACTIVE_TILE} defined
+ * as true on their TileService Manifest declaration, and will do nothing otherwise.
*/
public static final void requestListeningState(Context context, ComponentName component) {
Intent intent = new Intent(ACTION_REQUEST_LISTENING);
diff --git a/core/java/android/util/PathParser.java b/core/java/android/util/PathParser.java
index 29a72fd..f1c8c7d 100644
--- a/core/java/android/util/PathParser.java
+++ b/core/java/android/util/PathParser.java
@@ -31,12 +31,7 @@
throw new IllegalArgumentException("Path string can not be null.");
}
Path path = new Path();
- boolean hasValidPathData = nParseStringForPath(path.mNativePath, pathString,
- pathString.length());
- if (!hasValidPathData) {
- throw new IllegalArgumentException("Path string: " + pathString +
- " does not contain valid path data");
- }
+ nParseStringForPath(path.mNativePath, pathString, pathString.length());
return path;
}
@@ -104,7 +99,6 @@
}
super.finalize();
}
-
}
/**
@@ -123,7 +117,7 @@
}
// Native functions are defined below.
- private static native boolean nParseStringForPath(long pathPtr, String pathString,
+ private static native void nParseStringForPath(long pathPtr, String pathString,
int stringLength);
private static native void nCreatePathFromPathData(long outPathPtr, long pathData);
private static native long nCreateEmptyPathData();
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index e0c6770..636384c 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1870,6 +1870,11 @@
return keyCode == KeyEvent.KEYCODE_META_LEFT || keyCode == KeyEvent.KEYCODE_META_RIGHT;
}
+ /** @hide */
+ public static final boolean isAltKey(int keyCode) {
+ return keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT;
+ }
+
/** {@inheritDoc} */
@Override
public final int getDeviceId() {
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index df774b4..f44d4c1a 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -485,15 +485,25 @@
}
/**
- * Stops any rendering into the surface. Use this if it is unclear whether
+ * Halts any current rendering into the surface. Use this if it is unclear whether
* or not the surface used by the HardwareRenderer will be changing. It
- * Suspends any rendering into the surface, but will not do any destruction
+ * Suspends any rendering into the surface, but will not do any destruction.
+ *
+ * Any subsequent draws will override the pause, resuming normal operation.
*/
boolean pauseSurface(Surface surface) {
return nPauseSurface(mNativeProxy, surface);
}
/**
+ * Hard stops or resumes rendering into the surface. This flag is used to
+ * determine whether or not it is safe to use the given surface *at all*
+ */
+ void setStopped(boolean stopped) {
+ nSetStopped(mNativeProxy, stopped);
+ }
+
+ /**
* Destroys all hardware rendering resources associated with the specified
* view hierarchy.
*
@@ -794,8 +804,7 @@
}
final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
- int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length,
- mRootNode.mNativeRenderNode);
+ int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
setEnabled(false);
attachInfo.mViewRootImpl.mSurface.release();
@@ -989,13 +998,13 @@
private static native void nInitialize(long nativeProxy, Surface window);
private static native void nUpdateSurface(long nativeProxy, Surface window);
private static native boolean nPauseSurface(long nativeProxy, Surface window);
+ private static native void nSetStopped(long nativeProxy, boolean stopped);
private static native void nSetup(long nativeProxy, int width, int height,
float lightRadius, int ambientShadowAlpha, int spotShadowAlpha);
private static native void nSetLightCenter(long nativeProxy,
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,
- long rootRenderNode);
+ private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
private static native void nDestroy(long nativeProxy, long rootRenderNode);
private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b95d830..7e51096 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8877,7 +8877,7 @@
* @hide
*/
public void clearAccessibilityFocus() {
- clearAccessibilityFocusNoCallbacks();
+ clearAccessibilityFocusNoCallbacks(0);
// Clear the global reference of accessibility focus if this view or
// any of its descendants had accessibility focus. This will NOT send
@@ -8920,14 +8920,27 @@
/**
* Clears accessibility focus without calling any callback methods
* normally invoked in {@link #clearAccessibilityFocus()}. This method
- * is used for clearing accessibility focus when giving this focus to
- * another view.
+ * is used separately from that one for clearing accessibility focus when
+ * giving this focus to another view.
+ *
+ * @param action The action, if any, that led to focus being cleared. Set to
+ * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
+ * the window.
*/
- void clearAccessibilityFocusNoCallbacks() {
+ void clearAccessibilityFocusNoCallbacks(int action) {
if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
invalidate();
- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+ if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+ AccessibilityEvent event = AccessibilityEvent.obtain(
+ AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+ event.setAction(action);
+ if (mAccessibilityDelegate != null) {
+ mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
+ } else {
+ sendAccessibilityEventUnchecked(event);
+ }
+ }
}
}
@@ -20424,21 +20437,21 @@
* the touch point.
* </p>
*
- * @param shadowSize A {@link android.graphics.Point} containing the width and height
+ * @param outShadowSize A {@link android.graphics.Point} containing the width and height
* of the shadow image. Your application must set {@link android.graphics.Point#x} to the
* desired width and must set {@link android.graphics.Point#y} to the desired height of the
* image.
*
- * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
+ * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
* shadow image that should be underneath the touch point during the drag and drop
* operation. Your application must set {@link android.graphics.Point#x} to the
* X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
*/
- public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
+ public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
final View view = mView.get();
if (view != null) {
- shadowSize.set(view.getWidth(), view.getHeight());
- shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
+ outShadowSize.set(view.getWidth(), view.getHeight());
+ outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
} else {
Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
}
diff --git a/core/java/android/view/ViewAnimationUtils.java b/core/java/android/view/ViewAnimationUtils.java
index 4c75935..3e277eb 100644
--- a/core/java/android/view/ViewAnimationUtils.java
+++ b/core/java/android/view/ViewAnimationUtils.java
@@ -41,6 +41,22 @@
* As a result {@link AnimatorListener#onAnimationEnd(Animator)}
* will occur after the animation has ended, but it may be delayed depending
* on thread responsiveness.
+ * <p>
+ * Note that if any start delay is set on the reveal animator, the start radius
+ * will not be applied to the reveal circle until the start delay has passed.
+ * If it's desired to set a start radius on the reveal circle during the start
+ * delay, one workaround could be adding an animator with the same start and
+ * end radius. For example:
+ * <pre><code>
+ * public static Animator createRevealWithDelay(View view, int centerX, int centerY, float startRadius, float endRadius) {
+ * Animator delayAnimator = ViewAnimationUtils.createCircularReveal(view, centerX, centerY, startRadius, startRadius);
+ * delayAnimator.setDuration(delayTimeMS);
+ * Animator revealAnimator = ViewAnimationUtils.createCircularReveal(view, centerX, centerY, startRadius, endRadius);
+ * AnimatorSet set = new AnimatorSet();
+ * set.playSequentially(delayAnimator, revealAnimator);
+ * return set;
+ * }
+ * </code></pre>
*
* @param view The View will be clipped to the animating circle.
* @param centerX The x coordinate of the center of the animating circle, relative to
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 5b2877f..94c4cef 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1079,13 +1079,16 @@
void setWindowStopped(boolean stopped) {
if (mStopped != stopped) {
mStopped = stopped;
+ final ThreadedRenderer renderer = mAttachInfo.mHardwareRenderer;
+ if (renderer != null) {
+ if (DEBUG_DRAW) Log.d(mTag, "WindowStopped on " + getTitle() + " set to " + mStopped);
+ renderer.setStopped(mStopped);
+ }
if (!mStopped) {
scheduleTraversals();
} else {
- if (mAttachInfo.mHardwareRenderer != null) {
- if (DEBUG_DRAW) Log.d(mTag, "WindowStopped on " + getTitle());
- mAttachInfo.mHardwareRenderer.updateSurface(null);
- mAttachInfo.mHardwareRenderer.destroyHardwareResources(mView);
+ if (renderer != null) {
+ renderer.destroyHardwareResources(mView);
}
}
}
@@ -3071,7 +3074,8 @@
// Clear accessibility focus on the host after clearing state since
// this method may be reentrant.
- focusHost.clearAccessibilityFocusNoCallbacks();
+ focusHost.clearAccessibilityFocusNoCallbacks(
+ AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
AccessibilityNodeProvider provider = focusHost.getAccessibilityNodeProvider();
if (provider != null) {
@@ -3088,7 +3092,8 @@
}
if (mAccessibilityFocusedHost != null) {
// Clear accessibility focus in the view.
- mAccessibilityFocusedHost.clearAccessibilityFocusNoCallbacks();
+ mAccessibilityFocusedHost.clearAccessibilityFocusNoCallbacks(
+ AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
}
// Set the new focus host and node.
@@ -6623,7 +6628,7 @@
// Error state: virtual view with no provider. Clear focus.
mAccessibilityFocusedHost = null;
mAccessibilityFocusedVirtualView = null;
- focusedHost.clearAccessibilityFocusNoCallbacks();
+ focusedHost.clearAccessibilityFocusNoCallbacks(0);
return;
}
@@ -6673,7 +6678,7 @@
if (mAccessibilityFocusedVirtualView == null) {
// Error state: The node no longer exists. Clear focus.
mAccessibilityFocusedHost = null;
- focusedHost.clearAccessibilityFocusNoCallbacks();
+ focusedHost.clearAccessibilityFocusNoCallbacks(0);
// This will probably fail, but try to keep the provider's internal
// state consistent by clearing focus.
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index c372c30..584233c 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1240,6 +1240,13 @@
public static final int PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME = 0x00010000;
/**
+ * Flag to indicate that this window is always drawing the status bar background, no matter
+ * what the other flags are.
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND = 0x00020000;
+
+ /**
* Control flags that are private to the platform.
* @hide
*/
@@ -1701,6 +1708,14 @@
*/
public int accessibilityIdOfAnchor = -1;
+ /**
+ * The window title isn't kept in sync with what is displayed in the title bar, so we
+ * separately track the currently shown title to provide to accessibility.
+ *
+ * @hide
+ */
+ public CharSequence accessibilityTitle;
+
public LayoutParams() {
super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
type = TYPE_APPLICATION;
@@ -1749,6 +1764,7 @@
title = "";
mTitle = TextUtils.stringOrSpannedString(title);
+ accessibilityTitle = mTitle;
}
public final CharSequence getTitle() {
@@ -1808,6 +1824,7 @@
out.writeInt(hasManualSurfaceInsets ? 1 : 0);
out.writeInt(needsMenuKey);
out.writeInt(accessibilityIdOfAnchor);
+ TextUtils.writeToParcel(accessibilityTitle, out, parcelableFlags);
}
public static final Parcelable.Creator<LayoutParams> CREATOR
@@ -1859,6 +1876,7 @@
hasManualSurfaceInsets = in.readInt() != 0;
needsMenuKey = in.readInt();
accessibilityIdOfAnchor = in.readInt();
+ accessibilityTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
}
@SuppressWarnings({"PointlessBitwiseExpression"})
@@ -1900,6 +1918,8 @@
/** {@hide} */
public static final int ACCESSIBILITY_ANCHOR_CHANGED = 1 << 24;
/** {@hide} */
+ public static final int ACCESSIBILITY_TITLE_CHANGED = 1 << 25;
+ /** {@hide} */
public static final int EVERYTHING_CHANGED = 0xffffffff;
// internal buffer to backup/restore parameters under compatibility mode.
@@ -2065,6 +2085,13 @@
changes |= ACCESSIBILITY_ANCHOR_CHANGED;
}
+ if (!Objects.equals(accessibilityTitle, o.accessibilityTitle)
+ && o.accessibilityTitle != null) {
+ // NOTE: accessibilityTitle only copied if the originator set one.
+ accessibilityTitle = o.accessibilityTitle;
+ changes |= ACCESSIBILITY_TITLE_CHANGED;
+ }
+
return changes;
}
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index 1536c29..d89c172 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -93,8 +93,12 @@
*/
public static final int ZORDER_BOTTOM = -1;
- private static final boolean USE_CLOSEGUARD
- = SystemProperties.getBoolean("log.closeguard.Animation", false);
+ // Use a preload holder to isolate static initialization into inner class, which allows
+ // Animation and its subclasses to be compile-time initialized.
+ private static class NoImagePreloadHolder {
+ public static final boolean USE_CLOSEGUARD
+ = SystemProperties.getBoolean("log.closeguard.Animation", false);
+ }
/**
* Set by {@link #getTransformation(long, Transformation)} when the animation ends.
@@ -859,7 +863,7 @@
if (!mStarted) {
fireAnimationStart();
mStarted = true;
- if (USE_CLOSEGUARD) {
+ if (NoImagePreloadHolder.USE_CLOSEGUARD) {
guard.open("cancel or detach or getTransformation");
}
}
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java
index fd73432..24739bf 100644
--- a/core/java/android/view/inputmethod/CursorAnchorInfo.java
+++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java
@@ -16,6 +16,7 @@
package android.view.inputmethod;
+import android.annotation.NonNull;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.os.Parcel;
@@ -25,6 +26,7 @@
import android.text.TextUtils;
import android.view.inputmethod.SparseRectFArray.SparseRectFArrayBuilder;
+import java.util.Arrays;
import java.util.Objects;
/**
@@ -36,6 +38,11 @@
*/
public final class CursorAnchorInfo implements Parcelable {
/**
+ * The pre-computed hash code.
+ */
+ private final int mHashCode;
+
+ /**
* The index of the first character of the selected text (inclusive). {@code -1} when there is
* no text selection.
*/
@@ -100,7 +107,8 @@
* Transformation matrix that is applied to any positional information of this class to
* transform local coordinates into screen coordinates.
*/
- private final Matrix mMatrix;
+ @NonNull
+ private final float[] mMatrixValues;
/**
* Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
@@ -121,6 +129,7 @@
public static final int FLAG_IS_RTL = 0x04;
public CursorAnchorInfo(final Parcel source) {
+ mHashCode = source.readInt();
mSelectionStart = source.readInt();
mSelectionEnd = source.readInt();
mComposingTextStart = source.readInt();
@@ -131,8 +140,7 @@
mInsertionMarkerBaseline = source.readFloat();
mInsertionMarkerBottom = source.readFloat();
mCharacterBoundsArray = source.readParcelable(SparseRectFArray.class.getClassLoader());
- mMatrix = new Matrix();
- mMatrix.setValues(source.createFloatArray());
+ mMatrixValues = source.createFloatArray();
}
/**
@@ -143,6 +151,7 @@
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mHashCode);
dest.writeInt(mSelectionStart);
dest.writeInt(mSelectionEnd);
dest.writeInt(mComposingTextStart);
@@ -153,27 +162,12 @@
dest.writeFloat(mInsertionMarkerBaseline);
dest.writeFloat(mInsertionMarkerBottom);
dest.writeParcelable(mCharacterBoundsArray, flags);
- final float[] matrixArray = new float[9];
- mMatrix.getValues(matrixArray);
- dest.writeFloatArray(matrixArray);
+ dest.writeFloatArray(mMatrixValues);
}
@Override
public int hashCode(){
- final float floatHash = mInsertionMarkerHorizontal + mInsertionMarkerTop
- + mInsertionMarkerBaseline + mInsertionMarkerBottom;
- int hash = floatHash > 0 ? (int) floatHash : (int)(-floatHash);
- hash *= 31;
- hash += mInsertionMarkerFlags;
- hash *= 31;
- hash += mSelectionStart + mSelectionEnd + mComposingTextStart;
- hash *= 31;
- hash += Objects.hashCode(mComposingText);
- hash *= 31;
- hash += Objects.hashCode(mCharacterBoundsArray);
- hash *= 31;
- hash += Objects.hashCode(mMatrix);
- return hash;
+ return mHashCode;
}
/**
@@ -202,13 +196,13 @@
if (hashCode() != that.hashCode()) {
return false;
}
+
+ // Check fields that are not covered by hashCode() first.
+
if (mSelectionStart != that.mSelectionStart || mSelectionEnd != that.mSelectionEnd) {
return false;
}
- if (mComposingTextStart != that.mComposingTextStart
- || !Objects.equals(mComposingText, that.mComposingText)) {
- return false;
- }
+
if (mInsertionMarkerFlags != that.mInsertionMarkerFlags
|| !areSameFloatImpl(mInsertionMarkerHorizontal, that.mInsertionMarkerHorizontal)
|| !areSameFloatImpl(mInsertionMarkerTop, that.mInsertionMarkerTop)
@@ -216,18 +210,35 @@
|| !areSameFloatImpl(mInsertionMarkerBottom, that.mInsertionMarkerBottom)) {
return false;
}
+
if (!Objects.equals(mCharacterBoundsArray, that.mCharacterBoundsArray)) {
return false;
}
- if (!Objects.equals(mMatrix, that.mMatrix)) {
+
+ // Following fields are (partially) covered by hashCode().
+
+ if (mComposingTextStart != that.mComposingTextStart
+ || !Objects.equals(mComposingText, that.mComposingText)) {
return false;
}
+
+ // We do not use Arrays.equals(float[], float[]) to keep the previous behavior regarding
+ // NaN, 0.0f, and -0.0f.
+ if (mMatrixValues.length != that.mMatrixValues.length) {
+ return false;
+ }
+ for (int i = 0; i < mMatrixValues.length; ++i) {
+ if (mMatrixValues[i] != that.mMatrixValues[i]) {
+ return false;
+ }
+ }
return true;
}
@Override
public String toString() {
- return "SelectionInfo{mSelection=" + mSelectionStart + "," + mSelectionEnd
+ return "CursorAnchorInfo{mHashCode=" + mHashCode
+ + " mSelection=" + mSelectionStart + "," + mSelectionEnd
+ " mComposingTextStart=" + mComposingTextStart
+ " mComposingText=" + Objects.toString(mComposingText)
+ " mInsertionMarkerFlags=" + mInsertionMarkerFlags
@@ -236,7 +247,7 @@
+ " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline
+ " mInsertionMarkerBottom=" + mInsertionMarkerBottom
+ " mCharacterBoundsArray=" + Objects.toString(mCharacterBoundsArray)
- + " mMatrix=" + Objects.toString(mMatrix)
+ + " mMatrix=" + Arrays.toString(mMatrixValues)
+ "}";
}
@@ -254,7 +265,7 @@
private float mInsertionMarkerBottom = Float.NaN;
private int mInsertionMarkerFlags = 0;
private SparseRectFArrayBuilder mCharacterBoundsArrayBuilder = null;
- private final Matrix mMatrix = new Matrix(Matrix.IDENTITY_MATRIX);
+ private float[] mMatrixValues = null;
private boolean mMatrixInitialized = false;
/**
@@ -349,7 +360,10 @@
* is interpreted as an identity matrix.
*/
public Builder setMatrix(final Matrix matrix) {
- mMatrix.set(matrix != null ? matrix : Matrix.IDENTITY_MATRIX);
+ if (mMatrixValues == null) {
+ mMatrixValues = new float[9];
+ }
+ (matrix != null ? matrix : Matrix.IDENTITY_MATRIX).getValues(mMatrixValues);
mMatrixInitialized = true;
return this;
}
@@ -391,7 +405,6 @@
mInsertionMarkerTop = Float.NaN;
mInsertionMarkerBaseline = Float.NaN;
mInsertionMarkerBottom = Float.NaN;
- mMatrix.set(Matrix.IDENTITY_MATRIX);
mMatrixInitialized = false;
if (mCharacterBoundsArrayBuilder != null) {
mCharacterBoundsArrayBuilder.reset();
@@ -411,7 +424,18 @@
mInsertionMarkerBottom = builder.mInsertionMarkerBottom;
mCharacterBoundsArray = builder.mCharacterBoundsArrayBuilder != null ?
builder.mCharacterBoundsArrayBuilder.build() : null;
- mMatrix = new Matrix(builder.mMatrix);
+ mMatrixValues = new float[9];
+ if (builder.mMatrixInitialized) {
+ System.arraycopy(builder.mMatrixValues, 0, mMatrixValues, 0, 9);
+ } else {
+ Matrix.IDENTITY_MATRIX.getValues(mMatrixValues);
+ }
+
+ // To keep hash function simple, we only use some complex objects for hash.
+ int hash = Objects.hashCode(mComposingText);
+ hash *= 31;
+ hash += Arrays.hashCode(mMatrixValues);
+ mHashCode = hash;
}
/**
@@ -527,7 +551,9 @@
* @return a new instance (copy) of the transformation matrix.
*/
public Matrix getMatrix() {
- return new Matrix(mMatrix);
+ final Matrix matrix = new Matrix();
+ matrix.setValues(mMatrixValues);
+ return matrix;
}
/**
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index a42f4d9..dc433b1 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -68,6 +68,7 @@
// TODO: remove this
private static final String EXTRA_KEY_UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME =
"UntranslatableReplacementStringInSubtypeName";
+ private static final int SUBTYPE_ID_NONE = 0;
private final boolean mIsAuxiliary;
private final boolean mOverridesImplicitlyEnabledSubtype;
@@ -157,13 +158,13 @@
* track of enabled subtypes by ID. When the IME package gets upgraded, enabled IDs will
* stay enabled even if other attributes are different. If the ID is unspecified or 0,
* Arrays.hashCode(new Object[] {locale, mode, extraValue,
- * isAuxiliary, overridesImplicitlyEnabledSubtype}) will be used instead.
+ * isAuxiliary, overridesImplicitlyEnabledSubtype, isAsciiCapable}) will be used instead.
*/
public InputMethodSubtypeBuilder setSubtypeId(int subtypeId) {
mSubtypeId = subtypeId;
return this;
}
- private int mSubtypeId = 0;
+ private int mSubtypeId = SUBTYPE_ID_NONE;
/**
* @param subtypeLocale is the locale supported by this subtype.
@@ -268,7 +269,7 @@
* subtypes by ID. When the IME package gets upgraded, enabled IDs will stay enabled even if
* other attributes are different. If the ID is unspecified or 0,
* Arrays.hashCode(new Object[] {locale, mode, extraValue,
- * isAuxiliary, overridesImplicitlyEnabledSubtype}) will be used instead.
+ * isAuxiliary, overridesImplicitlyEnabledSubtype, isAsciiCapable}) will be used instead.
*/
public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, int id) {
@@ -293,9 +294,12 @@
mIsAsciiCapable = builder.mIsAsciiCapable;
// If hashCode() of this subtype is 0 and you want to specify it as an id of this subtype,
// just specify 0 as this subtype's id. Then, this subtype's id is treated as 0.
- mSubtypeHashCode = mSubtypeId != 0 ? mSubtypeId : hashCodeInternal(mSubtypeLocale,
- mSubtypeMode, mSubtypeExtraValue, mIsAuxiliary, mOverridesImplicitlyEnabledSubtype,
- mIsAsciiCapable);
+ if (mSubtypeId != SUBTYPE_ID_NONE) {
+ mSubtypeHashCode = mSubtypeId;
+ } else {
+ mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue,
+ mIsAuxiliary, mOverridesImplicitlyEnabledSubtype, mIsAsciiCapable);
+ }
}
InputMethodSubtype(Parcel source) {
@@ -501,6 +505,22 @@
return mSubtypeHashCode;
}
+ /**
+ * @hide
+ * @return {@code true} if a valid subtype ID exists.
+ */
+ public final boolean hasSubtypeId() {
+ return mSubtypeId != SUBTYPE_ID_NONE;
+ }
+
+ /**
+ * @hide
+ * @return subtype ID. {@code 0} means that not subtype ID is specified.
+ */
+ public final int getSubtypeId() {
+ return mSubtypeId;
+ }
+
@Override
public boolean equals(Object o) {
if (o instanceof InputMethodSubtype) {
diff --git a/core/java/android/webkit/WebViewProviderResponse.java b/core/java/android/webkit/WebViewProviderResponse.java
index f5e09e2..c0aeb59 100644
--- a/core/java/android/webkit/WebViewProviderResponse.java
+++ b/core/java/android/webkit/WebViewProviderResponse.java
@@ -21,7 +21,7 @@
import android.os.Parcelable;
/** @hide */
-public class WebViewProviderResponse implements Parcelable {
+public final class WebViewProviderResponse implements Parcelable {
public WebViewProviderResponse(PackageInfo packageInfo, int status) {
this.packageInfo = packageInfo;
@@ -56,6 +56,6 @@
out.writeInt(status);
}
- PackageInfo packageInfo;
- int status;
+ public final PackageInfo packageInfo;
+ public final int status;
}
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index e3357a7..0c5edc5 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -339,7 +339,9 @@
*
* @return {@code true} if the calendar view is shown
* @see #getCalendarView()
+ * @deprecated Not supported by Material-style {@code calendar} mode
*/
+ @Deprecated
public boolean getCalendarViewShown() {
return mDelegate.getCalendarViewShown();
}
@@ -347,13 +349,18 @@
/**
* Returns the {@link CalendarView} used by this picker.
* <p>
- * <strong>Note:</strong> This method returns {@code null} when the
+ * <strong>Note:</strong> This method throws an
+ * {@link UnsupportedOperationException} when the
* {@link android.R.styleable#DatePicker_datePickerMode} attribute is set
* to {@code calendar}.
*
* @return the calendar view
* @see #getCalendarViewShown()
+ * @deprecated Not supported by Material-style {@code calendar} mode
+ * @throws UnsupportedOperationException if called when the picker is
+ * displayed in {@code calendar} mode
*/
+ @Deprecated
public CalendarView getCalendarView() {
return mDelegate.getCalendarView();
}
@@ -367,7 +374,9 @@
*
* @param shown {@code true} to show the calendar view, {@code false} to
* hide it
+ * @deprecated Not supported by Material-style {@code calendar} mode
*/
+ @Deprecated
public void setCalendarViewShown(boolean shown) {
mDelegate.setCalendarViewShown(shown);
}
@@ -380,7 +389,9 @@
* to {@code calendar}.
*
* @return {@code true} if the spinners are shown
+ * @deprecated Not supported by Material-style {@code calendar} mode
*/
+ @Deprecated
public boolean getSpinnersShown() {
return mDelegate.getSpinnersShown();
}
@@ -394,7 +405,9 @@
*
* @param shown {@code true} to show the spinners, {@code false} to hide
* them
+ * @deprecated Not supported by Material-style {@code calendar} mode
*/
+ @Deprecated
public void setSpinnersShown(boolean shown) {
mDelegate.setSpinnersShown(shown);
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 7055f78..440ef21 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1778,6 +1778,18 @@
if (translate) canvas.translate(0, -cursorOffsetVertical);
}
+ void invalidateHandlesAndActionMode() {
+ if (mSelectionModifierCursorController != null) {
+ mSelectionModifierCursorController.invalidateHandles();
+ }
+ if (mInsertionPointCursorController != null) {
+ mInsertionPointCursorController.invalidateHandle();
+ }
+ if (mTextActionMode != null) {
+ mTextActionMode.invalidate();
+ }
+ }
+
/**
* Invalidates all the sub-display lists that overlap the specified character range
*/
@@ -3462,7 +3474,6 @@
popupBackground.getPadding(mTempRect);
width += mTempRect.left + mTempRect.right;
}
- mSuggestionListView.getLayoutParams().width = width;
mPopupWindow.setWidth(width);
}
@@ -4104,6 +4115,14 @@
setMeasuredDimension(getPreferredWidth(), getPreferredHeight());
}
+ @Override
+ public void invalidate() {
+ super.invalidate();
+ if (isShowing()) {
+ positionAtCursorOffset(getCurrentCursorOffset(), true);
+ }
+ };
+
private int getPreferredWidth() {
return Math.max(mDrawable.getIntrinsicWidth(), mMinSize);
}
@@ -4170,7 +4189,12 @@
return mTextView.getOffsetAtCoordinate(line, x);
}
- protected void positionAtCursorOffset(int offset, boolean parentScrolled) {
+ /**
+ * @param offset Cursor offset. Must be in [-1, length].
+ * @param forceUpdatePosition whether to force update the position. This should be true
+ * when If the parent has been scrolled, for example.
+ */
+ protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition) {
// A HandleView relies on the layout, which may be nulled by external methods
Layout layout = mTextView.getLayout();
if (layout == null) {
@@ -4181,7 +4205,7 @@
layout = mTextView.getLayout();
boolean offsetChanged = offset != mPreviousOffset;
- if (offsetChanged || parentScrolled) {
+ if (offsetChanged || forceUpdatePosition) {
if (offsetChanged) {
updateSelection(offset);
addPositionToTouchUpFilter(offset);
@@ -4782,13 +4806,9 @@
mPrevX = x;
}
- /**
- * @param offset Cursor offset. Must be in [-1, length].
- * @param parentScrolled If the parent has been scrolled or not.
- */
@Override
- protected void positionAtCursorOffset(int offset, boolean parentScrolled) {
- super.positionAtCursorOffset(offset, parentScrolled);
+ protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition) {
+ super.positionAtCursorOffset(offset, forceUpdatePosition);
mInWord = (offset != -1) && !getWordIteratorWithText().isBoundary(offset);
}
@@ -5014,6 +5034,12 @@
public boolean isActive() {
return mHandle != null && mHandle.isShowing();
}
+
+ public void invalidateHandle() {
+ if (mHandle != null) {
+ mHandle.invalidate();
+ }
+ }
}
class SelectionModifierCursorController implements CursorController {
@@ -5418,6 +5444,15 @@
public boolean isActive() {
return mStartHandle != null && mStartHandle.isShowing();
}
+
+ public void invalidateHandles() {
+ if (mStartHandle != null) {
+ mStartHandle.invalidate();
+ }
+ if (mEndHandle != null) {
+ mEndHandle.invalidate();
+ }
+ }
}
private class CorrectionHighlighter {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 4483b7ba..48fd58b 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3350,7 +3350,10 @@
mShadowColor = color;
// Will change text clip region
- if (mEditor != null) mEditor.invalidateTextDisplayList();
+ if (mEditor != null) {
+ mEditor.invalidateTextDisplayList();
+ mEditor.invalidateHandlesAndActionMode();
+ }
invalidate();
}
@@ -8306,6 +8309,7 @@
if (mEditor != null) {
if (oldStart >= 0) mEditor.invalidateTextDisplayList(mLayout, oldStart, oldEnd);
if (newStart >= 0) mEditor.invalidateTextDisplayList(mLayout, newStart, newEnd);
+ mEditor.invalidateHandlesAndActionMode();
}
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index a4e489c..ed6ab56 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -41,12 +41,12 @@
import android.os.IBinder;
import android.os.Message;
import android.os.Parcelable;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
-import android.provider.DocumentsContract;
import android.service.chooser.ChooserTarget;
import android.service.chooser.ChooserTargetService;
import android.service.chooser.IChooserTargetResult;
@@ -70,6 +70,7 @@
import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.google.android.collect.Lists;
import java.io.File;
import java.util.ArrayList;
@@ -89,6 +90,7 @@
private IntentSender mChosenComponentSender;
private IntentSender mRefinementIntentSender;
private RefinementResultReceiver mRefinementResultReceiver;
+ private ChooserTarget[] mCallerChooserTargets;
private Intent mReferrerFillInIntent;
@@ -97,6 +99,7 @@
private SharedPreferences mPinnedSharedPrefs;
private static final float PINNED_TARGET_SCORE_BOOST = 1000.f;
+ private static final float CALLER_TARGET_SCORE_BOOST = 900.f;
private static final String PINNED_SHARED_PREFS_NAME = "chooser_pin_settings";
private static final String TARGET_DETAILS_FRAGMENT_TAG = "targetDetailsFragment";
@@ -219,6 +222,34 @@
Intent.EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER);
setSafeForwardingMode(true);
+ pa = intent.getParcelableArrayExtra(Intent.EXTRA_EXCLUDE_COMPONENTS);
+ if (pa != null) {
+ ComponentName[] names = new ComponentName[pa.length];
+ for (int i = 0; i < pa.length; i++) {
+ if (!(pa[i] instanceof ComponentName)) {
+ Log.w(TAG, "Filtered component #" + i + " not a ComponentName: " + pa[i]);
+ names = null;
+ break;
+ }
+ names[i] = (ComponentName) pa[i];
+ }
+ setFilteredComponents(names);
+ }
+
+ pa = intent.getParcelableArrayExtra(Intent.EXTRA_CHOOSER_TARGETS);
+ if (pa != null) {
+ ChooserTarget[] targets = new ChooserTarget[pa.length];
+ for (int i = 0; i < pa.length; i++) {
+ if (!(pa[i] instanceof ChooserTarget)) {
+ Log.w(TAG, "Chooser target #" + i + " not a ChooserTarget: " + pa[i]);
+ targets = null;
+ break;
+ }
+ targets[i] = (ChooserTarget) pa[i];
+ }
+ mCallerChooserTargets = targets;
+ }
+
mPinnedSharedPrefs = getPinnedSharedPrefs(this);
super.onCreate(savedInstanceState, target, title, defaultTitleRes, initialIntents,
null, false);
@@ -292,6 +323,9 @@
boolean alwaysUseOption) {
final ListView listView = adapterView instanceof ListView ? (ListView) adapterView : null;
mChooserListAdapter = (ChooserListAdapter) adapter;
+ if (mCallerChooserTargets != null && mCallerChooserTargets.length > 0) {
+ mChooserListAdapter.addServiceResults(null, Lists.newArrayList(mCallerChooserTargets));
+ }
mChooserRowAdapter = new ChooserRowAdapter(mChooserListAdapter);
mChooserRowAdapter.registerDataSetObserver(new OffsetDataSetObserver(adapterView));
adapterView.setAdapter(mChooserRowAdapter);
@@ -427,13 +461,19 @@
continue;
}
} catch (NameNotFoundException e) {
- Log.e(TAG, "Could not look up service " + serviceComponent, e);
+ Log.e(TAG, "Could not look up service " + serviceComponent
+ + "; component name not found");
continue;
}
final ChooserTargetServiceConnection conn =
new ChooserTargetServiceConnection(this, dri);
- if (bindService(serviceIntent, conn, BIND_AUTO_CREATE | BIND_NOT_FOREGROUND)) {
+
+ // Explicitly specify Process.myUserHandle instead of calling bindService
+ // to avoid the warning from calling from the system process without an explicit
+ // user handle
+ if (bindServiceAsUser(serviceIntent, conn, BIND_AUTO_CREATE | BIND_NOT_FOREGROUND,
+ Process.myUserHandle())) {
if (DEBUG) {
Log.d(TAG, "Binding service connection for target " + dri
+ " intent " + serviceIntent);
@@ -635,7 +675,11 @@
if (mSourceInfo != null) {
return mSourceInfo.getResolvedIntent();
}
- return getTargetIntent();
+
+ final Intent targetIntent = new Intent(getTargetIntent());
+ targetIntent.setComponent(mChooserTarget.getComponentName());
+ targetIntent.putExtras(mChooserTarget.getIntentExtras());
+ return targetIntent;
}
@Override
@@ -650,8 +694,7 @@
}
private Intent getBaseIntentToSend() {
- Intent result = mSourceInfo != null
- ? mSourceInfo.getResolvedIntent() : getTargetIntent();
+ Intent result = getResolvedIntent();
if (result == null) {
Log.e(TAG, "ChooserTargetInfo: no base intent available to send");
} else {
@@ -677,7 +720,19 @@
}
intent.setComponent(mChooserTarget.getComponentName());
intent.putExtras(mChooserTarget.getIntentExtras());
- activity.startActivityAsCaller(intent, options, true, userId);
+
+ // Important: we will ignore the target security checks in ActivityManager
+ // if and only if the ChooserTarget's target package is the same package
+ // where we got the ChooserTargetService that provided it. This lets a
+ // ChooserTargetService provide a non-exported or permission-guarded target
+ // to the chooser for the user to pick.
+ //
+ // If mSourceInfo is null, we got this ChooserTarget from the caller or elsewhere
+ // so we'll obey the caller's normal security checks.
+ final boolean ignoreTargetSecurity = mSourceInfo != null
+ && mSourceInfo.getResolvedComponentName().getPackageName()
+ .equals(mChooserTarget.getComponentName().getPackageName());
+ activity.startActivityAsCaller(intent, options, ignoreTargetSecurity, userId);
return true;
}
@@ -810,6 +865,9 @@
@Override
public float getScore(DisplayResolveInfo target) {
+ if (target == null) {
+ return CALLER_TARGET_SCORE_BOOST;
+ }
float score = super.getScore(target);
if (target.isPinned()) {
score += PINNED_TARGET_SCORE_BOOST;
@@ -1281,7 +1339,7 @@
}
static class ChooserTargetServiceConnection implements ServiceConnection {
- private final DisplayResolveInfo mOriginalTarget;
+ private DisplayResolveInfo mOriginalTarget;
private ComponentName mConnectedComponent;
private ChooserActivity mChooserActivity;
private final Object mLock = new Object();
@@ -1359,6 +1417,7 @@
public void destroy() {
synchronized (mLock) {
mChooserActivity = null;
+ mOriginalTarget = null;
}
}
@@ -1366,7 +1425,9 @@
public String toString() {
return "ChooserTargetServiceConnection{service="
+ mConnectedComponent + ", activity="
- + mOriginalTarget.getResolveInfo().activityInfo.toString() + "}";
+ + (mOriginalTarget != null
+ ? mOriginalTarget.getResolveInfo().activityInfo.toString()
+ : "<connection destroyed>") + "}";
}
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index ff680e2..f2bf9e1 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -105,6 +105,7 @@
private final ArrayList<Intent> mIntents = new ArrayList<>();
private ResolverComparator mResolverComparator;
private PickTargetOptionRequest mPickOptionRequest;
+ private ComponentName[] mFilteredComponents;
protected ResolverDrawerLayout mResolverDrawerLayout;
@@ -332,6 +333,24 @@
}
}
+ public final void setFilteredComponents(ComponentName[] components) {
+ mFilteredComponents = components;
+ }
+
+ public final boolean isComponentFiltered(ComponentInfo component) {
+ if (mFilteredComponents == null) {
+ return false;
+ }
+
+ final ComponentName checkName = component.getComponentName();
+ for (ComponentName name : mFilteredComponents) {
+ if (name.equals(checkName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Perform any initialization needed for voice interaction.
*/
@@ -1269,7 +1288,8 @@
ai.applicationInfo.uid, ai.exported);
boolean suspended = (ai.applicationInfo.flags
& ApplicationInfo.FLAG_SUSPENDED) != 0;
- if (granted != PackageManager.PERMISSION_GRANTED || suspended) {
+ if (granted != PackageManager.PERMISSION_GRANTED || suspended
+ || isComponentFiltered(ai)) {
// Access not allowed!
if (mOrigResolveList == currentResolveList) {
mOrigResolveList = new ArrayList<>(mOrigResolveList);
diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
index f6fbaab..27588e9 100644
--- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java
+++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -53,6 +54,7 @@
private int mUserId;
private int mReason;
+ private IntentSender mTarget;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -60,6 +62,7 @@
Intent intent = getIntent();
mReason = intent.getIntExtra(EXTRA_UNLAUNCHABLE_REASON, -1);
mUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+ mTarget = intent.getParcelableExtra(Intent.EXTRA_INTENT);
if (mUserId == UserHandle.USER_NULL) {
Log.wtf(TAG, "Invalid user id: " + mUserId + ". Stopping.");
@@ -105,6 +108,14 @@
public void onClick(DialogInterface dialog, int which) {
if (mReason == UNLAUNCHABLE_REASON_QUIET_MODE && which == DialogInterface.BUTTON_POSITIVE) {
UserManager.get(this).setQuietModeEnabled(mUserId, false);
+
+ if (mTarget != null) {
+ try {
+ startIntentSenderForResult(mTarget, -1, null, 0, 0, 0);
+ } catch (IntentSender.SendIntentException e) {
+ /* ignore */
+ }
+ }
}
}
@@ -121,4 +132,10 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
return intent;
}
+
+ public static Intent createInQuietModeDialogIntent(int userId, IntentSender target) {
+ Intent intent = createInQuietModeDialogIntent(userId);
+ intent.putExtra(Intent.EXTRA_INTENT, target);
+ return intent;
+ }
}
diff --git a/core/java/com/android/internal/app/procstats/SparseMappingTable.java b/core/java/com/android/internal/app/procstats/SparseMappingTable.java
index 7252276..76102af 100644
--- a/core/java/com/android/internal/app/procstats/SparseMappingTable.java
+++ b/core/java/com/android/internal/app/procstats/SparseMappingTable.java
@@ -372,29 +372,35 @@
* Throw an exception if one of a variety of internal consistency checks fails.
*/
private void assertConsistency() {
- // Assert that our sequewnce number has been initialized. If it hasn't
- // that means someone tried to read or write data without allocating it
- // since we were created or reset.
- if (mSequence == UNINITIALIZED_SEQUENCE) {
- logOrThrow("mSequence == UNINITIALIZED_SEQUENCE in"
- + " SparseMappingTable.Table. -- "
- + dumpInternalState());
- return;
- }
+ // Something with this checking isn't working and is triggering
+ // more problems than it's helping to debug.
+ // Original bug: b/27045736
+ // New bug: b/27960286
+ if (false) {
+ // Assert that our sequence number has been initialized. If it hasn't
+ // that means someone tried to read or write data without allocating it
+ // since we were created or reset.
+ if (mSequence == UNINITIALIZED_SEQUENCE) {
+ logOrThrow("mSequence == UNINITIALIZED_SEQUENCE in"
+ + " SparseMappingTable.Table. -- "
+ + dumpInternalState());
+ return;
+ }
- // Assert that our sequence number matches mParent's. If it isn't that means
- // we have been reset and our
- if (mSequence != mParent.mSequence) {
- if (mSequence < mParent.mSequence) {
- logOrThrow("Sequence mismatch. SparseMappingTable.resetTable()"
- + " called but not Table.resetTable() -- "
- + dumpInternalState());
- return;
- } else if (mSequence > mParent.mSequence) {
- logOrThrow("Sequence mismatch. Table.resetTable()"
- + " called but not SparseMappingTable.resetTable() -- "
- + dumpInternalState());
- return;
+ // Assert that our sequence number matches mParent's. If it isn't that means
+ // we have been reset and our
+ if (mSequence != mParent.mSequence) {
+ if (mSequence < mParent.mSequence) {
+ logOrThrow("Sequence mismatch. SparseMappingTable.resetTable()"
+ + " called but not Table.resetTable() -- "
+ + dumpInternalState());
+ return;
+ } else if (mSequence > mParent.mSequence) {
+ logOrThrow("Sequence mismatch. Table.resetTable()"
+ + " called but not SparseMappingTable.resetTable() -- "
+ + dumpInternalState());
+ return;
+ }
}
}
}
@@ -623,7 +629,7 @@
* this is an eng build.)
*/
private static void logOrThrow(String message, Throwable th) {
- Slog.wtf(TAG, message, th);
+ Slog.e(TAG, message, th);
if (Build.TYPE.equals("eng")) {
throw new RuntimeException(message, th);
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
index 85cc841..46b49de 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -285,7 +285,7 @@
}
public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme,
- InputMethodInfo imi, InputMethodSubtype subtype) {
+ InputMethodInfo imi, InputMethodSubtype subtype, boolean forward) {
if (imi == null) {
return null;
}
@@ -297,8 +297,9 @@
return null;
}
final int N = mImeSubtypeList.size();
- for (int offset = 1; offset < N; ++offset) {
+ for (int i = 1; i < N; ++i) {
// Start searching the next IME/subtype from the next of the current index.
+ final int offset = forward ? i : N - i;
final int candidateIndex = (currentIndex + offset) % N;
final ImeSubtypeListItem candidate = mImeSubtypeList.get(candidateIndex);
// Skip if searching inside the current IME only, but the candidate is not
@@ -371,7 +372,7 @@
}
public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme,
- InputMethodInfo imi, InputMethodSubtype subtype) {
+ InputMethodInfo imi, InputMethodSubtype subtype, boolean forward) {
int currentUsageRank = getUsageRank(imi, subtype);
if (currentUsageRank < 0) {
if (DEBUG) {
@@ -381,7 +382,8 @@
}
final int N = mUsageHistoryOfSubtypeListItemIndex.length;
for (int i = 1; i < N; i++) {
- final int subtypeListItemRank = (currentUsageRank + i) % N;
+ final int offset = forward ? i : N - i;
+ final int subtypeListItemRank = (currentUsageRank + offset) % N;
final int subtypeListItemIndex =
mUsageHistoryOfSubtypeListItemIndex[subtypeListItemRank];
final ImeSubtypeListItem subtypeListItem =
@@ -455,16 +457,16 @@
}
public ImeSubtypeListItem getNextInputMethod(boolean onlyCurrentIme, InputMethodInfo imi,
- InputMethodSubtype subtype) {
+ InputMethodSubtype subtype, boolean forward) {
if (imi == null) {
return null;
}
if (imi.supportsSwitchingToNextInputMethod()) {
return mSwitchingAwareRotationList.getNextInputMethodLocked(onlyCurrentIme, imi,
- subtype);
+ subtype, forward);
} else {
return mSwitchingUnawareRotationList.getNextInputMethodLocked(onlyCurrentIme, imi,
- subtype);
+ subtype, forward);
}
}
@@ -532,14 +534,14 @@
}
public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, InputMethodInfo imi,
- InputMethodSubtype subtype) {
+ InputMethodSubtype subtype, boolean forward) {
if (mController == null) {
if (DEBUG) {
Log.e(TAG, "mController shouldn't be null.");
}
return null;
}
- return mController.getNextInputMethod(onlyCurrentIme, imi, subtype);
+ return mController.getNextInputMethod(onlyCurrentIme, imi, subtype, forward);
}
public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeListLocked(
diff --git a/core/java/com/android/internal/os/BackgroundThread.java b/core/java/com/android/internal/os/BackgroundThread.java
index d6f7b20..cffba01 100644
--- a/core/java/com/android/internal/os/BackgroundThread.java
+++ b/core/java/com/android/internal/os/BackgroundThread.java
@@ -18,6 +18,7 @@
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.Trace;
/**
* Shared singleton background thread for each process.
@@ -34,6 +35,7 @@
if (sInstance == null) {
sInstance = new BackgroundThread();
sInstance.start();
+ sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
sHandler = new Handler(sInstance.getLooper());
}
}
diff --git a/core/java/com/android/internal/os/InstallerConnection.java b/core/java/com/android/internal/os/InstallerConnection.java
index 2a9264d..47f2c70 100644
--- a/core/java/com/android/internal/os/InstallerConnection.java
+++ b/core/java/com/android/internal/os/InstallerConnection.java
@@ -103,21 +103,7 @@
}
}
- public void execute(String cmd, Object... args) throws InstallerException {
- final String resRaw = executeForResult(cmd, args);
- int res = -1;
- try {
- res = Integer.parseInt(resRaw);
- } catch (NumberFormatException ignored) {
- }
- if (res != 0) {
- throw new InstallerException(
- "Failed to execute " + cmd + " " + Arrays.toString(args) + ": " + res);
- }
- }
-
- public String executeForResult(String cmd, Object... args)
- throws InstallerException {
+ public String[] execute(String cmd, Object... args) throws InstallerException {
final StringBuilder builder = new StringBuilder(cmd);
for (Object arg : args) {
String escaped;
@@ -135,7 +121,17 @@
}
builder.append(' ').append(escaped);
}
- return transact(builder.toString());
+ final String[] resRaw = transact(builder.toString()).split(" ");
+ int res = -1;
+ try {
+ res = Integer.parseInt(resRaw[0]);
+ } catch (ArrayIndexOutOfBoundsException | NumberFormatException ignored) {
+ }
+ if (res != 0) {
+ throw new InstallerException(
+ "Failed to execute " + cmd + " " + Arrays.toString(args) + ": " + res);
+ }
+ return resRaw;
}
public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
@@ -160,19 +156,15 @@
}
public boolean mergeProfiles(int uid, String pkgName) throws InstallerException {
- String rawReply = executeForResult("merge_profiles", uid, pkgName);
- if (rawReply == null) {
- throw new IllegalStateException("Unexpected null reply");
- }
- final String res[] = rawReply.split(" ");
+ final String[] res = execute("merge_profiles", uid, pkgName);
if ((res == null) || (res.length != 2)) {
- throw new InstallerException("Invalid size result: " + rawReply);
+ throw new InstallerException("Invalid size result: " + Arrays.toString(res));
}
// Just as a sanity check. Anything != "true" will be interpreted as false by parseBoolean.
if (!res[1].equals("true") && !res[1].equals("false")) {
- throw new InstallerException("Invalid boolean result: " + rawReply);
+ throw new InstallerException("Invalid boolean result: " + Arrays.toString(res));
}
return Boolean.parseBoolean(res[1]);
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index ea0fbda..f9ac563 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -45,7 +45,6 @@
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.os.RemoteException;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -81,6 +80,8 @@
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.os.Build.VERSION_CODES.M;
+import static android.os.Build.VERSION_CODES.N;
import static android.view.View.MeasureSpec.AT_MOST;
import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.getMode;
@@ -171,7 +172,7 @@
private final Interpolator mShowInterpolator;
private final Interpolator mHideInterpolator;
private final int mBarEnterExitDuration;
- private final boolean mForceWindowDrawsStatusBarBackground;
+ final boolean mForceWindowDrawsStatusBarBackground;
private final int mSemiTransparentStatusBarColor;
private final BackgroundFallback mBackgroundFallback = new BackgroundFallback();
@@ -236,7 +237,8 @@
mBarEnterExitDuration = context.getResources().getInteger(
R.integer.dock_enter_exit_duration);
mForceWindowDrawsStatusBarBackground = context.getResources().getBoolean(
- R.bool.config_forceWindowDrawsStatusBarBackground);
+ R.bool.config_forceWindowDrawsStatusBarBackground)
+ && context.getApplicationInfo().targetSdkVersion >= N;
mSemiTransparentStatusBarColor = context.getResources().getColor(
R.color.system_bar_background_semi_transparent, null /* theme */);
@@ -1458,6 +1460,8 @@
st.menu.close();
}
+ releaseThreadedRenderer();
+
if (mWindowResizeCallbacksAdded) {
getViewRootImpl().removeWindowCallbacks(this);
mWindowResizeCallbacksAdded = false;
@@ -2208,7 +2212,7 @@
public void onDestroyActionMode(ActionMode mode) {
mWrapped.onDestroyActionMode(mode);
final boolean isMncApp = mContext.getApplicationInfo().targetSdkVersion
- >= Build.VERSION_CODES.M;
+ >= M;
final boolean isPrimary;
final boolean isFloating;
if (isMncApp) {
diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index 9907ea9..669e1ef 100644
--- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -17,9 +17,13 @@
package com.android.internal.policy;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
import android.util.Log;
+import android.view.Display;
+import android.view.DisplayInfo;
import java.util.ArrayList;
@@ -57,6 +61,7 @@
private final ArrayList<SnapTarget> mTargets = new ArrayList<>();
private final Rect mInsets = new Rect();
private final int mSnapMode;
+ private final int mMinimalSizeResizableTask;
private final float mFixedRatio;
private boolean mIsHorizontalDivision;
@@ -70,6 +75,22 @@
private final SnapTarget mDismissEndTarget;
private final SnapTarget mMiddleTarget;
+ public static DividerSnapAlgorithm create(Context ctx, Rect insets) {
+ DisplayInfo displayInfo = new DisplayInfo();
+ ctx.getSystemService(DisplayManager.class).getDisplay(
+ Display.DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
+ int dividerWindowWidth = ctx.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.docked_stack_divider_thickness);
+ int dividerInsets = ctx.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.docked_stack_divider_insets);
+ return new DividerSnapAlgorithm(ctx.getResources(),
+ displayInfo.logicalWidth, displayInfo.logicalHeight,
+ dividerWindowWidth - 2 * dividerInsets,
+ ctx.getResources().getConfiguration().orientation
+ == Configuration.ORIENTATION_PORTRAIT,
+ insets);
+ }
+
public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize,
boolean isHorizontalDivision, Rect insets) {
mMinFlingVelocityPxPerSecond =
@@ -85,6 +106,8 @@
com.android.internal.R.integer.config_dockedStackDividerSnapMode);
mFixedRatio = res.getFraction(
com.android.internal.R.fraction.docked_stack_divider_fixed_ratio, 1, 1);
+ mMinimalSizeResizableTask = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.default_minimal_size_resizable_task);
calculateTargets(isHorizontalDivision);
mFirstSplitTarget = mTargets.get(1);
mLastSplitTarget = mTargets.get(mTargets.size() - 2);
@@ -93,6 +116,20 @@
mMiddleTarget = mTargets.get(mTargets.size() / 2);
}
+ /**
+ * @return whether it's feasible to enable split screen in the current configuration, i.e. when
+ * snapping in the middle both tasks are larger than the minimal task size.
+ */
+ public boolean isSplitScreenFeasible() {
+ int statusBarSize = mInsets.top;
+ int navBarSize = mIsHorizontalDivision ? mInsets.bottom : mInsets.right;
+ int size = mIsHorizontalDivision
+ ? mDisplayHeight
+ : mDisplayWidth;
+ int availableSpace = size - navBarSize - statusBarSize - mDividerSize;
+ return availableSpace / 2 >= mMinimalSizeResizableTask;
+ }
+
public SnapTarget calculateSnapTarget(int position, float velocity) {
return calculateSnapTarget(position, velocity, true /* hardDismiss */);
}
@@ -212,10 +249,10 @@
mTargets.add(new SnapTarget(-mDividerSize, SnapTarget.FLAG_DISMISS_START, 0.35f));
switch (mSnapMode) {
case SNAP_MODE_16_9:
- addRatio16_9Targets(isHorizontalDivision);
+ addRatio16_9Targets(isHorizontalDivision, dividerMax);
break;
case SNAP_FIXED_RATIO:
- addFixedDivisionTargets(isHorizontalDivision);
+ addFixedDivisionTargets(isHorizontalDivision, dividerMax);
break;
case SNAP_ONLY_1_1:
addMiddleTarget(isHorizontalDivision);
@@ -225,19 +262,24 @@
mTargets.add(new SnapTarget(dividerMax - navBarSize, SnapTarget.FLAG_DISMISS_END, 0.35f));
}
- private void addFixedDivisionTargets(boolean isHorizontalDivision) {
+ private void addNonDismissingTargets(boolean isHorizontalDivision, int topPosition,
+ int bottomPosition, int dividerMax) {
+ maybeAddTarget(topPosition, topPosition - mInsets.top);
+ addMiddleTarget(isHorizontalDivision);
+ maybeAddTarget(bottomPosition, dividerMax - mInsets.bottom
+ - (bottomPosition + mDividerSize));
+ }
+ private void addFixedDivisionTargets(boolean isHorizontalDivision, int dividerMax) {
int start = isHorizontalDivision ? mInsets.top : mInsets.left;
int end = isHorizontalDivision
? mDisplayHeight - mInsets.bottom
: mDisplayWidth - mInsets.right;
- mTargets.add(new SnapTarget((int) (start + mFixedRatio * (end - start)) - mDividerSize / 2,
- SnapTarget.FLAG_NONE));
- addMiddleTarget(isHorizontalDivision);
- mTargets.add(new SnapTarget((int) (start + (1 - mFixedRatio) * (end - start))
- - mDividerSize / 2, SnapTarget.FLAG_NONE));
+ int topPosition = (int) (start + mFixedRatio * (end - start)) - mDividerSize / 2;
+ int bottomPosition = (int) (start + (1 - mFixedRatio) * (end - start)) - mDividerSize / 2;
+ addNonDismissingTargets(isHorizontalDivision, topPosition, bottomPosition, dividerMax);
}
- private void addRatio16_9Targets(boolean isHorizontalDivision) {
+ private void addRatio16_9Targets(boolean isHorizontalDivision, int dividerMax) {
int start = isHorizontalDivision ? mInsets.top : mInsets.left;
int end = isHorizontalDivision
? mDisplayHeight - mInsets.bottom
@@ -248,9 +290,19 @@
: mDisplayHeight - mInsets.bottom;
float size = 9.0f / 16.0f * (endOther - startOther);
int sizeInt = (int) Math.floor(size);
- mTargets.add(new SnapTarget(start + sizeInt, SnapTarget.FLAG_NONE));
- addMiddleTarget(isHorizontalDivision);
- mTargets.add(new SnapTarget(end - sizeInt - mDividerSize, SnapTarget.FLAG_NONE));
+ int topPosition = start + sizeInt;
+ int bottomPosition = end - sizeInt - mDividerSize;
+ addNonDismissingTargets(isHorizontalDivision, topPosition, bottomPosition, dividerMax);
+ }
+
+ /**
+ * Adds a target at {@param position} but only if the area with size of {@param smallerSize}
+ * meets the minimal size requirement.
+ */
+ private void maybeAddTarget(int position, int smallerSize) {
+ if (smallerSize >= mMinimalSizeResizableTask) {
+ mTargets.add(new SnapTarget(position, SnapTarget.FLAG_NONE));
+ }
}
private void addMiddleTarget(boolean isHorizontalDivision) {
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 0f257d7..d2ff9bc4 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -516,8 +516,8 @@
}
mTitle = title;
WindowManager.LayoutParams params = getAttributes();
- if (!TextUtils.equals(title, params.getTitle())) {
- params.setTitle(title);
+ if (!TextUtils.equals(title, params.accessibilityTitle)) {
+ params.accessibilityTitle = TextUtils.stringOrSpannedString(title);
dispatchWindowAttributesChanged(getAttributes());
}
}
@@ -2435,6 +2435,8 @@
mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
}
+ WindowManager.LayoutParams params = getAttributes();
+
// Non-floating windows on high end devices must put up decor beneath the system bars and
// therefore must know about visibility changes of those.
if (!mIsFloating && ActivityManager.isHighEndGfx()) {
@@ -2444,6 +2446,9 @@
setFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS & ~getForcedWindowFlags());
}
+ if (mDecor.mForceWindowDrawsStatusBarBackground) {
+ params.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+ }
}
if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) {
decor.setSystemUiVisibility(
@@ -2459,8 +2464,6 @@
}
}
- WindowManager.LayoutParams params = getAttributes();
-
if (!hasSoftInputMode()) {
params.softInputMode = a.getInt(
R.styleable.Window_windowSoftInputMode,
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index bed5a2e..18f715e 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.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -128,7 +129,7 @@
/**
* Checks if given array is null or has zero elements.
*/
- public static boolean isEmpty(@Nullable List<?> array) {
+ public static boolean isEmpty(@Nullable Collection<?> array) {
return array == null || array.isEmpty();
}
@@ -451,7 +452,7 @@
}
}
- public static <T> boolean contains(@Nullable ArrayList<T> cur, T val) {
+ public static <T> boolean contains(@Nullable Collection<T> cur, T val) {
return (cur != null) ? cur.contains(val) : false;
}
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index 5992f7a..b075db8 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -57,7 +57,7 @@
public static final int BASE_DATA_CONNECTION = 0x00040000;
public static final int BASE_DATA_CONNECTION_AC = 0x00041000;
public static final int BASE_DATA_CONNECTION_TRACKER = 0x00042000;
- public static final int BASE_DNS_PINGER = 0x00050000;
+ public static final int BASE_TETHERING = 0x00050000;
public static final int BASE_NSD_MANAGER = 0x00060000;
public static final int BASE_NETWORK_STATE_TRACKER = 0x00070000;
public static final int BASE_CONNECTIVITY_MANAGER = 0x00080000;
diff --git a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
index 29a9c8e..ddca51f 100644
--- a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
@@ -346,7 +346,15 @@
private void showMenu(@NonNull MenuBuilder menu) {
final LayoutInflater inflater = LayoutInflater.from(mContext);
final MenuAdapter adapter = new MenuAdapter(menu, inflater, mOverflowOnly);
- adapter.setForceShowIcon(mForceShowIcon);
+
+ // Apply "force show icon" setting; if the menu being shown is the top level menu, apply the
+ // setting set on this CascadingMenuPopup by its creating code. If it's a submenu, or if no
+ // "force" setting was explicitly set, determine the setting by examining the items.
+ if (!isShowing() && mForceShowIcon) {
+ adapter.setForceShowIcon(mForceShowIcon);
+ } else {
+ adapter.setForceShowIcon(MenuPopup.shouldPreserveIconSpacing(menu));
+ }
final int menuWidth = measureIndividualMenuWidth(adapter, null, mContext, mMenuMaxWidth);
final MenuPopupWindow popupWindow = createPopupWindow();
diff --git a/core/java/com/android/internal/view/menu/MenuPopup.java b/core/java/com/android/internal/view/menu/MenuPopup.java
index 42b1a56..16e4156 100644
--- a/core/java/com/android/internal/view/menu/MenuPopup.java
+++ b/core/java/com/android/internal/view/menu/MenuPopup.java
@@ -183,4 +183,25 @@
}
return (MenuAdapter) adapter;
}
+
+ /**
+ * Returns whether icon spacing needs to be preserved for the given menu, based on whether any
+ * of its items contains an icon.
+ * @param menu
+ * @return Whether to preserve icon spacing.
+ */
+ protected static boolean shouldPreserveIconSpacing(MenuBuilder menu) {
+ boolean preserveIconSpacing = false;
+ final int count = menu.size();
+
+ for (int i = 0; i < count; i++) {
+ MenuItem childItem = menu.getItem(i);
+ if (childItem.isVisible() && childItem.getIcon() != null) {
+ preserveIconSpacing = true;
+ break;
+ }
+ }
+
+ return preserveIconSpacing;
+ }
}
diff --git a/core/java/com/android/internal/view/menu/StandardMenuPopup.java b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
index 8ced36f..339c2bf 100644
--- a/core/java/com/android/internal/view/menu/StandardMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
@@ -208,7 +208,7 @@
@Override
public void show() {
if (!tryShow()) {
- throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor");
+ throw new IllegalStateException("StandardMenuPopup cannot be used without an anchor");
}
}
@@ -266,14 +266,14 @@
final MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu,
mShownAnchorView, mOverflowOnly, mPopupStyleAttr, mPopupStyleRes);
subPopup.setPresenterCallback(mPresenterCallback);
- subPopup.setForceShowIcon(mAdapter.getForceShowIcon());
+ subPopup.setForceShowIcon(MenuPopup.shouldPreserveIconSpacing(subMenu));
// Pass responsibility for handling onDismiss to the submenu.
subPopup.setOnDismissListener(mOnDismissListener);
mOnDismissListener = null;
// Close this menu popup to make room for the submenu popup.
- dismiss();
+ mMenu.close(false /* closeAllMenus */);
// Show the new sub-menu popup at the same location as this popup.
if (subPopup.tryShow(mXOffset, mYOffset)) {
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index b07e36a..21c4d12 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -33,9 +33,12 @@
void setLockPassword(in String password, in String savedPassword, int userId);
VerifyCredentialResponse checkPassword(in String password, int userId);
VerifyCredentialResponse verifyPassword(in String password, long challenge, int userId);
+ VerifyCredentialResponse verifyTiedProfileChallenge(String password, boolean isPattern, long challenge, int userId);
boolean checkVoldPassword(int userId);
boolean havePattern(int userId);
boolean havePassword(int userId);
+ void setSeparateProfileChallengeEnabled(int userId, boolean enabled, String managedUserPassword);
+ boolean getSeparateProfileChallengeEnabled(int userId);
void registerStrongAuthTracker(in IStrongAuthTracker tracker);
void unregisterStrongAuthTracker(in IStrongAuthTracker tracker);
void requireStrongAuth(int strongAuthReason, int userId);
diff --git a/core/java/com/android/internal/widget/LockPatternChecker.java b/core/java/com/android/internal/widget/LockPatternChecker.java
index 4880664..713f56f 100644
--- a/core/java/com/android/internal/widget/LockPatternChecker.java
+++ b/core/java/com/android/internal/widget/LockPatternChecker.java
@@ -145,6 +145,43 @@
}
/**
+ * Verify a password asynchronously.
+ *
+ * @param utils The LockPatternUtils instance to use.
+ * @param password The password to check.
+ * @param challenge The challenge to verify against the pattern.
+ * @param userId The user to check against the pattern.
+ * @param callback The callback to be invoked with the verification result.
+ */
+ public static AsyncTask<?, ?, ?> verifyTiedProfileChallenge(final LockPatternUtils utils,
+ final String password,
+ final boolean isPattern,
+ final long challenge,
+ final int userId,
+ final OnVerifyCallback callback) {
+ AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
+ private int mThrottleTimeout;
+
+ @Override
+ protected byte[] doInBackground(Void... args) {
+ try {
+ return utils.verifyTiedProfileChallenge(password, isPattern, challenge, userId);
+ } catch (RequestThrottledException ex) {
+ mThrottleTimeout = ex.getTimeoutMs();
+ return null;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(byte[] result) {
+ callback.onVerified(result, mThrottleTimeout);
+ }
+ };
+ task.execute();
+ return task;
+ }
+
+ /**
* Checks a password asynchronously.
*
* @param utils The LockPatternUtils instance to use.
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 3d892af..bceeaca 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -137,8 +137,6 @@
private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
private static final String IS_TRUST_USUALLY_MANAGED = "lockscreen.istrustusuallymanaged";
- private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
-
// Maximum allowed number of repeated or ordered characters in a sequence before we'll
// consider it a complex PIN/password.
public static final int MAX_ALLOWED_SEQUENCE = 3;
@@ -377,6 +375,36 @@
}
}
+
+ /**
+ * Check to see if a password matches the saved password.
+ * If password matches, return an opaque attestation that the challenge
+ * was verified.
+ *
+ * @param password The password to check.
+ * @param challenge The challenge to verify against the password
+ * @return the attestation that the challenge was verified, or null.
+ */
+ public byte[] verifyTiedProfileChallenge(String password, boolean isPattern, long challenge,
+ int userId) throws RequestThrottledException {
+ throwIfCalledOnMainThread();
+ try {
+ VerifyCredentialResponse response =
+ getLockSettings().verifyTiedProfileChallenge(password, isPattern, challenge,
+ userId);
+
+ if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
+ return response.getPayload();
+ } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
+ throw new RequestThrottledException(response.getTimeout());
+ } else {
+ return null;
+ }
+ } catch (RemoteException re) {
+ return null;
+ }
+ }
+
/**
* Check to see if a password matches the saved password. If no password exists,
* always returns true.
@@ -785,6 +813,7 @@
}
getLockSettings().setLockPassword(password, savedPassword, userHandle);
+ getLockSettings().setSeparateProfileChallengeEnabled(userHandle, true, null);
int computedQuality = computePasswordQuality(password);
// Update the device encryption password.
@@ -919,11 +948,23 @@
/**
* Enables/disables the Separate Profile Challenge for this {@param userHandle}. This is a no-op
* for user handles that do not belong to a managed profile.
+ *
+ * @param userHandle Managed profile user id
+ * @param enabled True if separate challenge is enabled
+ * @param managedUserPassword Managed profile previous password. Null when {@param enabled} is
+ * true
*/
- public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled) {
+ public void setSeparateProfileChallengeEnabled(int userHandle, boolean enabled,
+ String managedUserPassword) {
UserInfo info = getUserManager().getUserInfo(userHandle);
if (info.isManagedProfile()) {
- setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userHandle);
+ try {
+ getLockSettings().setSeparateProfileChallengeEnabled(userHandle, enabled,
+ managedUserPassword);
+ onAfterChangingPassword(userHandle);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't update work profile challenge enabled");
+ }
}
}
@@ -935,7 +976,13 @@
if (info == null || !info.isManagedProfile()) {
return false;
}
- return getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userHandle);
+ try {
+ return getLockSettings().getSeparateProfileChallengeEnabled(userHandle);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't get separate profile challenge enabled");
+ // Default value is false
+ return false;
+ }
}
/**
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 6dc251c..1c2d13d 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -53,36 +53,14 @@
fontFamily->Unref();
}
-static jboolean addSkTypeface(FontFamily* family, SkTypeface* face) {
- MinikinFont* minikinFont = new MinikinFontSkia(face);
+static jboolean addSkTypeface(FontFamily* family, SkTypeface* face, const void* fontData,
+ size_t fontSize, int ttcIndex) {
+ MinikinFont* minikinFont = new MinikinFontSkia(face, fontData, fontSize, ttcIndex);
bool result = family->addFont(minikinFont);
minikinFont->Unref();
return result;
}
-static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong familyPtr, jstring path,
- jint ttcIndex) {
- NPE_CHECK_RETURN_ZERO(env, path);
- ScopedUtfChars str(env, path);
- SkTypeface* face = SkTypeface::CreateFromFile(str.c_str(), ttcIndex);
- if (face == NULL) {
- ALOGE("addFont failed to create font %s", str.c_str());
- return false;
- }
- FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr);
- return addSkTypeface(fontFamily, face);
-}
-
-static struct {
- jmethodID mGet;
- jmethodID mSize;
-} gListClassInfo;
-
-static struct {
- jfieldID mTag;
- jfieldID mStyleValue;
-} gAxisClassInfo;
-
static void release_global_ref(const void* /*data*/, void* context) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
bool needToAttach = (env == NULL);
@@ -106,6 +84,47 @@
}
}
+static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong familyPtr, jobject bytebuf,
+ jint ttcIndex) {
+ NPE_CHECK_RETURN_ZERO(env, bytebuf);
+ const void* fontPtr = env->GetDirectBufferAddress(bytebuf);
+ if (fontPtr == NULL) {
+ ALOGE("addFont failed to create font, buffer invalid");
+ return false;
+ }
+ jlong fontSize = env->GetDirectBufferCapacity(bytebuf);
+ if (fontSize < 0) {
+ ALOGE("addFont failed to create font, buffer size invalid");
+ return false;
+ }
+ jobject fontRef = MakeGlobalRefOrDie(env, bytebuf);
+ SkAutoTUnref<SkData> data(SkData::NewWithProc(fontPtr, fontSize,
+ release_global_ref, reinterpret_cast<void*>(fontRef)));
+ std::unique_ptr<SkStreamAsset> fontData(new SkMemoryStream(data));
+
+ SkFontMgr::FontParameters params;
+ params.setCollectionIndex(ttcIndex);
+
+ SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
+ SkTypeface* face = fm->createFromStream(fontData.release(), params);
+ if (face == NULL) {
+ ALOGE("addFont failed to create font");
+ return false;
+ }
+ FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr);
+ return addSkTypeface(fontFamily, face, fontPtr, (size_t)fontSize, ttcIndex);
+}
+
+static struct {
+ jmethodID mGet;
+ jmethodID mSize;
+} gListClassInfo;
+
+static struct {
+ jfieldID mTag;
+ jfieldID mStyleValue;
+} gAxisClassInfo;
+
static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong familyPtr,
jobject font, jint ttcIndex, jobject listOfAxis, jint weight, jboolean isItalic) {
NPE_CHECK_RETURN_ZERO(env, font);
@@ -133,7 +152,7 @@
}
}
- void* fontPtr = env->GetDirectBufferAddress(font);
+ const void* fontPtr = env->GetDirectBufferAddress(font);
if (fontPtr == NULL) {
ALOGE("addFont failed to create font, buffer invalid");
return false;
@@ -159,7 +178,7 @@
return false;
}
FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr);
- MinikinFont* minikinFont = new MinikinFontSkia(face);
+ MinikinFont* minikinFont = new MinikinFontSkia(face, fontPtr, (size_t)fontSize, ttcIndex);
fontFamily->addFont(minikinFont, FontStyle(weight / 100, isItalic));
minikinFont->Unref();
return true;
@@ -191,6 +210,7 @@
return false;
}
+ size_t bufSize = asset->getLength();
SkAutoTUnref<SkData> data(SkData::NewWithProc(buf, asset->getLength(), releaseAsset, asset));
SkMemoryStream* stream = new SkMemoryStream(data);
// CreateFromStream takes ownership of stream.
@@ -200,7 +220,7 @@
return false;
}
FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr);
- return addSkTypeface(fontFamily, face);
+ return addSkTypeface(fontFamily, face, buf, bufSize, /* ttcIndex */ 0);
}
///////////////////////////////////////////////////////////////////////////////
@@ -208,7 +228,7 @@
static const JNINativeMethod gFontFamilyMethods[] = {
{ "nCreateFamily", "(Ljava/lang/String;I)J", (void*)FontFamily_create },
{ "nUnrefFamily", "(J)V", (void*)FontFamily_unref },
- { "nAddFont", "(JLjava/lang/String;I)Z", (void*)FontFamily_addFont },
+ { "nAddFont", "(JLjava/nio/ByteBuffer;I)Z", (void*)FontFamily_addFont },
{ "nAddFontWeightStyle", "(JLjava/nio/ByteBuffer;ILjava/util/List;IZ)Z",
(void*)FontFamily_addFontWeightStyle },
{ "nAddFontFromAsset", "(JLandroid/content/res/AssetManager;Ljava/lang/String;)Z",
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 1844a98..f46f45c 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -768,6 +768,22 @@
return false;
}
+ // Returns true if the given string is exact one pair of regional indicators.
+ static bool isFlag(const jchar* str, size_t length) {
+ const jchar RI_LEAD_SURROGATE = 0xD83C;
+ const jchar RI_TRAIL_SURROGATE_MIN = 0xDDE6;
+ const jchar RI_TRAIL_SURROGATE_MAX = 0xDDFF;
+
+ if (length != 4) {
+ return false;
+ }
+ if (str[0] != RI_LEAD_SURROGATE || str[2] != RI_LEAD_SURROGATE) {
+ return false;
+ }
+ return RI_TRAIL_SURROGATE_MIN <= str[1] && str[1] <= RI_TRAIL_SURROGATE_MAX &&
+ RI_TRAIL_SURROGATE_MIN <= str[3] && str[3] <= RI_TRAIL_SURROGATE_MAX;
+ }
+
static jboolean hasGlyph(JNIEnv *env, jclass, jlong paintHandle, jlong typefaceHandle,
jint bidiFlags, jstring string) {
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
@@ -817,7 +833,26 @@
// in joining scripts, such as Arabic and Mongolian.
return false;
}
- return nGlyphs > 0 && !layoutContainsNotdef(layout);
+
+ if (nGlyphs == 0 || layoutContainsNotdef(layout)) {
+ return false; // The collection doesn't have a glyph.
+ }
+
+ if (nChars == 2 && isFlag(str.get(), str.size())) {
+ // Some font may have a special glyph for unsupported regional indicator pairs.
+ // To return false for this case, need to compare the glyph id with the one of ZZ
+ // since ZZ is reserved for unknown or invalid territory.
+ // U+1F1FF (REGIONAL INDICATOR SYMBOL LETTER Z) is \uD83C\uDDFF in UTF16.
+ static const jchar ZZ_FLAG_STR[] = { 0xD83C, 0xDDFF, 0xD83C, 0xDDFF };
+ Layout zzLayout;
+ MinikinUtils::doLayout(&zzLayout, paint, bidiFlags, typeface, ZZ_FLAG_STR, 0, 4, 4);
+ if (zzLayout.nGlyphs() != 1 || layoutContainsNotdef(zzLayout)) {
+ // The font collection doesn't have a glyph for unknown flag. Just return true.
+ return true;
+ }
+ return zzLayout.getGlyphId(0) != layout.getGlyphId(0);
+ }
+ return true;
}
static jfloat doRunAdvance(const Paint* paint, Typeface* typeface, const jchar buf[],
diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp
index b04293e..e5c4a2d 100644
--- a/core/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -176,6 +176,9 @@
PathParser::ParseResult result;
PathData data;
PathParser::getPathDataFromString(&data, &result, pathString, stringLength);
+ if (result.failureOccurred) {
+ doThrowIAE(env, result.failureMessage.c_str());
+ }
path->mutateStagingProperties()->setData(data);
env->ReleaseStringUTFChars(inputStr, pathString);
}
diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp
index 80ae550..91a3b4f 100644
--- a/core/jni/android_hardware_location_ContextHubService.cpp
+++ b/core/jni/android_hardware_location_ContextHubService.cpp
@@ -382,6 +382,9 @@
char *msg, int msgLen) {
int retVal;
+ //ALOGD("Rcd OS message from hubHandle %" PRIu32 " type %" PRIu32 " length %d",
+ // hubHandle, msgType, msgLen);
+
switch(msgType) {
case CONTEXT_HUB_APPS_ENABLE:
retVal = 0;
@@ -633,7 +636,7 @@
if (numHeaderElements >= MSG_HEADER_SIZE) {
- int setAddressSuccess;
+ bool setAddressSuccess;
int hubId;
hub_message_t msg;
@@ -654,7 +657,7 @@
ALOGD("Could not find app instance %d on hubHandle %d, setAddress %d",
header[HEADER_FIELD_APP_INSTANCE],
header[HEADER_FIELD_HUB_HANDLE],
- setAddressSuccess);
+ (int)setAddressSuccess);
}
} else {
ALOGD("Malformed header len");
diff --git a/core/jni/android_util_PathParser.cpp b/core/jni/android_util_PathParser.cpp
index 0927120..0c867f1 100644
--- a/core/jni/android_util_PathParser.cpp
+++ b/core/jni/android_util_PathParser.cpp
@@ -15,6 +15,7 @@
*/
#include "jni.h"
+#include "GraphicsJNI.h"
#include <PathParser.h>
#include <SkPath.h>
@@ -27,7 +28,7 @@
using namespace uirenderer;
-static bool parseStringForPath(JNIEnv* env, jobject, jlong skPathHandle, jstring inputPathStr,
+static void parseStringForPath(JNIEnv* env, jobject, jlong skPathHandle, jstring inputPathStr,
jint strLength) {
const char* pathString = env->GetStringUTFChars(inputPathStr, NULL);
SkPath* skPath = reinterpret_cast<SkPath*>(skPathHandle);
@@ -36,9 +37,8 @@
PathParser::parseStringForSkPath(skPath, &result, pathString, strLength);
env->ReleaseStringUTFChars(inputPathStr, pathString);
if (result.failureOccurred) {
- ALOGE(result.failureMessage.c_str());
+ doThrowIAE(env, result.failureMessage.c_str());
}
- return !result.failureOccurred;
}
static long createEmptyPathData(JNIEnv*, jobject) {
@@ -62,7 +62,7 @@
return reinterpret_cast<jlong>(pathData);
} else {
delete pathData;
- ALOGE(result.failureMessage.c_str());
+ doThrowIAE(env, result.failureMessage.c_str());
return NULL;
}
}
@@ -100,7 +100,7 @@
}
static const JNINativeMethod gMethods[] = {
- {"nParseStringForPath", "(JLjava/lang/String;I)Z", (void*)parseStringForPath},
+ {"nParseStringForPath", "(JLjava/lang/String;I)V", (void*)parseStringForPath},
{"nCreateEmptyPathData", "!()J", (void*)createEmptyPathData},
{"nCreatePathData", "!(J)J", (void*)createPathData},
{"nCreatePathDataFromString", "(Ljava/lang/String;I)J", (void*)createPathDataFromStringPath},
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 27e2ee8..4459f32 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -128,9 +128,22 @@
static void android_view_RenderNode_setDisplayList(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jlong displayListPtr) {
+ class RemovedObserver : public TreeObserver {
+ public:
+ virtual void onMaybeRemovedFromTree(RenderNode* node) override {
+ maybeRemovedNodes.insert(sp<RenderNode>(node));
+ }
+ std::set< sp<RenderNode> > maybeRemovedNodes;
+ };
+
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
DisplayList* newData = reinterpret_cast<DisplayList*>(displayListPtr);
- renderNode->setStagingDisplayList(newData);
+ RemovedObserver observer;
+ renderNode->setStagingDisplayList(newData, &observer);
+ for (auto& node : observer.maybeRemovedNodes) {
+ if (node->hasParents()) continue;
+ onRenderNodeRemoved(env, node.get());
+ }
}
// ----------------------------------------------------------------------------
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 14252dc..21e4d2f 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -525,7 +525,7 @@
UiFrameInfoBuilder(proxy->frameInfo())
.setVsync(vsync, vsync)
.addFlag(FrameInfoFlags::SurfaceCanvas);
- proxy->syncAndDrawFrame();
+ proxy->syncAndDrawFrame(nullptr);
}
static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) {
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 8019326..ef45c87 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -72,6 +72,31 @@
return env;
}
+// TODO: Clean this up, it's a bit odd to need to call over to
+// rendernode's jni layer. Probably means RootRenderNode should be pulled
+// into HWUI with appropriate callbacks for the various JNI hooks so
+// that RenderNode's JNI layer can handle its own thing
+void onRenderNodeRemoved(JNIEnv* env, RenderNode* node);
+
+class ScopedRemovedRenderNodeObserver : public TreeObserver {
+public:
+ ScopedRemovedRenderNodeObserver(JNIEnv* env) : mEnv(env) {}
+ ~ScopedRemovedRenderNodeObserver() {
+ for (auto& node : mMaybeRemovedNodes) {
+ if (node->hasParents()) continue;
+ onRenderNodeRemoved(mEnv, node.get());
+ }
+ }
+
+ virtual void onMaybeRemovedFromTree(RenderNode* node) override {
+ mMaybeRemovedNodes.insert(sp<RenderNode>(node));
+ }
+
+private:
+ JNIEnv* mEnv;
+ std::set< sp<RenderNode> > mMaybeRemovedNodes;
+};
+
class OnFinishedEvent {
public:
OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
@@ -120,13 +145,7 @@
std::string mMessage;
};
-// TODO: Clean this up, it's a bit odd to need to call over to
-// rendernode's jni layer. Probably means RootRenderNode should be pulled
-// into HWUI with appropriate callbacks for the various JNI hooks so
-// that RenderNode's JNI layer can handle its own thing
-void onRenderNodeRemoved(JNIEnv* env, RenderNode* node);
-
-class RootRenderNode : public RenderNode, ErrorHandler, TreeObserver {
+class RootRenderNode : public RenderNode, ErrorHandler {
public:
RootRenderNode(JNIEnv* env) : RenderNode() {
mLooper = Looper::getForThread();
@@ -143,9 +162,6 @@
virtual void prepareTree(TreeInfo& info) override {
info.errorHandler = this;
- if (info.mode == TreeInfo::MODE_FULL) {
- info.observer = this;
- }
// TODO: This is hacky
info.windowInsetLeft = -stagingProperties().getLeft();
info.windowInsetTop = -stagingProperties().getTop();
@@ -155,7 +171,6 @@
info.windowInsetLeft = 0;
info.windowInsetTop = 0;
info.errorHandler = nullptr;
- info.observer = nullptr;
}
void sendMessage(const sp<MessageHandler>& handler) {
@@ -181,27 +196,10 @@
mPendingAnimatingRenderNodes.clear();
}
- virtual void onMaybeRemovedFromTree(RenderNode* node) override {
- mMaybeRemovedNodes.insert(sp<RenderNode>(node));
- }
-
- void processMaybeRemovedNodes(JNIEnv* env) {
- // We can safely access mMaybeRemovedNodes here because
- // we will only modify it in prepareTree calls that are
- // MODE_FULL
-
- for (auto& node : mMaybeRemovedNodes) {
- if (node->hasParents()) continue;
- onRenderNodeRemoved(env, node.get());
- }
- mMaybeRemovedNodes.clear();
- }
-
private:
sp<Looper> mLooper;
JavaVM* mVm;
std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes;
- std::set< sp<RenderNode> > mMaybeRemovedNodes;
};
class AnimationContextBridge : public AnimationContext {
@@ -481,6 +479,12 @@
return proxy->pauseSurface(surface);
}
+static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz,
+ jlong proxyPtr, jboolean stopped) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ proxy->setStopped(stopped);
+}
+
static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
jint width, jint height, jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -500,24 +504,23 @@
}
static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize, jlong rootNodePtr) {
+ jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
"Mismatched size expectations, given %d expected %d",
frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
+ ScopedRemovedRenderNodeObserver observer(env);
env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
- int ret = proxy->syncAndDrawFrame();
- rootRenderNode->processMaybeRemovedNodes(env);
- return ret;
+ return proxy->syncAndDrawFrame(&observer);
}
static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
jlong proxyPtr, jlong rootNodePtr) {
+ ScopedRemovedRenderNodeObserver observer(env);
RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
rootRenderNode->destroy();
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- proxy->destroy();
+ proxy->destroy(&observer);
}
static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
@@ -542,9 +545,10 @@
static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
jlong proxyPtr, jlong nodePtr) {
+ ScopedRemovedRenderNodeObserver observer(env);
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
- proxy->buildLayer(node);
+ proxy->buildLayer(node, &observer);
}
static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
@@ -579,8 +583,9 @@
static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
jlong proxyPtr) {
+ ScopedRemovedRenderNodeObserver observer(env);
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- proxy->destroyHardwareResources();
+ proxy->destroyHardwareResources(&observer);
}
static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
@@ -733,10 +738,11 @@
{ "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize },
{ "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
{ "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
+ { "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped },
{ "nSetup", "(JIIFII)V", (void*) android_view_ThreadedRenderer_setup },
{ "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
{ "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
- { "nSyncAndDrawFrame", "(J[JIJ)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
+ { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
{ "nDestroy", "(JJ)V", (void*) android_view_ThreadedRenderer_destroy },
{ "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
{ "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
diff --git a/core/res/res/drawable/ic_corp_user_badge.xml b/core/res/res/drawable/ic_corp_user_badge.xml
new file mode 100644
index 0000000..23809d5
--- /dev/null
+++ b/core/res/res/drawable/ic_corp_user_badge.xml
@@ -0,0 +1,24 @@
+<!--
+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="36dp"
+ android:height="36dp"
+ android:viewportWidth="36.0"
+ android:viewportHeight="36.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M18,0C8.06,-0 0,8.06 0,18C0,27.94 8.06,36 18,36C27.94,36 36,27.94 36,18C36,8.06 27.94,0 18,0zM15.5,10.5L20.5,10.5L21.75,11.75L21.75,13L24.66,13C25.57,13 26.34,13.74 26.34,14.66L26.34,18C26.34,18.92 25.57,19.66 24.66,19.66L19.66,19.66L19.66,18.41L16.34,18.41L16.34,19.66L11.34,19.66C10.43,19.66 9.66,18.92 9.66,18L9.66,14.66C9.66,13.74 10.43,13 11.34,13L14.25,13L14.25,11.78L15.5,10.5zM15.5,11.75L15.5,13L20.5,13L20.5,11.75L15.5,11.75zM10.5,20.5L16.34,20.5L16.34,21.75L19.66,21.75L19.66,20.5L25.5,20.5L25.5,23.84C25.5,24.76 24.76,25.5 23.84,25.5L12.16,25.5C11.24,25.5 10.5,24.76 10.5,23.84L10.5,20.5z"/>
+</vector>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 2a16a1e..6a85537 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Deur jou administrateur uitgevee"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 0668c35..7a3673f 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"በእርስዎ አስተዳዳሪ ተሰርዟል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 6a7c76c..70ebba16 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -56,8 +56,8 @@
<string name="badPin" msgid="9015277645546710014">"رمز PIN القديم الذي كتبته غير صحيح."</string>
<string name="badPuk" msgid="5487257647081132201">"رمز PUK الذي كتبته غير صحيح."</string>
<string name="mismatchPin" msgid="609379054496863419">"أرقام التعريف الشخصية التي كتبتها غير مطابقة."</string>
- <string name="invalidPin" msgid="3850018445187475377">"اكتب رقم تعريف شخصيًا مكونًا من 4 إلى ثمانية أعداد."</string>
- <string name="invalidPuk" msgid="8761456210898036513">"اكتب رمز PUK مكونًا من 8 أرقام أو أكثر."</string>
+ <string name="invalidPin" msgid="3850018445187475377">"ادخل رقم تعريف شخصي مكون من ٤ إلى ٨ أرقام."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"اكتب رمز PUK مكونًا من ٨ أرقام أو أكثر."</string>
<string name="needPuk" msgid="919668385956251611">"شريحة SIM مؤمّنة بكود PUK. اكتب كود PUK لإلغاء تأمينها."</string>
<string name="needPuk2" msgid="4526033371987193070">"اكتب PUK2 لإلغاء تأمين شريحة SIM."</string>
<string name="enablePin" msgid="209412020907207950">"محاولة غير ناجحة، مكّن قفل SIM/RUIM."</string>
@@ -904,7 +904,7 @@
<string name="editTextMenuTitle" msgid="4909135564941815494">"إجراءات النص"</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 ميغابايت وأعد التشغيل."</string>
+ <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"ليست هناك سعة تخزينية كافية للنظام. تأكد من أنه لديك مساحة خالية تبلغ ۲۵۰ ميغابايت وأعد التشغيل."</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>
@@ -1343,8 +1343,8 @@
<string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"تأكيد رمز رمز PIN المراد"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"جارٍ إلغاء تأمين شريحة SIM…"</string>
<string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"رمز PIN غير صحيح."</string>
- <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"اكتب رمز PIN المكون من 4 إلى 8 أرقام."</string>
- <string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"يجب أن يتكون رمز PUK من 8 أرقام."</string>
+ <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"اكتب رقم التعريف الشخصي المكون من ٤ إلى ٨ أرقام."</string>
+ <string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"يجب أن يتكون رمز PUK من ۸ أرقام."</string>
<string name="kg_invalid_puk" msgid="3638289409676051243">"أعد إدخال رمز PUK الصحيح. وستؤدي المحاولات المتكررة إلى تعطيل شريحة SIM نهائيًا."</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"لا يتطابق رمزا رمز PIN"</string>
<string name="kg_login_too_many_attempts" msgid="6486842094005698475">"محاولات النقش كثيرة جدًا"</string>
@@ -1478,7 +1478,7 @@
<string name="restr_pin_confirm_pin" msgid="8501523829633146239">"تأكيد رمز PIN الجديد"</string>
<string name="restr_pin_create_pin" msgid="8017600000263450337">"إنشاء رقم تعريف شخصي لتعديل القيود"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"أرقام التعريف الشخصية لا تتطابق، أعد المحاولة."</string>
- <string name="restr_pin_error_too_short" msgid="8173982756265777792">"رمز PIN أقصر مما يلزم، يجب ألا يقل عن 4 أرقام. "</string>
+ <string name="restr_pin_error_too_short" msgid="8173982756265777792">"رقم التعريف الشخصي أقصر مما يلزم، يجب ألا يقل عن ٤ أرقام. "</string>
<plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
<item quantity="zero">حاول مرة أخرى خلال أقل من ثانية <xliff:g id="COUNT">%d</xliff:g></item>
<item quantity="two">حاول مرة أخرى خلال ثانيتين (<xliff:g id="COUNT">%d</xliff:g>)</item>
@@ -1508,8 +1508,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"تم حذف الحزمة عن طريق المشرف"</string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index e76ce87..2e4c10d 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Administratorunuz tərəfindən silinib"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 9231e9a..b1d086e 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1478,8 +1478,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Izbrisao je vaš admiistrator"</string>
diff --git a/core/res/res/values-be-rBY/strings.xml b/core/res/res/values-be-rBY/strings.xml
index 8a23529..3152943 100644
--- a/core/res/res/values-be-rBY/strings.xml
+++ b/core/res/res/values-be-rBY/strings.xml
@@ -1488,8 +1488,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Выдалена вашым адміністратарам"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 76c7002..ec7ba3a 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Изтрито от администратора ви"</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 620e532..491b3a2 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"আপনার প্রশাসক দ্বারা মুছে ফেলা হয়েছে"</string>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index 82639af..ba164ee 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -1478,8 +1478,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Izbrisao administrator"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 6fcadfa..6980cd5 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"L\'administrador ho ha suprimit"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 127d38b..612475a 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1488,8 +1488,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Smazáno administrátorem"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 407f1f8..f25492b 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1194,8 +1194,8 @@
<string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Sænk minuttal"</string>
<string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Forøg timetal"</string>
<string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Sænk timetal"</string>
- <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Indstil PM"</string>
- <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Indstil AM"</string>
+ <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Indstil e.m."</string>
+ <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Indstil f.m."</string>
<string name="date_picker_increment_month_button" msgid="5369998479067934110">"Senere måned"</string>
<string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Tidligere måned"</string>
<string name="date_picker_increment_day_button" msgid="7130465412308173903">"Senere dag"</string>
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Slettet af din administrator"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index e539a28..898883e 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Von deinem Administrator gelöscht"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 1e891d0..58ff631 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Διαγράφηκε από το διαχειριστή σας"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index b94222c..fe9d8db 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Deleted by your administrator"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index b94222c..fe9d8db 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Deleted by your administrator"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index b94222c..fe9d8db 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Deleted by your administrator"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 0bfb9e0..289c6ba 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Lo eliminó el administrador."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 99202ab..8bd955b 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminado por tu administrador"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index b1cc971..1aaf4ae 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Kustutas teie administraator"</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index ea666d9..4601ff8 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index df9d78f..064055e 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"توسط سرپرستتان حذف شد"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index c869961..41c583f 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Järjestelmänvalvoja on poistanut paketin."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index efc8af3..3607382 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Supprimé par votre administrateur"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 4e83fa9..27e1b70 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Supprimé par votre administrateur"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 2fa6087..c724f8c 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminado polo administrador"</string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 0b9f4ad..49acd99 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"તમારા વ્યવસ્થાપક દ્વારા કાઢી નાખેલ"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 474e81e..b621005 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"आपके नियंत्रक द्वारा हटाया गया"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 837aa56..6bc0d6e 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1478,8 +1478,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Izbrisao administrator"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 0c4705d..dd39cca 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"A rendszergazda törölte"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 4be90da..e41bf64 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Ադմինիստրատորը ջնջել է այն"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 7218617..8940875 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Dihapus oleh administrator"</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index cebc4cc..546af60 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Eytt af kerfisstjóra"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 2a73990..fc13359 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminato dall\'amministratore"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 80435b6..5b9b5e1 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1488,8 +1488,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"נמחקה על ידי מנהל המערכת שלך"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 394775f..d3ecef8 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"管理者によって削除されました"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index fcc56da..20b1055 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"თქვენი ადმინისტრატორის მიერ წაშლილი"</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 6eaa770..1372064 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Әкімші жойған"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 30d3c0a..d57659c 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1470,8 +1470,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"បានលុបដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 087b399..7f94a1d 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರಿಂದ ಅಳಿಸಲಾಗಿದೆ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 52de5ba..4f6d602 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"관리자가 삭제함"</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 34cc7e5..c7d32d11 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1469,8 +1469,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Администраторуңуз тарабынан жок кылынган"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index ea62f9b..a69ccb7 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"ຖືກຜູ້ຄວບຄຸມຂອງທ່ານລຶບໄປແລ້ວ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 3e815ec..9130d2c 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1488,8 +1488,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Ištrynė administratorius"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 56001fc..19aa282 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1478,8 +1478,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Izdzēsa jūsu administrators"</string>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 060a9fa..425722d 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1470,8 +1470,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Избришано од администраторот"</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index f6ff1d8..1e24d01 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"നിങ്ങളുടെ അഡ്മിനിസ്ട്രേറ്റർ ഇല്ലാതാക്കി"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 75105e6..0e2f8af 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Таны админ устгасан байна"</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 8a3e564..5dc9721 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"आपल्या प्रशासकाद्वारे हटविले आहे"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 5db9c77..ced967b 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Dipadamkan oleh pentadbir anda"</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 5e5ec4e..4e88bb40 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"သင့် အက်ဒမင်အား ဖျက်ပစ်ရန်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index cfccdeb..ff28307 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Slettet av administratoren"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index fb817b5..878eff9f 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1474,8 +1474,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"तपाईँको प्रशासकद्वारा हटाइएको"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 3de8496..f76d185 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Verwijderd door je beheerder"</string>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index 87f973f..26d5af9 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"ਤੁਹਾਡੇ ਪ੍ਰਬੰਧਕ ਵੱਲੋਂ ਮਿਟਾਇਆ ਗਿਆ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 6be9a9d..6bfac83 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1488,8 +1488,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Usunięty przez administratora"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index c8004bf..241ee823 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -254,7 +254,7 @@
<string name="permgrouplab_sensors" msgid="416037179223226722">"Sensores corporais"</string>
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"acesse dados do sensor sobre seus sinais vitais"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Recuperar cont. da janela"</string>
- <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspecionar o conteúdo da janela com que você está interagindo."</string>
+ <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspecionar o conteúdo da janela com a qual você está interagindo."</string>
<string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Ativar Explorar por toque"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="5800552516779249356">"Itens tocados serão falados em voz alta e a tela poderá ser explorada por meio de gestos."</string>
<string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Ativar acessibilidade na Web aprimorada"</string>
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Excluído pelo seu administrador"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index c2ba8ad..ebe6efb 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminado pelo administrador"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index c8004bf..241ee823 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -254,7 +254,7 @@
<string name="permgrouplab_sensors" msgid="416037179223226722">"Sensores corporais"</string>
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"acesse dados do sensor sobre seus sinais vitais"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Recuperar cont. da janela"</string>
- <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspecionar o conteúdo da janela com que você está interagindo."</string>
+ <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspecionar o conteúdo da janela com a qual você está interagindo."</string>
<string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Ativar Explorar por toque"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="5800552516779249356">"Itens tocados serão falados em voz alta e a tela poderá ser explorada por meio de gestos."</string>
<string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Ativar acessibilidade na Web aprimorada"</string>
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Excluído pelo seu administrador"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 7485e65..951e365 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1478,8 +1478,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Șters de administrator"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 5926bfd..a012a95 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1488,8 +1488,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Удалено администратором"</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 6c76da0..9175e7e 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1470,8 +1470,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"ඔබගේ පරිපාලක විසින් මකන ලද"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index ec45070..e09ed27 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1488,8 +1488,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Odstránený správcom"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index b2dba7e0..6cdcf31 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1488,8 +1488,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Izbrisal skrbnik"</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index 1846399..e5d8eaa 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"U fshi nga administratori yt"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 2112dbb..5ebe971c 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1478,8 +1478,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Избрисао је ваш адмиистратор"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 832d4a2..bf64512 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Paketet har raderats av administratören"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index e0a32f6..6c2952a 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1470,8 +1470,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Kilifutwa na msimamizi wako"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 773301f..e805360 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"நிர்வாகி நீக்கிவிட்டார்"</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 4809c98..8585c07 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"మీ నిర్వాహకులు తొలగించారు"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 0ea2e52..17a732f 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"ลบโดยผู้ดูแลระบบของคุณ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 00918a4..7f4393e 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Na-delete ng iyong administrator"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 4db8264..1dbf7f3 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Yöneticiniz tarafından silindi"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index fe7be12..78a2947 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1488,8 +1488,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Видалив адміністратор"</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 5236b7f..f5ffbde 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"آپ کے منتظم کی جانب سے حذف کر دیا گیا"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 6cb65a3..0b6a0cc 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Administratoringiz tomonidan o‘chirilgan"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 29eef92..6236153 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Đã bị xóa bởi quản trị viên của bạn"</string>
diff --git a/core/res/res/values-h426dp-port/integers.xml b/core/res/res/values-w320dp-h426dp/integers.xml
similarity index 100%
rename from core/res/res/values-h426dp-port/integers.xml
rename to core/res/res/values-w320dp-h426dp/integers.xml
diff --git a/core/res/res/values-w320dp/dimens.xml b/core/res/res/values-w320dp/dimens.xml
new file mode 100644
index 0000000..ad6d2ec
--- /dev/null
+++ b/core/res/res/values-w320dp/dimens.xml
@@ -0,0 +1,23 @@
+<?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>
+ <!-- The platform's desired fixed width for a dialog along the major axis
+ (the screen is in landscape). This may be either a fraction or a dimension.-->
+ <item type="dimen" name="dialog_fixed_width_major">320dp</item>
+ <!-- The platform's desired fixed width for a dialog along the minor axis
+ (the screen is in portrait). This may be either a fraction or a dimension.-->
+ <item type="dimen" name="dialog_fixed_width_minor">320dp</item>
+</resources>
diff --git a/core/res/res/values-w426dp-land/integers.xml b/core/res/res/values-w426dp-h320dp/integers.xml
similarity index 100%
rename from core/res/res/values-w426dp-land/integers.xml
rename to core/res/res/values-w426dp-h320dp/integers.xml
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 3b26e46..708f1be 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"已被管理员删除"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 28f2bac..95b7244 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"已由管理員刪除"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index dfc7890..7c980bd 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"已遭管理員刪除"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index e32f26b..d64e79c 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1468,8 +1468,6 @@
<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_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>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Isuswe ngumlawuli wakho"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b4371c1..dfa5143b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -265,19 +265,6 @@
<item>"0,1"</item>
</string-array>
- <!-- Set of NetworkInfo.getType() that reflect data usage. -->
- <integer-array translatable="false" name="config_data_usage_network_types">
- <item>0</item> <!-- TYPE_MOBILE -->
- <item>2</item> <!-- TYPE_MOBILE_MMS -->
- <item>3</item> <!-- TYPE_MOBILE_SUPL -->
- <item>4</item> <!-- TYPE_MOBILE_DUN -->
- <item>5</item> <!-- TYPE_MOBILE_HIPRI -->
- <item>10</item> <!-- TYPE_MOBILE_FOTA -->
- <item>11</item> <!-- TYPE_MOBILE_IMS -->
- <item>12</item> <!-- TYPE_MOBILE_CBS -->
- <item>14</item> <!-- TYPE_MOBILE_IA -->
- </integer-array>
-
<!-- The maximum duration (in milliseconds) we expect a network transition to take -->
<integer name="config_networkTransitionTimeout">60000</integer>
@@ -2434,10 +2421,6 @@
disables NetworkPolicyManagerService's presentation of data-usage notifications. -->
<string translatable="false" name="config_networkPolicyNotificationComponent"></string>
- <!-- The fraction of display size (lower of height and width) that will be used to determine
- the default minimal size for resizeable tasks. -->
- <fraction name="config_displayFractionForDefaultMinimalSizeOfResizeableTask">25%</fraction>
-
<!-- The BT name of the keyboard packaged with the device. If this is defined, SystemUI will
automatically try to pair with it when the device exits tablet mode. -->
<string translatable="false" name="config_packagedKeyboardName"></string>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index a21f276..dd54d57 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -112,10 +112,10 @@
<!-- The platform's desired fixed width for a dialog along the major axis
(the screen is in landscape). This may be either a fraction or a dimension.-->
- <item type="dimen" name="dialog_fixed_width_major">320dp</item>
+ <item type="dimen" name="dialog_fixed_width_major">100%</item>
<!-- The platform's desired fixed width for a dialog along the minor axis
(the screen is in portrait). This may be either a fraction or a dimension.-->
- <item type="dimen" name="dialog_fixed_width_minor">320dp</item>
+ <item type="dimen" name="dialog_fixed_width_minor">100%</item>
<!-- The platform's desired fixed height for a dialog along the major axis
(the screen is in portrait). This may be either a fraction or a dimension.-->
<item type="dimen" name="dialog_fixed_height_major">80%</item>
@@ -455,4 +455,7 @@
<item type="fraction" name="docked_stack_divider_fixed_ratio">34.15%</item>
<dimen name="resize_shadow_size">5dp</dimen>
+
+ <!-- The default minimal size of a resizable task, in both dimensions. -->
+ <dimen name="default_minimal_size_resizable_task">220dp</dimen>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b4f95dc..96731cf 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4018,12 +4018,6 @@
<!-- Lock-to-app unlock password string -->
<string name="lock_to_app_unlock_password">Ask for password before unpinning</string>
- <!-- Multi-Window strings -->
- <!-- 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>
-
<!-- Notification shown when device owner silently installs a package [CHAR LIMIT=NONE] -->
<string name="package_installed_device_owner">Installed by your administrator</string>
<!-- Notification shown when device owner silently updates a package [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 2215bd4..8d8b832 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -613,8 +613,6 @@
<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_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" />
<java-symbol type="string" name="durationDayHours" />
@@ -1130,7 +1128,6 @@
<java-symbol type="plurals" name="pinpuk_attempts" />
<java-symbol type="array" name="carrier_properties" />
- <java-symbol type="array" name="config_data_usage_network_types" />
<java-symbol type="array" name="config_sms_enabled_locking_shift_tables" />
<java-symbol type="array" name="config_sms_enabled_single_shift_tables" />
<java-symbol type="array" name="config_twoDigitNumberPattern" />
@@ -1267,6 +1264,7 @@
<java-symbol type="drawable" name="ic_corp_badge" />
<java-symbol type="drawable" name="ic_corp_badge_off" />
<java-symbol type="drawable" name="ic_corp_icon_badge" />
+ <java-symbol type="drawable" name="ic_corp_user_badge" />
<java-symbol type="drawable" name="ic_corp_badge_no_background" />
<java-symbol type="drawable" name="ic_corp_icon" />
<java-symbol type="drawable" name="ic_corp_statusbar_icon" />
@@ -1728,7 +1726,7 @@
<java-symbol type="id" name="replace_app_icon" />
<java-symbol type="id" name="replace_message" />
<java-symbol type="fraction" name="config_dimBehindFadeDuration" />
- <java-symbol type="fraction" name="config_displayFractionForDefaultMinimalSizeOfResizeableTask" />
+ <java-symbol type="dimen" name="default_minimal_size_resizable_task" />
<java-symbol type="fraction" name="config_screenAutoBrightnessDozeScaleFactor" />
<java-symbol type="fraction" name="config_autoBrightnessAdjustmentMaxGamma" />
<java-symbol type="integer" name="config_autoBrightnessAmbientLightHorizon"/>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 6611eb1..2ea5c5e 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -890,6 +890,11 @@
<item name="listDivider">@null</item>
<item name="preferencePanelStyle">@style/PreferencePanel.Dialog</item>
+
+ <item name="windowFixedWidthMajor">@null</item>
+ <item name="windowFixedWidthMinor">@null</item>
+ <item name="windowFixedHeightMajor">@null</item>
+ <item name="windowFixedHeightMinor">@null</item>
</style>
<!-- Theme overlay that overrides window properties to display as a date picker dialog. -->
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index b7926cf..2452cfd 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1256,15 +1256,6 @@
<service android:name="android.os.BinderThreadPriorityService"
android:process=":BinderThreadPriorityService" />
- <!-- Used by ApplyOverrideConfigurationTest -->
- <activity android:name="android.app.activity.ApplyOverrideConfigurationActivity"
- android:configChanges="orientation|screenSize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
- </intent-filter>
- </activity>
-
<!-- Application components used for search manager tests -->
<activity android:name="android.app.activity.SearchableActivity"
diff --git a/core/tests/coretests/src/android/app/activity/ApplyOverrideConfigurationActivity.java b/core/tests/coretests/src/android/app/activity/ApplyOverrideConfigurationActivity.java
deleted file mode 100644
index 3df522d..0000000
--- a/core/tests/coretests/src/android/app/activity/ApplyOverrideConfigurationActivity.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package android.app.activity;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.Configuration;
-
-public class ApplyOverrideConfigurationActivity extends Activity {
-
- @Override
- protected void attachBaseContext(Context newBase) {
- super.attachBaseContext(newBase);
-
- Configuration overrideConfig = new Configuration();
- overrideConfig.smallestScreenWidthDp = ApplyOverrideConfigurationTest.OVERRIDE_WIDTH;
- applyOverrideConfiguration(overrideConfig);
- }
-}
diff --git a/core/tests/coretests/src/android/app/activity/ApplyOverrideConfigurationTest.java b/core/tests/coretests/src/android/app/activity/ApplyOverrideConfigurationTest.java
deleted file mode 100644
index 15ed77e..0000000
--- a/core/tests/coretests/src/android/app/activity/ApplyOverrideConfigurationTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package android.app.activity;
-
-import android.app.UiAutomation;
-import android.content.res.Configuration;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.ActivityInstrumentationTestCase2;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class ApplyOverrideConfigurationTest extends
- ActivityInstrumentationTestCase2<ApplyOverrideConfigurationActivity> {
-
- public static final int OVERRIDE_WIDTH = 9999;
-
- public ApplyOverrideConfigurationTest() {
- super(ApplyOverrideConfigurationActivity.class);
- }
-
- @Before
- @Override
- public void setUp() throws Exception {
- super.setUp();
- injectInstrumentation(InstrumentationRegistry.getInstrumentation());
- getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_FREEZE_0);
- }
-
- @Test
- public void testConfigurationIsOverriden() throws Exception {
- Configuration config = getActivity().getResources().getConfiguration();
- assertEquals(OVERRIDE_WIDTH, config.smallestScreenWidthDp);
-
- getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_FREEZE_90);
-
- config = getActivity().getResources().getConfiguration();
- assertEquals(OVERRIDE_WIDTH, config.smallestScreenWidthDp);
- }
-
- @After
- @Override
- public void tearDown() throws Exception {
- getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_UNFREEZE);
- super.tearDown();
- }
-}
diff --git a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
index 59ffd56..eafe427 100644
--- a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
+++ b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
@@ -16,13 +16,35 @@
package android.widget;
-import android.app.Activity;
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.Espresso.pressBack;
+import static android.support.test.espresso.action.ViewActions.clearText;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.action.ViewActions.replaceText;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static android.widget.espresso.DragHandleUtils.onHandleView;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.clickFloatingToolbarItem;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup;
+import static android.widget.espresso.SuggestionsPopupwindowUtils.assertSuggestionsPopupContainsItem;
+import static android.widget.espresso.SuggestionsPopupwindowUtils.assertSuggestionsPopupIsDisplayed;
+import static android.widget.espresso.SuggestionsPopupwindowUtils.assertSuggestionsPopupIsNotDisplayed;
+import static android.widget.espresso.SuggestionsPopupwindowUtils.clickSuggestionsPopupItem;
+import static android.widget.espresso.SuggestionsPopupwindowUtils.onSuggestionsPopup;
+import static android.widget.espresso.TextViewActions.clickOnTextAtIndex;
+import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex;
+import static org.hamcrest.Matchers.is;
import android.content.res.TypedArray;
+import android.support.test.espresso.NoMatchingViewException;
+import android.support.test.espresso.ViewAssertion;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.SmallTest;
import android.test.suitebuilder.annotation.Suppress;
import android.text.Selection;
-import android.text.SpannableStringBuilder;
+import android.text.Spannable;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.style.SuggestionSpan;
@@ -42,55 +64,215 @@
super(TextViewActivity.class);
}
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ getActivity();
+ }
+
+ private void setSuggestionSpan(SuggestionSpan span, int start, int end) {
+ final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+ textView.post(
+ () -> {
+ final Spannable text = (Spannable) textView.getText();
+ text.setSpan(span, start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ Selection.setSelection(text, (start + end) / 2);
+ });
+ getInstrumentation().waitForIdleSync();
+ }
+
@SmallTest
- @Suppress
+ public void testOnTextContextMenuItem() {
+ final String text = "abc def ghi";
+
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+ new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION);
+ setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+ final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+ textView.post(() -> textView.onTextContextMenuItem(TextView.ID_REPLACE));
+ getInstrumentation().waitForIdleSync();
+
+ assertSuggestionsPopupIsDisplayed();
+ }
+
+ @SmallTest
+ public void testSelectionActionMode() {
+ final String text = "abc def ghi";
+
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+ new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION);
+ setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+ onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('e')));
+ sleepForFloatingToolbarPopup();
+ assertFloatingToolbarContainsItem(
+ getActivity().getString(com.android.internal.R.string.replace));
+ sleepForFloatingToolbarPopup();
+ clickFloatingToolbarItem(
+ getActivity().getString(com.android.internal.R.string.replace));
+
+ assertSuggestionsPopupIsDisplayed();
+ }
+
+ @SmallTest
+ public void testInsertionActionMode() {
+ final String text = "abc def ghi";
+
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+ new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION);
+ setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('e')));
+ onHandleView(com.android.internal.R.id.insertion_handle).perform(click());
+ sleepForFloatingToolbarPopup();
+ assertFloatingToolbarContainsItem(
+ getActivity().getString(com.android.internal.R.string.replace));
+ clickFloatingToolbarItem(
+ getActivity().getString(com.android.internal.R.string.replace));
+
+ assertSuggestionsPopupIsDisplayed();
+ }
+
+ private void showSuggestionsPopup() {
+ final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+ textView.post(() -> textView.onTextContextMenuItem(TextView.ID_REPLACE));
+ getInstrumentation().waitForIdleSync();
+ assertSuggestionsPopupIsDisplayed();
+ }
+
+ @SmallTest
+ public void testSuggestionItems() {
+ final String text = "abc def ghi";
+
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+ new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_AUTO_CORRECTION);
+ setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+ showSuggestionsPopup();
+
+ assertSuggestionsPopupIsDisplayed();
+ assertSuggestionsPopupContainsItem("DEF");
+ assertSuggestionsPopupContainsItem("Def");
+ assertSuggestionsPopupContainsItem(
+ getActivity().getString(com.android.internal.R.string.delete));
+
+ // Select an item.
+ clickSuggestionsPopupItem("DEF");
+ assertSuggestionsPopupIsNotDisplayed();
+ onView(withId(R.id.textview)).check(matches(withText("abc DEF ghi")));
+
+ showSuggestionsPopup();
+ assertSuggestionsPopupIsDisplayed();
+ assertSuggestionsPopupContainsItem("def");
+ assertSuggestionsPopupContainsItem("Def");
+ assertSuggestionsPopupContainsItem(
+ getActivity().getString(com.android.internal.R.string.delete));
+
+ // Delete
+ clickSuggestionsPopupItem(
+ getActivity().getString(com.android.internal.R.string.delete));
+ assertSuggestionsPopupIsNotDisplayed();
+ onView(withId(R.id.textview)).check(matches(withText("abc ghi")));
+ }
+
+ @SmallTest
+ public void testMisspelled() {
+ final String text = "abc def ghi";
+
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+ new String[]{"DEF", "Def"}, SuggestionSpan.FLAG_MISSPELLED);
+ setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+ showSuggestionsPopup();
+
+ assertSuggestionsPopupIsDisplayed();
+ assertSuggestionsPopupContainsItem("DEF");
+ assertSuggestionsPopupContainsItem("Def");
+ assertSuggestionsPopupContainsItem(
+ getActivity().getString(com.android.internal.R.string.addToDictionary));
+ assertSuggestionsPopupContainsItem(
+ getActivity().getString(com.android.internal.R.string.delete));
+
+ // Click "Add to dictionary".
+ clickSuggestionsPopupItem(
+ getActivity().getString(com.android.internal.R.string.addToDictionary));
+ // TODO: Check if add to dictionary dialog is displayed.
+ }
+
+ @SmallTest
+ public void testEasyCorrect() {
+ final String text = "abc def ghi";
+
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+ new String[]{"DEF", "Def"},
+ SuggestionSpan.FLAG_EASY_CORRECT | SuggestionSpan.FLAG_MISSPELLED);
+ setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('e')));
+
+ assertSuggestionsPopupIsDisplayed();
+ assertSuggestionsPopupContainsItem("DEF");
+ assertSuggestionsPopupContainsItem("Def");
+ assertSuggestionsPopupContainsItem(
+ getActivity().getString(com.android.internal.R.string.delete));
+
+ // Select an item.
+ clickSuggestionsPopupItem("DEF");
+ assertSuggestionsPopupIsNotDisplayed();
+ onView(withId(R.id.textview)).check(matches(withText("abc DEF ghi")));
+
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('e')));
+ assertSuggestionsPopupIsNotDisplayed();
+
+ showSuggestionsPopup();
+ assertSuggestionsPopupIsDisplayed();
+ assertSuggestionsPopupContainsItem("def");
+ assertSuggestionsPopupContainsItem("Def");
+ assertSuggestionsPopupContainsItem(
+ getActivity().getString(com.android.internal.R.string.delete));
+ }
+
+ @SmallTest
public void testTextAppearanceInSuggestionsPopup() {
- final Activity activity = getActivity();
+ final String text = "abc def ghi";
- final String sampleText = "abc def ghi";
final String[] singleWordCandidates = {"DEF", "Def"};
- final SuggestionSpan singleWordSuggestionSpan = new SuggestionSpan(activity,
- singleWordCandidates, SuggestionSpan.FLAG_AUTO_CORRECTION);
- final int singleWordSpanStart = 4;
- final int singleWordSpanEnd = 7;
-
+ final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
+ singleWordCandidates, SuggestionSpan.FLAG_MISSPELLED);
final String[] multiWordCandidates = {"ABC DEF GHI", "Abc Def Ghi"};
- final SuggestionSpan multiWordSuggestionSpan = new SuggestionSpan(activity,
- multiWordCandidates, SuggestionSpan.FLAG_AUTO_CORRECTION);
- final int multiWordSpanStart = 0;
- final int multiWordSpanEnd = 11;
+ final SuggestionSpan multiWordSuggestionSpan = new SuggestionSpan(getActivity(),
+ multiWordCandidates, SuggestionSpan.FLAG_MISSPELLED);
- TypedArray array = activity.obtainStyledAttributes(com.android.internal.R.styleable.Theme);
- int id = array.getResourceId(
+ final TypedArray array =
+ getActivity().obtainStyledAttributes(com.android.internal.R.styleable.Theme);
+ final int id = array.getResourceId(
com.android.internal.R.styleable.Theme_textEditSuggestionHighlightStyle, 0);
array.recycle();
-
- TextAppearanceSpan expectedSpan = new TextAppearanceSpan(activity, id);
- TextPaint tmpTp = new TextPaint();
+ final TextAppearanceSpan expectedSpan = new TextAppearanceSpan(getActivity(), id);
+ final TextPaint tmpTp = new TextPaint();
expectedSpan.updateDrawState(tmpTp);
final int expectedHighlightTextColor = tmpTp.getColor();
final float expectedHighlightTextSize = tmpTp.getTextSize();
-
- final EditText editText = (EditText) activity.findViewById(R.id.textview);
- final Editor editor = editText.getEditorForTesting();
- assertNotNull(editor);
-
- // Request to show SuggestionsPopupWindow.
- Runnable showSuggestionWindowRunner = new Runnable() {
- @Override
- public void run() {
- SpannableStringBuilder ssb = new SpannableStringBuilder();
- ssb.append(sampleText);
- ssb.setSpan(singleWordSuggestionSpan, singleWordSpanStart, singleWordSpanEnd,
- Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- ssb.setSpan(multiWordSuggestionSpan, multiWordSpanStart, multiWordSpanEnd,
- Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- editText.setText(ssb);
-
- Selection.setSelection(editText.getText(), singleWordSpanStart, singleWordSpanEnd);
- editText.onTextContextMenuItem(TextView.ID_REPLACE);
- }
- };
+ final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
// In this test, the SuggestionsPopupWindow looks like
// abc def ghi
@@ -103,96 +285,74 @@
// | DELETE |
// -----------------
// *XX* means that XX is highlighted.
- Runnable popupVaridator = new Runnable() {
- @Override
- public void run() {
- Editor.SuggestionsPopupWindow popupWindow =
- editor.getSuggestionsPopupWindowForTesting();
- assertNotNull(popupWindow);
+ for (int i = 0; i < 2; i++) {
+ onView(withId(R.id.textview)).perform(click());
+ onView(withId(R.id.textview)).perform(replaceText(text));
+ setSuggestionSpan(suggestionSpan, text.indexOf('d'), text.indexOf('f') + 1);
+ setSuggestionSpan(multiWordSuggestionSpan, 0, text.length());
- LinearLayout linearLayout = (LinearLayout) popupWindow.getContentViewForTesting();
- assertNotNull(linearLayout);
+ showSuggestionsPopup();
+ assertSuggestionsPopupIsDisplayed();
+ assertSuggestionsPopupContainsItem("abc DEF ghi");
+ assertSuggestionsPopupContainsItem("abc Def ghi");
+ assertSuggestionsPopupContainsItem("ABC DEF GHI");
+ assertSuggestionsPopupContainsItem("Abc Def Ghi");
+ assertSuggestionsPopupContainsItem(
+ getActivity().getString(com.android.internal.R.string.delete));
- ListView listView = (ListView)linearLayout.findViewById(
- com.android.internal.R.id.suggestionContainer);
- assertNotNull(listView);
+ onSuggestionsPopup().check(new ViewAssertion() {
+ @Override
+ public void check(View view, NoMatchingViewException e) {
+ final ListView listView = (ListView) view.findViewById(
+ com.android.internal.R.id.suggestionContainer);
+ assertNotNull(listView);
+ final int childNum = listView.getChildCount();
+ assertEquals(singleWordCandidates.length + multiWordCandidates.length,
+ childNum);
- int childNum = listView.getChildCount();
- assertEquals(singleWordCandidates.length + multiWordCandidates.length, childNum);
+ for (int j = 0; j < childNum; j++) {
+ final TextView suggestion = (TextView) listView.getChildAt(j);
+ assertNotNull(suggestion);
+ final Spanned spanned = (Spanned) suggestion.getText();
+ assertNotNull(spanned);
- for (int i = 0; i < singleWordCandidates.length; ++i) {
- TextView textView = (TextView) listView.getChildAt(i);
- assertNotNull(textView);
+ // Check that the suggestion item order is kept.
+ final String expectedText;
+ if (j < singleWordCandidates.length) {
+ expectedText = "abc " + singleWordCandidates[j] + " ghi";
+ } else {
+ expectedText = multiWordCandidates[j - singleWordCandidates.length];
+ }
+ assertEquals(expectedText, spanned.toString());
- Spanned spanned = (Spanned) textView.getText();
- assertNotNull(spanned);
+ // Check that the text is highlighted with correct color and text size.
+ final TextAppearanceSpan[] taSpan = spanned.getSpans(
+ text.indexOf('d'), text.indexOf('f') + 1, TextAppearanceSpan.class);
+ assertEquals(1, taSpan.length);
+ TextPaint tp = new TextPaint();
+ taSpan[0].updateDrawState(tp);
+ assertEquals(expectedHighlightTextColor, tp.getColor());
+ assertEquals(expectedHighlightTextSize, tp.getTextSize());
- // Check that the suggestion item order is kept.
- String expectedText = "abc " + singleWordCandidates[i] + " ghi";
- assertEquals(expectedText, spanned.toString());
-
- // Check that the text is highlighted with correct color and text size.
- TextAppearanceSpan[] taSpan = spanned.getSpans(singleWordSpanStart,
- singleWordSpanEnd, TextAppearanceSpan.class);
- assertEquals(1, taSpan.length);
- TextPaint tp = new TextPaint();
- taSpan[0].updateDrawState(tp);
- assertEquals(expectedHighlightTextColor, tp.getColor());
- assertEquals(expectedHighlightTextSize, tp.getTextSize());
-
- // Check only center word is highlighted.
- assertEquals(singleWordSpanStart, spanned.getSpanStart(taSpan[0]));
- assertEquals(singleWordSpanEnd, spanned.getSpanEnd(taSpan[0]));
+ // Check the correct part of the text is highlighted.
+ final int expectedStart;
+ final int expectedEnd;
+ if (j < singleWordCandidates.length) {
+ expectedStart = text.indexOf('d');
+ expectedEnd = text.indexOf('f') + 1;
+ } else {
+ expectedStart = 0;
+ expectedEnd = text.length();
+ }
+ assertEquals(expectedStart, spanned.getSpanStart(taSpan[0]));
+ assertEquals(expectedEnd, spanned.getSpanEnd(taSpan[0]));
+ }
}
-
- for (int i = 0; i < multiWordCandidates.length; ++i) {
- int indexInListView = singleWordCandidates.length + i;
- TextView textView = (TextView) listView.getChildAt(indexInListView);
- assertNotNull(textView);
-
- Spanned spanned = (Spanned) textView.getText();
- assertNotNull(spanned);
-
- // Check that the suggestion item order is kept.
- assertEquals(multiWordCandidates[i], spanned.toString());
-
- // Check that the text is highlighted with correct color and text size.
- TextAppearanceSpan[] taSpan = spanned.getSpans(
- 0, multiWordCandidates[i].length(), TextAppearanceSpan.class);
- assertEquals(1, taSpan.length);
- TextPaint tp = new TextPaint();
- taSpan[0].updateDrawState(tp);
- assertEquals(expectedHighlightTextColor, tp.getColor());
- assertEquals(expectedHighlightTextSize, tp.getTextSize());
-
- // Check the whole text is highlighted.
- assertEquals(multiWordSpanStart, spanned.getSpanStart(taSpan[0]));
- assertEquals(multiWordSpanEnd, spanned.getSpanEnd(taSpan[0]));
- }
-
- TextView deleteButton = (TextView)linearLayout.findViewById(
- com.android.internal.R.id.deleteButton);
- assertEquals(View.VISIBLE, deleteButton.getWindowVisibility());
- }
- };
-
- // Show the SuggestionWindow and verify the contents.
- activity.runOnUiThread(showSuggestionWindowRunner);
- getInstrumentation().waitForIdleSync();
- activity.runOnUiThread(popupVaridator);
-
- // Request to hide the SuggestionPopupWindow and wait until it is hidden.
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- editText.setText("");
- }
- });
- getInstrumentation().waitForIdleSync();
-
- // Show and verify the contents again.
- activity.runOnUiThread(showSuggestionWindowRunner);
- getInstrumentation().waitForIdleSync();
- activity.runOnUiThread(popupVaridator);
+ });
+ pressBack();
+ onView(withId(R.id.textview))
+ .inRoot(withDecorView(is(getActivity().getWindow().getDecorView())))
+ .perform(clearText());
+ }
}
}
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
index 923b829..edb749b95 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
@@ -16,6 +16,10 @@
package android.widget;
+
+import static android.widget.espresso.ContextMenuUtils.assertContextMenuContainsItemDisabled;
+import static android.widget.espresso.ContextMenuUtils.assertContextMenuContainsItemEnabled;
+import static android.widget.espresso.ContextMenuUtils.assertContextMenuIsNotDisplayed;
import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles;
import static android.widget.espresso.DragHandleUtils.onHandleView;
import static android.widget.espresso.TextViewActions.mouseClickOnTextAtIndex;
@@ -41,11 +45,9 @@
import com.android.frameworks.coretests.R;
-import android.support.test.espresso.Espresso;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.MotionEvent;
-import android.widget.espresso.ContextMenuUtils;
/**
* Tests mouse interaction of the TextView widget from an Activity
@@ -57,7 +59,8 @@
}
@Override
- public void setUp() {
+ public void setUp() throws Exception {
+ super.setUp();
getActivity();
}
@@ -102,28 +105,28 @@
onView(withId(R.id.textview)).perform(click());
onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(text));
- ContextMenuUtils.assertContextMenuIsNotDisplayed();
+ assertContextMenuIsNotDisplayed();
onView(withId(R.id.textview)).perform(
mouseClickOnTextAtIndex(text.indexOf("d"), MotionEvent.BUTTON_SECONDARY));
- ContextMenuUtils.assertContextMenuContainsItemDisabled(
+ assertContextMenuContainsItemDisabled(
getActivity().getString(com.android.internal.R.string.copy));
- ContextMenuUtils.assertContextMenuContainsItemEnabled(
+ assertContextMenuContainsItemEnabled(
getActivity().getString(com.android.internal.R.string.undo));
// Hide context menu.
pressBack();
- ContextMenuUtils.assertContextMenuIsNotDisplayed();
+ assertContextMenuIsNotDisplayed();
onView(withId(R.id.textview)).perform(
mouseDragOnText(text.indexOf("c"), text.indexOf("h")));
onView(withId(R.id.textview)).perform(
mouseClickOnTextAtIndex(text.indexOf("d"), MotionEvent.BUTTON_SECONDARY));
- ContextMenuUtils.assertContextMenuContainsItemEnabled(
+ assertContextMenuContainsItemEnabled(
getActivity().getString(com.android.internal.R.string.copy));
- ContextMenuUtils.assertContextMenuContainsItemEnabled(
+ assertContextMenuContainsItemEnabled(
getActivity().getString(com.android.internal.R.string.undo));
// Hide context menu.
@@ -133,9 +136,9 @@
onView(withId(R.id.textview)).perform(
mouseClickOnTextAtIndex(text.indexOf("i"), MotionEvent.BUTTON_SECONDARY));
- ContextMenuUtils.assertContextMenuContainsItemDisabled(
+ assertContextMenuContainsItemDisabled(
getActivity().getString(com.android.internal.R.string.copy));
- ContextMenuUtils.assertContextMenuContainsItemEnabled(
+ assertContextMenuContainsItemEnabled(
getActivity().getString(com.android.internal.R.string.undo));
// Hide context menu.
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index ecf88f1..67ffd2b 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -19,7 +19,6 @@
import static android.support.test.espresso.action.ViewActions.longClick;
import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles;
import static android.widget.espresso.DragHandleUtils.onHandleView;
-import static android.widget.espresso.FloatingToolbarEspressoUtils.onFloatingToolBarItem;
import static android.widget.espresso.TextViewActions.clickOnTextAtIndex;
import static android.widget.espresso.TextViewActions.doubleTapAndDragOnText;
import static android.widget.espresso.TextViewActions.doubleClickOnTextAtIndex;
@@ -31,9 +30,10 @@
import static android.widget.espresso.TextViewAssertions.hasSelection;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsDisplayed;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsNotDisplayed;
-import static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarDoesNotContainItem;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.clickFloatingToolbarItem;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.sleepForFloatingToolbarPopup;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.action.ViewActions.pressKey;
@@ -67,7 +67,8 @@
}
@Override
- public void setUp() {
+ public void setUp() throws Exception {
+ super.setUp();
getActivity();
}
@@ -256,7 +257,8 @@
onView(withId(R.id.textview)).perform(typeTextIntoFocusedView("test"));
onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(1));
- onFloatingToolBarItem(withText(com.android.internal.R.string.cut)).perform(click());
+ clickFloatingToolbarItem(
+ getActivity().getString(com.android.internal.R.string.cut));
onView(withId(R.id.textview)).perform(longClick());
sleepForFloatingToolbarPopup();
diff --git a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
index 0f7f359..838f4db 100644
--- a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
+++ b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
@@ -17,6 +17,7 @@
package android.widget.espresso;
import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
@@ -24,6 +25,7 @@
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
import static android.support.test.espresso.matcher.ViewMatchers.withTagValue;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.is;
@@ -34,8 +36,6 @@
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.ViewInteraction;
-import android.support.test.espresso.action.ViewActions;
-import android.support.test.espresso.matcher.ViewMatchers;
import android.view.View;
import com.android.internal.widget.FloatingToolbar;
@@ -90,7 +90,7 @@
final int id = com.android.internal.R.id.overflow;
onView(allOf(withId(id), isDisplayed()))
.inRoot(withDecorView(hasDescendant(withId(id))))
- .perform(ViewActions.click());
+ .perform(click());
onView(isRoot()).perform(SLEEP);
}
@@ -106,7 +106,7 @@
*/
public static void assertFloatingToolbarContainsItem(String itemLabel) {
try{
- onFloatingToolBar().check(matches(hasDescendant(ViewMatchers.withText(itemLabel))));
+ onFloatingToolBar().check(matches(hasDescendant(withText(itemLabel))));
} catch (AssertionError e) {
try{
toggleOverflow();
@@ -115,7 +115,7 @@
throw e;
}
try{
- onFloatingToolBar().check(matches(hasDescendant(ViewMatchers.withText(itemLabel))));
+ onFloatingToolBar().check(matches(hasDescendant(withText(itemLabel))));
} finally {
toggleOverflow();
}
@@ -138,6 +138,21 @@
}
/**
+ * Click specified item on the floating tool bar.
+ *
+ * @param itemLabel label of the item.
+ */
+ public static void clickFloatingToolbarItem(String itemLabel) {
+ try{
+ onFloatingToolBarItem(withText(itemLabel)).check(matches(isDisplayed()));
+ } catch (AssertionError e) {
+ // Try to find the item in the overflow menu.
+ toggleOverflow();
+ }
+ onFloatingToolBarItem(withText(itemLabel)).perform(click());
+ }
+
+ /**
* ViewAction to sleep to wait floating toolbar's animation.
*/
private static final ViewAction SLEEP = new ViewAction() {
diff --git a/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java b/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java
new file mode 100644
index 0000000..b5a96ae
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/espresso/SuggestionsPopupwindowUtils.java
@@ -0,0 +1,121 @@
+/*
+ * 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.espresso;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
+import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import org.hamcrest.Matcher;
+
+import android.support.test.espresso.NoMatchingRootException;
+import android.support.test.espresso.NoMatchingViewException;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.espresso.ViewInteraction;
+import android.support.test.espresso.action.GeneralLocation;
+import android.support.test.espresso.action.Press;
+import android.support.test.espresso.action.Tap;
+import android.view.View;
+
+public final class SuggestionsPopupwindowUtils {
+ private static final int id = com.android.internal.R.id.suggestionWindowContainer;
+
+ private SuggestionsPopupwindowUtils() {};
+
+ public static ViewInteraction onSuggestionsPopup() {
+ return onView(withId(id)).inRoot(withDecorView(hasDescendant(withId(id))));
+ }
+
+ private static ViewInteraction onSuggestionsPopupItem(Matcher<View> matcher) {
+ return onView(matcher).inRoot(withDecorView(hasDescendant(withId(id))));
+ }
+
+ /**
+ * Asserts that the suggestions popup is displayed on screen.
+ *
+ * @throws AssertionError if the assertion fails
+ */
+ public static void assertSuggestionsPopupIsDisplayed() {
+ onSuggestionsPopup().check(matches(isDisplayed()));
+ }
+
+ /**
+ * Asserts that the suggestions popup is not displayed on screen.
+ *
+ * @throws AssertionError if the assertion fails
+ */
+ public static void assertSuggestionsPopupIsNotDisplayed() {
+ try {
+ onSuggestionsPopup().check(matches(isDisplayed()));
+ } catch (NoMatchingRootException | NoMatchingViewException | AssertionError e) {
+ return;
+ }
+ throw new AssertionError("Suggestions popup is displayed");
+ }
+
+ /**
+ * Asserts that the suggestions popup contains the specified item.
+ *
+ * @param itemLabel label of the item.
+ * @throws AssertionError if the assertion fails
+ */
+ public static void assertSuggestionsPopupContainsItem(String itemLabel) {
+ onSuggestionsPopupItem(withText(itemLabel)).check(matches(isDisplayed()));
+ }
+
+ /**
+ * Click on the specified item in the suggestions popup.
+ *
+ * @param itemLabel label of the item.
+ */
+ public static void clickSuggestionsPopupItem(String itemLabel) {
+ onSuggestionsPopupItem(withText(itemLabel)).perform(new SuggestionItemClickAction());
+ }
+
+ /**
+ * Click action to avoid checking ViewClickAction#getConstraints().
+ * TODO: Use Espresso.onData instead of this.
+ */
+ private static final class SuggestionItemClickAction implements ViewAction {
+ private final ViewClickAction mViewClickAction;
+
+ public SuggestionItemClickAction() {
+ mViewClickAction =
+ new ViewClickAction(Tap.SINGLE, GeneralLocation.VISIBLE_CENTER, Press.FINGER);
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return mViewClickAction.getDescription();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ mViewClickAction.perform(uiController, view);
+ }
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
index ec5220f..ba5206a 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
@@ -27,7 +27,6 @@
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ControllerImpl;
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
-import com.android.internal.inputmethod.InputMethodUtils;
import java.util.ArrayList;
import java.util.Arrays;
@@ -68,7 +67,7 @@
ri.serviceInfo = si;
List<InputMethodSubtype> subtypes = null;
if (subtypeLocales != null) {
- subtypes = new ArrayList<InputMethodSubtype>();
+ subtypes = new ArrayList<>();
for (String subtypeLocale : subtypeLocales) {
subtypes.add(createDummySubtype(subtypeLocale));
}
@@ -89,7 +88,7 @@
}
private static List<ImeSubtypeListItem> createEnabledImeSubtypes() {
- final List<ImeSubtypeListItem> items = new ArrayList<ImeSubtypeListItem>();
+ final List<ImeSubtypeListItem> items = new ArrayList<>();
addDummyImeSubtypeListItems(items, "LatinIme", "LatinIme", Arrays.asList("en_US", "fr"),
true /* supportsSwitchingToNextInputMethod*/);
addDummyImeSubtypeListItems(items, "switchUnawareLatinIme", "switchUnawareLatinIme",
@@ -105,7 +104,7 @@
}
private static List<ImeSubtypeListItem> createDisabledImeSubtypes() {
- final List<ImeSubtypeListItem> items = new ArrayList<ImeSubtypeListItem>();
+ final List<ImeSubtypeListItem> items = new ArrayList<>();
addDummyImeSubtypeListItems(items,
"UnknownIme", "UnknownIme",
Arrays.asList("en_US", "hi"),
@@ -121,15 +120,18 @@
}
private void assertNextInputMethod(final ControllerImpl controller,
- final boolean onlyCurrentIme,
- final ImeSubtypeListItem currentItem, final ImeSubtypeListItem nextItem) {
+ final boolean onlyCurrentIme, final ImeSubtypeListItem currentItem,
+ final ImeSubtypeListItem nextItem, final ImeSubtypeListItem prevItem) {
InputMethodSubtype subtype = null;
if (currentItem.mSubtypeName != null) {
subtype = createDummySubtype(currentItem.mSubtypeName.toString());
}
final ImeSubtypeListItem nextIme = controller.getNextInputMethod(onlyCurrentIme,
- currentItem.mImi, subtype);
+ currentItem.mImi, subtype, true /* forward */);
assertEquals(nextItem, nextIme);
+ final ImeSubtypeListItem prevIme = controller.getNextInputMethod(onlyCurrentIme,
+ currentItem.mImi, subtype, false /* forward */);
+ assertEquals(prevItem, prevIme);
}
private void assertRotationOrder(final ControllerImpl controller,
@@ -138,11 +140,13 @@
final int N = expectedRotationOrderOfImeSubtypeList.length;
for (int i = 0; i < N; i++) {
final int currentIndex = i;
+ final int prevIndex = (currentIndex + N - 1) % N;
final int nextIndex = (currentIndex + 1) % N;
final ImeSubtypeListItem currentItem =
expectedRotationOrderOfImeSubtypeList[currentIndex];
final ImeSubtypeListItem nextItem = expectedRotationOrderOfImeSubtypeList[nextIndex];
- assertNextInputMethod(controller, onlyCurrentIme, currentItem, nextItem);
+ final ImeSubtypeListItem prevItem = expectedRotationOrderOfImeSubtypeList[prevIndex];
+ assertNextInputMethod(controller, onlyCurrentIme, currentItem, nextItem, prevItem);
}
}
@@ -190,29 +194,29 @@
assertRotationOrder(controller, true /* onlyCurrentIme */,
switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
- subtypeUnawareIme, null);
+ subtypeUnawareIme, null, null);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
- japaneseIme_ja_JP, null);
+ japaneseIme_ja_JP, null, null);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
- switchUnawareJapaneseIme_ja_JP, null);
+ switchUnawareJapaneseIme_ja_JP, null, null);
// Make sure that disabled IMEs are not accepted.
assertNextInputMethod(controller, false /* onlyCurrentIme */,
- disabledIme_en_US, null);
+ disabledIme_en_US, null, null);
assertNextInputMethod(controller, false /* onlyCurrentIme */,
- disabledIme_hi, null);
+ disabledIme_hi, null, null);
assertNextInputMethod(controller, false /* onlyCurrentIme */,
- disabledSwitchingUnawareIme, null);
+ disabledSwitchingUnawareIme, null, null);
assertNextInputMethod(controller, false /* onlyCurrentIme */,
- disabledSubtypeUnawareIme, null);
+ disabledSubtypeUnawareIme, null, null);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
- disabledIme_en_US, null);
+ disabledIme_en_US, null, null);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
- disabledIme_hi, null);
+ disabledIme_hi, null, null);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
- disabledSwitchingUnawareIme, null);
+ disabledSwitchingUnawareIme, null, null);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
- disabledSubtypeUnawareIme, null);
+ disabledSubtypeUnawareIme, null, null);
}
@SmallTest
@@ -246,7 +250,7 @@
japaneseIme_ja_JP, latinIme_fr, latinIme_en_US);
// Check onlyCurrentIme == true.
assertNextInputMethod(controller, true /* onlyCurrentIme */,
- japaneseIme_ja_JP, null);
+ japaneseIme_ja_JP, null, null);
assertRotationOrder(controller, true /* onlyCurrentIme */,
latinIme_fr, latinIme_en_US);
assertRotationOrder(controller, true /* onlyCurrentIme */,
@@ -270,9 +274,9 @@
assertRotationOrder(controller, true /* onlyCurrentIme */,
switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
- subtypeUnawareIme, null);
+ subtypeUnawareIme, null, null);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
- switchUnawareJapaneseIme_ja_JP, null);
+ switchUnawareJapaneseIme_ja_JP, null, null);
// Rotation order should be preserved when created with the same subtype list.
final List<ImeSubtypeListItem> sameEnabledItems = createEnabledImeSubtypes();
@@ -298,7 +302,7 @@
@SmallTest
public void testImeSubtypeListItem() throws Exception {
- final List<ImeSubtypeListItem> items = new ArrayList<ImeSubtypeListItem>();
+ final List<ImeSubtypeListItem> items = new ArrayList<>();
addDummyImeSubtypeListItems(items, "LatinIme", "LatinIme",
Arrays.asList("en_US", "fr", "en", "en_uk", "enn", "e", "EN_US"),
true /* supportsSwitchingToNextInputMethod*/);
diff --git a/core/tests/notificationtests/Android.mk b/core/tests/notificationtests/Android.mk
index be2e6bf..702218c 100644
--- a/core/tests/notificationtests/Android.mk
+++ b/core/tests/notificationtests/Android.mk
@@ -11,6 +11,9 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_PACKAGE_NAME := NotificationStressTests
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ ub-uiautomator
+
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/core/tests/notificationtests/src/android/app/NotificationStressTest.java b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
index 4cb617e..6e86c37 100644
--- a/core/tests/notificationtests/src/android/app/NotificationStressTest.java
+++ b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
@@ -16,15 +16,19 @@
package android.app;
-
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Build;
+import android.os.RemoteException;
import android.os.SystemClock;
+import android.support.test.uiautomator.UiDevice;
import android.test.InstrumentationTestCase;
import android.test.RepetitiveTest;
-import android.test.TimedTest;
+import android.util.Log;
+import java.lang.InterruptedException;
+import java.lang.reflect.Method;
import java.util.Random;
/**
@@ -34,51 +38,78 @@
public class NotificationStressTest extends InstrumentationTestCase {
private static final int NUM_ITERATIONS = 200;
+ private static final int NUM_ITERATIONS_2 = 30;
+ private static final int LONG_TIMEOUT = 2000;
+ // 50 notifications per app: defined as Variable MAX_PACKAGE_NOTIFICATIONS in
+ // NotificationManagerService.java
+ private static final int MAX_NOTIFCATIONS = 50;
private static final int[] ICONS = new int[] {
- android.R.drawable.stat_notify_call_mute,
- android.R.drawable.stat_notify_chat,
- android.R.drawable.stat_notify_error,
- android.R.drawable.stat_notify_missed_call,
- android.R.drawable.stat_notify_more,
- android.R.drawable.stat_notify_sdcard,
- android.R.drawable.stat_notify_sdcard_prepare,
- android.R.drawable.stat_notify_sdcard_usb,
- android.R.drawable.stat_notify_sync,
- android.R.drawable.stat_notify_sync_noanim,
- android.R.drawable.stat_notify_voicemail,
+ android.R.drawable.stat_notify_call_mute,
+ android.R.drawable.stat_notify_chat,
+ android.R.drawable.stat_notify_error,
+ android.R.drawable.stat_notify_missed_call,
+ android.R.drawable.stat_notify_more,
+ android.R.drawable.stat_notify_sdcard,
+ android.R.drawable.stat_notify_sdcard_prepare,
+ android.R.drawable.stat_notify_sdcard_usb,
+ android.R.drawable.stat_notify_sync,
+ android.R.drawable.stat_notify_sync_noanim,
+ android.R.drawable.stat_notify_voicemail,
};
private final Random mRandom = new Random();
private Context mContext;
private NotificationManager mNotificationManager;
- private int notifyId = 0;
+ private UiDevice mDevice = null;
+ private int mNotifyId = 0;
@Override
protected void setUp() throws Exception {
super.setUp();
+ mDevice = UiDevice.getInstance(getInstrumentation());
mContext = getInstrumentation().getContext();
mNotificationManager = (NotificationManager) mContext.getSystemService(
Context.NOTIFICATION_SERVICE);
+ mDevice.setOrientationNatural();
+ mNotificationManager.cancelAll();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
+ mDevice.unfreezeRotation();
mNotificationManager.cancelAll();
}
- @RepetitiveTest(numIterations=NUM_ITERATIONS)
+ @RepetitiveTest(numIterations = NUM_ITERATIONS)
public void testNotificationStress() {
// Cancel one of every five notifications to vary load on notification manager
- if (notifyId % 5 == 4) {
- mNotificationManager.cancel(notifyId - 4);
+ if (mNotifyId % 5 == 4) {
+ mNotificationManager.cancel(mNotifyId - 4);
}
- sendNotification(notifyId++, "testNotificationStressNotify");
+ sendNotification(mNotifyId++, "testNotificationStressNotify");
+ }
+
+ @RepetitiveTest(numIterations = NUM_ITERATIONS_2)
+ public void testNotificationsWithShadeStress() throws Exception {
+ mDevice.openNotification();
+ Thread.sleep(LONG_TIMEOUT);
+ for (int j = 0; j < MAX_NOTIFCATIONS; j++) {
+ sendNotification(mNotifyId++, "testNotificationStressNotify");
+ }
+ Thread.sleep(500);
+ assertTrue(mNotificationManager.getActiveNotifications().length == MAX_NOTIFCATIONS);
+ for (int j = 0; j < MAX_NOTIFCATIONS; j++) {
+ mNotificationManager.cancel(--mNotifyId);
+ }
+ if (isLockScreen()) {
+ fail("Notification stress test failed, back to lockscreen");
+ }
}
private void sendNotification(int id, CharSequence text) {
// Fill in arbitrary content
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
+ Intent intent = new Intent(Intent.ACTION_VIEW);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
CharSequence title = text + " " + id;
CharSequence subtitle = String.valueOf(System.currentTimeMillis());
@@ -90,8 +121,19 @@
.setContentTitle(title)
.setContentText(subtitle)
.setContentIntent(pendingIntent)
+ .setPriority(Notification.PRIORITY_HIGH)
.build();
mNotificationManager.notify(id, notification);
SystemClock.sleep(10);
}
+
+ private boolean isLockScreen() {
+ KeyguardManager myKM = (KeyguardManager) mContext
+ .getSystemService(Context.KEYGUARD_SERVICE);
+ if (myKM.inKeyguardRestrictedInputMode()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
}
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index f741e3c..e48bf79 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -17,8 +17,12 @@
package android.graphics;
import android.content.res.AssetManager;
+import android.util.Log;
+import java.io.FileInputStream;
+import java.io.IOException;
import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
import java.util.List;
/**
@@ -27,6 +31,9 @@
* @hide
*/
public class FontFamily {
+
+ private static String TAG = "FontFamily";
+
/**
* @hide
*/
@@ -62,7 +69,15 @@
}
public boolean addFont(String path, int ttcIndex) {
- return nAddFont(mNativePtr, path, ttcIndex);
+ try (FileInputStream file = new FileInputStream(path)) {
+ FileChannel fileChannel = file.getChannel();
+ long fontSize = fileChannel.size();
+ ByteBuffer fontBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
+ return nAddFont(mNativePtr, fontBuffer, ttcIndex);
+ } catch (IOException e) {
+ Log.e(TAG, "Error mapping font file " + path);
+ return false;
+ }
}
public boolean addFontWeightStyle(ByteBuffer font, int ttcIndex, List<FontListParser.Axis> axes,
@@ -76,7 +91,7 @@
private static native long nCreateFamily(String lang, int variant);
private static native void nUnrefFamily(long nativePtr);
- private static native boolean nAddFont(long nativeFamily, String path, int ttcIndex);
+ private static native boolean nAddFont(long nativeFamily, ByteBuffer font, int ttcIndex);
private static native boolean nAddFontWeightStyle(long nativeFamily, ByteBuffer font,
int ttcIndex, List<FontListParser.Axis> listOfAxis,
int weight, boolean isItalic);
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index be816f78..0606b0b 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -248,16 +248,17 @@
tests/unit/FatVectorTests.cpp \
tests/unit/GlopBuilderTests.cpp \
tests/unit/GpuMemoryTrackerTests.cpp \
+ tests/unit/GradientCacheTests.cpp \
tests/unit/LayerUpdateQueueTests.cpp \
tests/unit/LinearAllocatorTests.cpp \
tests/unit/MatrixTests.cpp \
tests/unit/OffscreenBufferPoolTests.cpp \
tests/unit/RenderNodeTests.cpp \
tests/unit/SkiaBehaviorTests.cpp \
+ tests/unit/SnapshotTests.cpp \
tests/unit/StringUtilsTests.cpp \
tests/unit/TextDropShadowCacheTests.cpp \
- tests/unit/VectorDrawableTests.cpp \
- tests/unit/GradientCacheTests.cpp
+ tests/unit/VectorDrawableTests.cpp
ifeq (true, $(HWUI_NEW_OPS))
LOCAL_SRC_FILES += \
diff --git a/libs/hwui/BakedOpState.cpp b/libs/hwui/BakedOpState.cpp
index b70d586..9f98241 100644
--- a/libs/hwui/BakedOpState.cpp
+++ b/libs/hwui/BakedOpState.cpp
@@ -50,7 +50,7 @@
}
// resolvedClipRect = intersect(parentMatrix * localClip, parentClip)
- clipState = snapshot.mutateClipArea().serializeIntersectedClip(allocator,
+ clipState = snapshot.serializeIntersectedClip(allocator,
recordedOp.localClip, *(snapshot.transform));
LOG_ALWAYS_FATAL_IF(!clipState, "must clip!");
@@ -85,8 +85,7 @@
ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
const Matrix4& localTransform, const ClipBase* localClip) {
transform.loadMultiply(*snapshot.transform, localTransform);
- clipState = snapshot.mutateClipArea().serializeIntersectedClip(allocator,
- localClip, *(snapshot.transform));
+ clipState = snapshot.serializeIntersectedClip(allocator, localClip, *(snapshot.transform));
clippedBounds = clipState->rect;
clipSideFlags = OpClipSideFlags::Full;
localProjectionPathMask = nullptr;
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index f886dda..35fe06d 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -217,6 +217,7 @@
void ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform,
SkRegion::Op op) {
+ if (op == SkRegion::kReplace_Op) mReplaceOpObserved = true;
if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op;
onClipUpdated();
switch (mMode) {
@@ -233,6 +234,7 @@
}
void ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) {
+ if (op == SkRegion::kReplace_Op) mReplaceOpObserved = true;
if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op;
onClipUpdated();
enterRegionMode();
@@ -242,6 +244,7 @@
void ClipArea::clipPathWithTransform(const SkPath& path, const mat4* transform,
SkRegion::Op op) {
+ if (op == SkRegion::kReplace_Op) mReplaceOpObserved = true;
if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op;
onClipUpdated();
SkMatrix skTransform;
@@ -379,6 +382,7 @@
serialization->rect.set(mClipRegion.getBounds());
break;
}
+ serialization->intersectWithRoot = mReplaceOpObserved;
// TODO: this is only done for draw time, should eventually avoid for record time
serialization->rect.snapToPixelBoundaries();
mLastSerialization = serialization;
diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h
index 1654eb8..6eb2eef 100644
--- a/libs/hwui/ClipArea.h
+++ b/libs/hwui/ClipArea.h
@@ -103,6 +103,7 @@
: mode(ClipMode::Rectangle)
, rect(rect) {}
const ClipMode mode;
+ bool intersectWithRoot = false;
// Bounds of the clipping area, used to define the scissor, and define which
// portion of the stencil is updated/used
Rect rect;
@@ -173,8 +174,8 @@
return mMode == ClipMode::RectangleList;
}
- const ClipBase* serializeClip(LinearAllocator& allocator);
- const ClipBase* serializeIntersectedClip(LinearAllocator& allocator,
+ WARN_UNUSED_RESULT const ClipBase* serializeClip(LinearAllocator& allocator);
+ WARN_UNUSED_RESULT const ClipBase* serializeIntersectedClip(LinearAllocator& allocator,
const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
void applyClip(const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
@@ -214,6 +215,7 @@
ClipMode mMode;
bool mPostViewportClipObserved = false;
+ bool mReplaceOpObserved = false;
/**
* If mLastSerialization is non-null, it represents an already serialized copy
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 0401f2d..f12e523 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -462,7 +462,7 @@
int count = mCanvasState.save(SaveFlags::MatrixClip);
// apply state from RecordedOp (clip first, since op's clip is transformed by current matrix)
- mCanvasState.writableSnapshot()->mutateClipArea().applyClip(op.localClip,
+ mCanvasState.writableSnapshot()->applyClip(op.localClip,
*mCanvasState.currentSnapshot()->transform);
mCanvasState.concatMatrix(op.localMatrix);
diff --git a/libs/hwui/OpDumper.cpp b/libs/hwui/OpDumper.cpp
index c34cfbe..cab93e8 100644
--- a/libs/hwui/OpDumper.cpp
+++ b/libs/hwui/OpDumper.cpp
@@ -33,10 +33,15 @@
op.localMatrix.mapRect(localBounds);
output << sOpNameLut[op.opId] << " " << localBounds;
- if (op.localClip && !op.localClip->rect.contains(localBounds)) {
+ if (op.localClip
+ && (!op.localClip->rect.contains(localBounds) || op.localClip->intersectWithRoot)) {
output << std::fixed << std::setprecision(0)
<< " clip=" << op.localClip->rect
<< " mode=" << (int)op.localClip->mode;
+
+ if (op.localClip->intersectWithRoot) {
+ output << " iwr";
+ }
}
}
diff --git a/libs/hwui/PathParser.cpp b/libs/hwui/PathParser.cpp
index 4e9ac9c..7e85333 100644
--- a/libs/hwui/PathParser.cpp
+++ b/libs/hwui/PathParser.cpp
@@ -156,6 +156,12 @@
return;
}
+bool PathParser::isVerbValid(char verb) {
+ verb = tolower(verb);
+ return verb == 'a' || verb == 'c' || verb == 'h' || verb == 'l' || verb == 'm' || verb == 'q'
+ || verb == 's' || verb == 't' || verb == 'v' || verb == 'z';
+}
+
void PathParser::getPathDataFromString(PathData* data, ParseResult* result,
const char* pathStr, size_t strLen) {
if (pathStr == NULL) {
@@ -171,6 +177,12 @@
end = nextStart(pathStr, strLen, end);
std::vector<float> points;
getFloats(&points, result, pathStr, start, end);
+ if (!isVerbValid(pathStr[start])) {
+ result->failureOccurred = true;
+ result->failureMessage = "Invalid pathData. Failure occurred at position "
+ + std::to_string(start) + " of path: " + pathStr;
+ }
+ // If either verb or points is not valid, return immediately.
if (result->failureOccurred) {
return;
}
@@ -182,10 +194,15 @@
}
if ((end - start) == 1 && start < strLen) {
+ if (!isVerbValid(pathStr[start])) {
+ result->failureOccurred = true;
+ result->failureMessage = "Invalid pathData. Failure occurred at position "
+ + std::to_string(start) + " of path: " + pathStr;
+ return;
+ }
data->verbs.push_back(pathStr[start]);
data->verbSizes.push_back(0);
}
- return;
}
void PathParser::dump(const PathData& data) {
@@ -218,7 +235,8 @@
// Check if there is valid data coming out of parsing the string.
if (pathData.verbs.size() == 0) {
result->failureOccurred = true;
- result->failureMessage = "No verbs found in the string for pathData";
+ result->failureMessage = "No verbs found in the string for pathData: ";
+ result->failureMessage += pathStr;
return;
}
VectorDrawableUtils::verbsToPath(skPath, pathData);
diff --git a/libs/hwui/PathParser.h b/libs/hwui/PathParser.h
index c4bbb74..180a7a3 100644
--- a/libs/hwui/PathParser.h
+++ b/libs/hwui/PathParser.h
@@ -44,6 +44,7 @@
ANDROID_API static void getPathDataFromString(PathData* outData, ParseResult* result,
const char* pathStr, size_t strLength);
static void dump(const PathData& data);
+ static bool isVerbValid(char verb);
};
}; // namespace uirenderer
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 9578486..ea06fcd 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -81,14 +81,14 @@
#endif
}
-void RenderNode::setStagingDisplayList(DisplayList* displayList) {
+void RenderNode::setStagingDisplayList(DisplayList* displayList, TreeObserver* observer) {
mNeedsDisplayListSync = true;
delete mStagingDisplayList;
mStagingDisplayList = displayList;
// If mParentCount == 0 we are the sole reference to this RenderNode,
// so immediately free the old display list
if (!mParentCount && !mStagingDisplayList) {
- deleteDisplayList(nullptr);
+ deleteDisplayList(observer);
}
}
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index b0136cf..acdc3d8 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -117,7 +117,7 @@
void debugDumpLayers(const char* prefix);
- ANDROID_API void setStagingDisplayList(DisplayList* newData);
+ ANDROID_API void setStagingDisplayList(DisplayList* newData, TreeObserver* observer);
void computeOrdering();
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index d784280..2c9c9d9 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -242,6 +242,33 @@
#endif
}
+static Snapshot* getClipRoot(Snapshot* target) {
+ while (target->previous && target->previous->previous) {
+ target = target->previous;
+ }
+ return target;
+}
+
+const ClipBase* Snapshot::serializeIntersectedClip(LinearAllocator& allocator,
+ const ClipBase* recordedClip, const Matrix4& recordedClipTransform) {
+ auto target = this;
+ if (CC_UNLIKELY(recordedClip && recordedClip->intersectWithRoot)) {
+ // Clip must be intersected with root, instead of current clip.
+ target = getClipRoot(this);
+ }
+
+ return target->mClipArea->serializeIntersectedClip(allocator,
+ recordedClip, recordedClipTransform);
+}
+
+void Snapshot::applyClip(const ClipBase* recordedClip, const Matrix4& transform) {
+ if (CC_UNLIKELY(recordedClip && recordedClip->intersectWithRoot)) {
+ // current clip is being replaced, but must intersect with clip root
+ *mClipArea = *(getClipRoot(this)->mClipArea);
+ }
+ mClipArea->applyClip(recordedClip, transform);
+}
+
///////////////////////////////////////////////////////////////////////////////
// Queries
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 3a01d04..d8f926e 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -170,6 +170,10 @@
const ClipArea& getClipArea() const { return *mClipArea; }
ClipArea& mutateClipArea() { return *mClipArea; }
+ WARN_UNUSED_RESULT const ClipBase* serializeIntersectedClip(LinearAllocator& allocator,
+ const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
+ void applyClip(const ClipBase* clip, const Matrix4& transform);
+
/**
* Resets the clip to the specified rect.
*/
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index b9e3358..b39de26 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -22,8 +22,9 @@
namespace android {
-MinikinFontSkia::MinikinFontSkia(SkTypeface *typeface) :
- mTypeface(typeface) {
+MinikinFontSkia::MinikinFontSkia(SkTypeface* typeface, const void* fontData, size_t fontSize,
+ int ttcIndex) :
+ mTypeface(typeface), mFontData(fontData), mFontSize(fontSize), mTtcIndex(ttcIndex) {
}
MinikinFontSkia::~MinikinFontSkia() {
@@ -66,22 +67,38 @@
bounds->mBottom = skBounds.fBottom;
}
-bool MinikinFontSkia::GetTable(uint32_t tag, uint8_t *buf, size_t *size) {
- if (buf == NULL) {
- const size_t tableSize = mTypeface->getTableSize(tag);
- *size = tableSize;
- return tableSize != 0;
- } else {
- const size_t actualSize = mTypeface->getTableData(tag, 0, *size, buf);
- *size = actualSize;
- return actualSize != 0;
+const void* MinikinFontSkia::GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy) {
+ // we don't have a buffer to the font data, copy to own buffer
+ const size_t tableSize = mTypeface->getTableSize(tag);
+ *size = tableSize;
+ if (tableSize == 0) {
+ return nullptr;
}
+ void* buf = malloc(tableSize);
+ if (buf == nullptr) {
+ return nullptr;
+ }
+ mTypeface->getTableData(tag, 0, tableSize, buf);
+ *destroy = free;
+ return buf;
}
SkTypeface *MinikinFontSkia::GetSkTypeface() const {
return mTypeface;
}
+const void* MinikinFontSkia::GetFontData() const {
+ return mFontData;
+}
+
+size_t MinikinFontSkia::GetFontSize() const {
+ return mFontSize;
+}
+
+int MinikinFontSkia::GetFontIndex() const {
+ return mTtcIndex;
+}
+
int32_t MinikinFontSkia::GetUniqueId() const {
return mTypeface->uniqueID();
}
diff --git a/libs/hwui/hwui/MinikinSkia.h b/libs/hwui/hwui/MinikinSkia.h
index 1d50168..dbc65f9 100644
--- a/libs/hwui/hwui/MinikinSkia.h
+++ b/libs/hwui/hwui/MinikinSkia.h
@@ -28,7 +28,8 @@
class ANDROID_API MinikinFontSkia : public MinikinFont {
public:
// Note: this takes ownership of the reference (will unref on dtor)
- explicit MinikinFontSkia(SkTypeface *typeface);
+ explicit MinikinFontSkia(SkTypeface *typeface, const void* fontData, size_t fontSize,
+ int ttcIndex);
~MinikinFontSkia();
@@ -38,20 +39,30 @@
void GetBounds(MinikinRect* bounds, uint32_t glyph_id,
const MinikinPaint &paint) const;
- // If buf is NULL, just update size
- bool GetTable(uint32_t tag, uint8_t *buf, size_t *size);
+ const void* GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy);
int32_t GetUniqueId() const;
SkTypeface* GetSkTypeface() const;
+ // Access to underlying raw font bytes
+ const void* GetFontData() const;
+ size_t GetFontSize() const;
+ int GetFontIndex() const;
+
static uint32_t packPaintFlags(const SkPaint* paint);
static void unpackPaintFlags(SkPaint* paint, uint32_t paintFlags);
// set typeface and fake bold/italic parameters
static void populateSkPaint(SkPaint* paint, const MinikinFont* font, FontFakery fakery);
private:
- SkTypeface *mTypeface;
+ SkTypeface* mTypeface;
+
+ // A raw pointer to the font data - it should be owned by some other object with
+ // lifetime at least as long as this object.
+ const void* mFontData;
+ size_t mFontSize;
+ int mTtcIndex;
};
} // namespace android
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index fa8ad5d..c583988 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -66,7 +66,10 @@
ALOGD("makeFontCollection adding %s", fn);
SkTypeface *skFace = SkTypeface::CreateFromFile(fn);
if (skFace != NULL) {
- MinikinFont *font = new MinikinFontSkia(skFace);
+ // TODO: might be a nice optimization to get access to the underlying font
+ // data, but would require us opening the file ourselves and passing that
+ // to the appropriate Create method of SkTypeface.
+ MinikinFont *font = new MinikinFontSkia(skFace, NULL, 0, 0);
family->addFont(font);
font->Unref();
} else {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 63fa788..890d4a1 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -76,15 +76,15 @@
}
CanvasContext::~CanvasContext() {
- destroy();
+ destroy(nullptr);
mRenderThread.renderState().unregisterCanvasContext(this);
}
-void CanvasContext::destroy() {
+void CanvasContext::destroy(TreeObserver* observer) {
stopDrawing();
setSurface(nullptr);
- freePrefetechedLayers();
- destroyHardwareResources();
+ freePrefetchedLayers(observer);
+ destroyHardwareResources(observer);
mAnimationContext->destroy();
#if !HWUI_NEW_OPS
if (mCanvas) {
@@ -113,18 +113,11 @@
mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
mHaveNewSurface = true;
mSwapHistory.clear();
- makeCurrent();
} else {
mRenderThread.removeFrameCallback(this);
}
}
-void CanvasContext::requireSurface() {
- LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
- "requireSurface() called but no surface set!");
- makeCurrent();
-}
-
void CanvasContext::setSwapBehavior(SwapBehavior swapBehavior) {
mSwapBehavior = swapBehavior;
}
@@ -146,6 +139,18 @@
return mRenderThread.removeFrameCallback(this);
}
+void CanvasContext::setStopped(bool stopped) {
+ if (mStopped != stopped) {
+ mStopped = stopped;
+ if (mStopped) {
+ mRenderThread.removeFrameCallback(this);
+ if (mEglManager.isCurrent(mEglSurface)) {
+ mEglManager.makeCurrent(EGL_NO_SURFACE);
+ }
+ }
+ }
+}
+
// TODO: don't pass viewport size, it's automatic via EGL
void CanvasContext::setup(int width, int height, float lightRadius,
uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
@@ -172,7 +177,9 @@
mOpaque = opaque;
}
-void CanvasContext::makeCurrent() {
+bool CanvasContext::makeCurrent() {
+ if (mStopped) return false;
+
// TODO: Figure out why this workaround is needed, see b/13913604
// In the meantime this matches the behavior of GLRenderer, so it is not a regression
EGLint error = 0;
@@ -180,6 +187,7 @@
if (error) {
setSurface(nullptr);
}
+ return !error;
}
static bool wasSkipped(FrameInfo* info) {
@@ -222,7 +230,7 @@
mAnimationContext->runRemainingAnimations(info);
GL_CHECKPOINT(MODERATE);
- freePrefetechedLayers();
+ freePrefetchedLayers(info.observer);
GL_CHECKPOINT(MODERATE);
if (CC_UNLIKELY(!mNativeSurface.get())) {
@@ -569,25 +577,24 @@
}
void CanvasContext::markLayerInUse(RenderNode* node) {
- if (mPrefetechedLayers.erase(node)) {
+ if (mPrefetchedLayers.erase(node)) {
node->decStrong(nullptr);
}
}
-static void destroyPrefetechedNode(RenderNode* node) {
- ALOGW("Incorrectly called buildLayer on View: %s, destroying layer...", node->getName());
- node->destroyHardwareResources(nullptr);
- node->decStrong(nullptr);
-}
-
-void CanvasContext::freePrefetechedLayers() {
- if (mPrefetechedLayers.size()) {
- std::for_each(mPrefetechedLayers.begin(), mPrefetechedLayers.end(), destroyPrefetechedNode);
- mPrefetechedLayers.clear();
+void CanvasContext::freePrefetchedLayers(TreeObserver* observer) {
+ if (mPrefetchedLayers.size()) {
+ for (auto& node : mPrefetchedLayers) {
+ ALOGW("Incorrectly called buildLayer on View: %s, destroying layer...",
+ node->getName());
+ node->destroyHardwareResources(observer);
+ node->decStrong(observer);
+ }
+ mPrefetchedLayers.clear();
}
}
-void CanvasContext::buildLayer(RenderNode* node) {
+void CanvasContext::buildLayer(RenderNode* node, TreeObserver* observer) {
ATRACE_CALL();
if (!mEglManager.hasEglContext()) return;
#if !HWUI_NEW_OPS
@@ -599,6 +606,7 @@
TreeInfo info(TreeInfo::MODE_FULL, *this);
info.damageAccumulator = &mDamageAccumulator;
+ info.observer = observer;
#if HWUI_NEW_OPS
info.layerUpdateQueue = &mLayerUpdateQueue;
#else
@@ -628,7 +636,7 @@
#endif
node->incStrong(nullptr);
- mPrefetechedLayers.insert(node);
+ mPrefetchedLayers.insert(node);
}
bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
@@ -636,12 +644,12 @@
return LayerRenderer::copyLayer(mRenderThread.renderState(), layer->backingLayer(), bitmap);
}
-void CanvasContext::destroyHardwareResources() {
+void CanvasContext::destroyHardwareResources(TreeObserver* observer) {
stopDrawing();
if (mEglManager.hasEglContext()) {
- freePrefetechedLayers();
+ freePrefetchedLayers(observer);
for (const sp<RenderNode>& node : mRenderNodes) {
- node->destroyHardwareResources(nullptr);
+ node->destroyHardwareResources(observer);
}
Caches& caches = Caches::getInstance();
// Make sure to release all the textures we were owning as there won't
@@ -671,7 +679,7 @@
}
Layer* CanvasContext::createTextureLayer() {
- requireSurface();
+ mEglManager.initialize();
return LayerRenderer::createTextureLayer(mRenderThread.renderState());
}
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 6d0889e..52df3abe 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -82,27 +82,28 @@
void initialize(Surface* surface);
void updateSurface(Surface* surface);
bool pauseSurface(Surface* surface);
+ void setStopped(bool stopped);
bool hasSurface() { return mNativeSurface.get(); }
void setup(int width, int height, float lightRadius,
uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
void setLightCenter(const Vector3& lightCenter);
void setOpaque(bool opaque);
- void makeCurrent();
+ bool makeCurrent();
void prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
int64_t syncQueued, RenderNode* target);
void draw();
- void destroy();
+ void destroy(TreeObserver* observer);
// IFrameCallback, Choreographer-driven frame callback entry point
virtual void doFrame() override;
void prepareAndDraw(RenderNode* node);
- void buildLayer(RenderNode* node);
+ void buildLayer(RenderNode* node, TreeObserver* observer);
bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
void markLayerInUse(RenderNode* node);
- void destroyHardwareResources();
+ void destroyHardwareResources(TreeObserver* observer);
static void trimMemory(RenderThread& thread, int level);
static void invokeFunctor(RenderThread& thread, Functor* functor);
@@ -172,9 +173,8 @@
friend class android::uirenderer::RenderState;
void setSurface(Surface* window);
- void requireSurface();
- void freePrefetechedLayers();
+ void freePrefetchedLayers(TreeObserver* observer);
void waitOnFences();
@@ -185,6 +185,7 @@
EglManager& mEglManager;
sp<Surface> mNativeSurface;
EGLSurface mEglSurface = EGL_NO_SURFACE;
+ bool mStopped = false;
bool mBufferPreserved = false;
SwapBehavior mSwapBehavior = kSwap_default;
struct SwapHistory {
@@ -218,7 +219,7 @@
FrameInfoVisualizer mProfiler;
std::unique_ptr<FrameMetricsReporter> mFrameMetricsReporter;
- std::set<RenderNode*> mPrefetechedLayers;
+ std::set<RenderNode*> mPrefetchedLayers;
// Stores the bounds of the main content.
Rect mContentDrawBounds;
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index e8b9725..ed472ac 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -65,11 +65,12 @@
}
}
-int DrawFrameTask::drawFrame() {
+int DrawFrameTask::drawFrame(TreeObserver* observer) {
LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
mSyncResult = kSync_OK;
mSyncQueued = systemTime(CLOCK_MONOTONIC);
+ mObserver = observer;
postAndWait();
return mSyncResult;
@@ -88,6 +89,7 @@
bool canDrawThisFrame;
{
TreeInfo info(TreeInfo::MODE_FULL, *mContext);
+ info.observer = mObserver;
canUnblockUiThread = syncFrameState(info);
canDrawThisFrame = info.out.canDrawThisFrame;
}
@@ -113,7 +115,7 @@
ATRACE_CALL();
int64_t vsync = mFrameInfo[static_cast<int>(FrameInfoIndex::Vsync)];
mRenderThread->timeLord().vsyncReceived(vsync);
- mContext->makeCurrent();
+ bool canDraw = mContext->makeCurrent();
Caches::getInstance().textureCache.resetMarkInUse(mContext);
for (size_t i = 0; i < mLayers.size(); i++) {
@@ -124,8 +126,9 @@
// This is after the prepareTree so that any pending operations
// (RenderNode tree state, prefetched layers, etc...) will be flushed.
- if (CC_UNLIKELY(!mContext->hasSurface())) {
+ if (CC_UNLIKELY(!mContext->hasSurface() || !canDraw)) {
mSyncResult |= kSync_LostSurfaceRewardIfFound;
+ info.out.canDrawThisFrame = false;
}
if (info.out.hasAnimations) {
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index cae251a9..9bba065 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -62,7 +62,7 @@
void pushLayerUpdate(DeferredLayerUpdater* layer);
void removeLayerUpdate(DeferredLayerUpdater* layer);
- int drawFrame();
+ int drawFrame(TreeObserver* observer);
int64_t* frameInfo() { return mFrameInfo; }
@@ -87,6 +87,7 @@
int mSyncResult;
int64_t mSyncQueued;
+ TreeObserver* mObserver;
int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
};
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 8def7ad..ac6a28f 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -270,12 +270,6 @@
// 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();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 16dd108..c5a2dc7 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -52,14 +52,6 @@
MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
ARGS(method) *args = (ARGS(method) *) task->payload()
-namespace DumpFlags {
- enum {
- FrameStats = 1 << 0,
- Reset = 1 << 1,
- JankStats = 1 << 2,
- };
-};
-
CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
RenderNode* rootRenderNode, IContextFactory* contextFactory) {
return new CanvasContext(*args->thread, args->translucent,
@@ -175,6 +167,18 @@
return (bool) postAndWait(task);
}
+CREATE_BRIDGE2(setStopped, CanvasContext* context, bool stopped) {
+ args->context->setStopped(args->stopped);
+ return nullptr;
+}
+
+void RenderProxy::setStopped(bool stopped) {
+ SETUP_TASK(setStopped);
+ args->context = mContext;
+ args->stopped = stopped;
+ postAndWait(task);
+}
+
CREATE_BRIDGE6(setup, CanvasContext* context, int width, int height,
float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
args->context->setup(args->width, args->height, args->lightRadius,
@@ -222,18 +226,19 @@
return mDrawFrameTask.frameInfo();
}
-int RenderProxy::syncAndDrawFrame() {
- return mDrawFrameTask.drawFrame();
+int RenderProxy::syncAndDrawFrame(TreeObserver* observer) {
+ return mDrawFrameTask.drawFrame(observer);
}
-CREATE_BRIDGE1(destroy, CanvasContext* context) {
- args->context->destroy();
+CREATE_BRIDGE2(destroy, CanvasContext* context, TreeObserver* observer) {
+ args->context->destroy(args->observer);
return nullptr;
}
-void RenderProxy::destroy() {
+void RenderProxy::destroy(TreeObserver* observer) {
SETUP_TASK(destroy);
args->context = mContext;
+ args->observer = observer;
// destroyCanvasAndSurface() needs a fence as when it returns the
// underlying BufferQueue is going to be released from under
// the render thread.
@@ -287,15 +292,16 @@
return layer;
}
-CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) {
- args->context->buildLayer(args->node);
+CREATE_BRIDGE3(buildLayer, CanvasContext* context, RenderNode* node, TreeObserver* observer) {
+ args->context->buildLayer(args->node, args->observer);
return nullptr;
}
-void RenderProxy::buildLayer(RenderNode* node) {
+void RenderProxy::buildLayer(RenderNode* node, TreeObserver* observer) {
SETUP_TASK(buildLayer);
args->context = mContext;
args->node = node;
+ args->observer = observer;
postAndWait(task);
}
@@ -332,15 +338,16 @@
postAndWait(task);
}
-CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) {
- args->context->destroyHardwareResources();
+CREATE_BRIDGE2(destroyHardwareResources, CanvasContext* context, TreeObserver* observer) {
+ args->context->destroyHardwareResources(args->observer);
return nullptr;
}
-void RenderProxy::destroyHardwareResources() {
+void RenderProxy::destroyHardwareResources(TreeObserver* observer) {
SETUP_TASK(destroyHardwareResources);
args->context = mContext;
- post(task);
+ args->observer = observer;
+ postAndWait(task);
}
CREATE_BRIDGE2(trimMemory, RenderThread* thread, int level) {
@@ -422,6 +429,9 @@
if (args->dumpFlags & DumpFlags::Reset) {
args->context->resetFrameStats();
}
+ if (args->dumpFlags & DumpFlags::JankStats) {
+ args->thread->jankTracker().dump(args->fd);
+ }
return nullptr;
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 8d65a82..32d3283b 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -42,6 +42,7 @@
class DisplayList;
class Layer;
class Rect;
+class TreeObserver;
namespace renderthread {
@@ -49,6 +50,14 @@
class RenderThread;
class RenderProxyBridge;
+namespace DumpFlags {
+ enum {
+ FrameStats = 1 << 0,
+ Reset = 1 << 1,
+ JankStats = 1 << 2,
+ };
+};
+
/*
* RenderProxy is strictly single threaded. All methods must be invoked on the owning
* thread. It is important to note that RenderProxy may be deleted while it has
@@ -70,26 +79,27 @@
ANDROID_API void initialize(const sp<Surface>& surface);
ANDROID_API void updateSurface(const sp<Surface>& surface);
ANDROID_API bool pauseSurface(const sp<Surface>& surface);
+ ANDROID_API void setStopped(bool stopped);
ANDROID_API void setup(int width, int height, float lightRadius,
uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
ANDROID_API void setLightCenter(const Vector3& lightCenter);
ANDROID_API void setOpaque(bool opaque);
ANDROID_API int64_t* frameInfo();
- ANDROID_API int syncAndDrawFrame();
- ANDROID_API void destroy();
+ ANDROID_API int syncAndDrawFrame(TreeObserver* observer);
+ ANDROID_API void destroy(TreeObserver* observer);
ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion);
ANDROID_API void runWithGlContext(RenderTask* task);
ANDROID_API DeferredLayerUpdater* createTextureLayer();
- ANDROID_API void buildLayer(RenderNode* node);
+ ANDROID_API void buildLayer(RenderNode* node, TreeObserver* observer);
ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap);
ANDROID_API void pushLayerUpdate(DeferredLayerUpdater* layer);
ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer);
ANDROID_API void detachSurfaceTexture(DeferredLayerUpdater* layer);
- ANDROID_API void destroyHardwareResources();
+ ANDROID_API void destroyHardwareResources(TreeObserver* observer);
ANDROID_API static void trimMemory(int level);
ANDROID_API static void overrideProperty(const char* name, const char* value);
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 5492035..5f4ebc0 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -146,7 +146,7 @@
if (setup) {
TestCanvas canvas(props.getWidth(), props.getHeight());
setup(props, canvas);
- node->setStagingDisplayList(canvas.finishRecording());
+ node->setStagingDisplayList(canvas.finishRecording(), nullptr);
}
node->setPropertyFieldsDirty(0xFFFFFFFF);
return node;
@@ -157,7 +157,7 @@
TestCanvas canvas(node.stagingProperties().getWidth(),
node.stagingProperties().getHeight());
contentCallback(canvas);
- node.setStagingDisplayList(canvas.finishRecording());
+ node.setStagingDisplayList(canvas.finishRecording(), nullptr);
}
/**
diff --git a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
index 63c067b..f184411 100644
--- a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
@@ -59,6 +59,6 @@
0, 100 * (i + 2), kBidi_Force_LTR, paint, nullptr);
}
- container->setStagingDisplayList(canvas.finishRecording());
+ container->setStagingDisplayList(canvas.finishRecording(), nullptr);
}
};
diff --git a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
index ab368c05..8035dc4 100644
--- a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
@@ -76,7 +76,7 @@
// draw it to parent DisplayList
canvas.drawRenderNode(cards[ci].get());
}
- listView->setStagingDisplayList(canvas.finishRecording());
+ listView->setStagingDisplayList(canvas.finishRecording(), nullptr);
}
private:
SkBitmap createRandomCharIcon() {
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 58c0876..c5af061 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -95,7 +95,7 @@
testContext.waitForVsync();
nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
- proxy->syncAndDrawFrame();
+ proxy->syncAndDrawFrame(nullptr);
}
proxy->resetProfileInfo();
@@ -110,7 +110,7 @@
ATRACE_NAME("UI-Draw Frame");
UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
scene->doFrame(i);
- proxy->syncAndDrawFrame();
+ proxy->syncAndDrawFrame(nullptr);
}
if (opts.reportFrametimeWeight) {
proxy->fence();
@@ -122,5 +122,5 @@
}
}
- proxy->dumpProfileInfo(STDOUT_FILENO, 0);
+ proxy->dumpProfileInfo(STDOUT_FILENO, DumpFlags::JankStats);
}
diff --git a/libs/hwui/tests/unit/ClipAreaTests.cpp b/libs/hwui/tests/unit/ClipAreaTests.cpp
index 822d04f..b864703 100644
--- a/libs/hwui/tests/unit/ClipAreaTests.cpp
+++ b/libs/hwui/tests/unit/ClipAreaTests.cpp
@@ -132,8 +132,7 @@
auto serializedClip = area.serializeClip(allocator);
ASSERT_NE(nullptr, serializedClip);
ASSERT_EQ(ClipMode::Rectangle, serializedClip->mode);
- auto clipRect = reinterpret_cast<const ClipRect*>(serializedClip);
- EXPECT_EQ(Rect(200, 200), clipRect->rect);
+ EXPECT_EQ(Rect(200, 200), serializedClip->rect);
EXPECT_EQ(serializedClip, area.serializeClip(allocator))
<< "Requery of clip on unmodified ClipArea must return same pointer.";
}
@@ -192,8 +191,7 @@
auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip, translateScale);
ASSERT_NE(nullptr, resolvedClip);
ASSERT_EQ(ClipMode::Rectangle, resolvedClip->mode);
- EXPECT_EQ(Rect(100, 100, 200, 200),
- reinterpret_cast<const ClipRect*>(resolvedClip)->rect);
+ EXPECT_EQ(Rect(100, 100, 200, 200), resolvedClip->rect);
EXPECT_EQ(resolvedClip, area.serializeIntersectedClip(allocator, &recordedClip, translateScale))
<< "Must return previous serialization, since input is same";
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 0ea246f..9877439 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -1946,5 +1946,28 @@
EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix);
}
+RENDERTHREAD_TEST(FrameBuilder, clip_replace) {
+ class ClipReplaceTestRenderer : public TestRendererBase {
+ public:
+ void onColorOp(const ColorOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(0, mIndex++);
+ EXPECT_TRUE(op.localClip->intersectWithRoot);
+ EXPECT_EQ(Rect(20, 10, 30, 40), state.computedState.clipState->rect)
+ << "Expect resolved clip to be intersection of viewport clip and clip op";
+ }
+ };
+ auto node = TestUtils::createNode(20, 20, 30, 30,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.clipRect(0, -20, 10, 30, SkRegion::kReplace_Op);
+ canvas.drawColor(SK_ColorWHITE, SkXfermode::Mode::kSrcOver_Mode);
+ });
+
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeLTRB(10, 10, 40, 40), 50, 50,
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
+ ClipReplaceTestRenderer renderer;
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+ EXPECT_EQ(1, renderer.getIndex());
+}
+
} // namespace uirenderer
} // namespace android
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index 58376c6..c49ff71 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -569,6 +569,19 @@
EXPECT_CLIP_RECT(Rect(-100, -100, 300, 300), dl->getOps()[0]->localClip);
}
+TEST(RecordingCanvas, replaceClipIntersectWithRoot) {
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [](RecordingCanvas& canvas) {
+ canvas.save(SaveFlags::MatrixClip);
+ canvas.clipRect(-10, -10, 110, 110, SkRegion::kReplace_Op);
+ canvas.drawColor(SK_ColorWHITE, SkXfermode::Mode::kSrcOver_Mode);
+ canvas.restore();
+ });
+ ASSERT_EQ(1u, dl->getOps().size()) << "Must have one op";
+ // first clip must be preserved, even if it extends beyond canvas bounds
+ EXPECT_CLIP_RECT(Rect(-10, -10, 110, 110), dl->getOps()[0]->localClip);
+ EXPECT_TRUE(dl->getOps()[0]->localClip->intersectWithRoot);
+}
+
TEST(RecordingCanvas, insertReorderBarrier) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
canvas.drawRect(0, 0, 400, 400, SkPaint());
diff --git a/libs/hwui/tests/unit/SnapshotTests.cpp b/libs/hwui/tests/unit/SnapshotTests.cpp
new file mode 100644
index 0000000..11797a8
--- /dev/null
+++ b/libs/hwui/tests/unit/SnapshotTests.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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 <Snapshot.h>
+
+#include <tests/common/TestUtils.h>
+
+using namespace android::uirenderer;
+
+TEST(Snapshot, serializeIntersectedClip) {
+ auto actualRoot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(0, 0, 100, 100));
+ auto root = TestUtils::makeSnapshot(Matrix4::identity(), Rect(10, 10, 90, 90));
+ auto child = TestUtils::makeSnapshot(Matrix4::identity(), Rect(50, 50, 90, 90));
+ root->previous = actualRoot.get();
+ child->previous = root.get();
+
+ LinearAllocator allocator;
+ ClipRect rect(Rect(0, 0, 75, 75));
+ {
+ auto intersectWithChild = child->serializeIntersectedClip(allocator,
+ &rect, Matrix4::identity());
+ ASSERT_NE(nullptr, intersectWithChild);
+ EXPECT_EQ(Rect(50, 50, 75, 75), intersectWithChild->rect) << "Expect intersect with child";
+ }
+
+ rect.intersectWithRoot = true;
+ {
+ auto intersectWithRoot = child->serializeIntersectedClip(allocator,
+ &rect, Matrix4::identity());
+ ASSERT_NE(nullptr, intersectWithRoot);
+ EXPECT_EQ(Rect(10, 10, 75, 75), intersectWithRoot->rect) << "Expect intersect with root";
+ }
+}
+
+TEST(Snapshot, applyClip) {
+ auto actualRoot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(0, 0, 100, 100));
+ auto root = TestUtils::makeSnapshot(Matrix4::identity(), Rect(10, 10, 90, 90));
+ root->previous = actualRoot.get();
+
+ ClipRect rect(Rect(0, 0, 75, 75));
+ {
+ auto child = TestUtils::makeSnapshot(Matrix4::identity(), Rect(50, 50, 90, 90));
+ child->previous = root.get();
+ child->applyClip(&rect, Matrix4::identity());
+
+ EXPECT_TRUE(child->getClipArea().isSimple());
+ EXPECT_EQ(Rect(50, 50, 75, 75), child->getRenderTargetClip());
+ }
+
+ {
+ rect.intersectWithRoot = true;
+ auto child = TestUtils::makeSnapshot(Matrix4::identity(), Rect(50, 50, 90, 90));
+ child->previous = root.get();
+ child->applyClip(&rect, Matrix4::identity());
+
+ EXPECT_TRUE(child->getClipArea().isSimple());
+ EXPECT_EQ(Rect(10, 10, 75, 75), child->getRenderTargetClip());
+ }
+}
diff --git a/libs/hwui/tests/unit/VectorDrawableTests.cpp b/libs/hwui/tests/unit/VectorDrawableTests.cpp
index 7208547..796169e 100644
--- a/libs/hwui/tests/unit/VectorDrawableTests.cpp
+++ b/libs/hwui/tests/unit/VectorDrawableTests.cpp
@@ -231,11 +231,12 @@
};
const StringPath sStringPaths[] = {
- {"3e...3", false},
- {"L.M.F.A.O", false},
- {"m 1 1", true},
- {"z", true},
- {"1-2e34567", false}
+ {"3e...3", false}, // Not starting with a verb and ill-formatted float
+ {"L.M.F.A.O", false}, // No floats following verbs
+ {"m 1 1", true}, // Valid path data
+ {"z", true}, // Valid path data
+ {"1-2e34567", false}, // Not starting with a verb and ill-formatted float
+ {"f 4 5", false} // Invalid verb
};
diff --git a/libs/hwui/utils/TestWindowContext.cpp b/libs/hwui/utils/TestWindowContext.cpp
index b0431ce..b3195c4 100644
--- a/libs/hwui/utils/TestWindowContext.cpp
+++ b/libs/hwui/utils/TestWindowContext.cpp
@@ -104,8 +104,8 @@
}
void finishDrawing() {
- mRootNode->setStagingDisplayList(mCanvas->finishRecording());
- mProxy->syncAndDrawFrame();
+ mRootNode->setStagingDisplayList(mCanvas->finishRecording(), nullptr);
+ mProxy->syncAndDrawFrame(nullptr);
// Surprisingly, calling mProxy->fence() here appears to make no difference to
// the timings we record.
}
diff --git a/location/java/android/location/GnssClock.java b/location/java/android/location/GnssClock.java
index df42a73..25d247d 100644
--- a/location/java/android/location/GnssClock.java
+++ b/location/java/android/location/GnssClock.java
@@ -22,7 +22,8 @@
/**
* A class containing a GPS clock timestamp.
- * It represents a measurement of the GPS receiver's clock.
+ *
+ * <p>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
@@ -85,7 +86,7 @@
}
/**
- * Returns true if {@link #getLeapSecond()} is available, false otherwise.
+ * Returns {@code true} if {@link #getLeapSecond()} is available, {@code false} otherwise.
*/
public boolean hasLeapSecond() {
return isFlagSet(HAS_LEAP_SECOND);
@@ -93,10 +94,12 @@
/**
* Gets the leap second associated with the clock's time.
- * The sign of the value is defined by the following equation:
- * utc_time_ns = time_ns + (full_bias_ns + bias_ns) - leap_second * 1,000,000,000
*
- * The value is only available if {@link #hasLeapSecond()} is true.
+ * <p>The sign of the value is defined by the following equation:
+ * <pre>
+ * UtcTimeNanos = TimeNanos - (FullBiasNanos + BiasNanos) - LeapSecond * 1,000,000,000</pre>
+ *
+ * <p>The value is only available if {@link #hasLeapSecond()} is {@code true}.
*/
public int getLeapSecond() {
return mLeapSecond;
@@ -123,18 +126,15 @@
}
/**
- * Gets the GNSS receiver internal clock value in nanoseconds.
+ * Gets the GNSS receiver internal hardware 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 #getFullBiasNanos()} (when it is available) from this value.
+ * <p>This value is expected to be monotonically increasing while the hardware clock remains
+ * powered on. For the case of a hardware clock that is not continuously on, see the
+ * {@link #getHardwareClockDiscontinuityCount} field. The GPS time can be derived by subtracting
+ * the sum of {@link #getFullBiasNanos()} and {@link #getBiasNanos()} (when they are available)
+ * from this value. Sub-nanosecond accuracy can be provided by means of {@link #getBiasNanos()}.
*
- * For 'GPS time' this value is expected to be the best estimation of current GPS time that GPS
- * receiver can achieve. {@link #getTimeUncertaintyNanos()} should be available when GPS time is
- * specified.
- *
- * Sub-nanosecond accuracy can be provided by means of {@link #getBiasNanos()}.
- * The reported time includes {@link #getTimeUncertaintyNanos()}.
+ * <p>The error estimate for this value (if applicable) is {@link #getTimeUncertaintyNanos()}.
*/
public long getTimeNanos() {
return mTimeNanos;
@@ -150,7 +150,8 @@
}
/**
- * Returns true if {@link #getTimeUncertaintyNanos()} is available, false otherwise.
+ * Returns {@code true} if {@link #getTimeUncertaintyNanos()} is available, {@code false}
+ * otherwise.
*/
public boolean hasTimeUncertaintyNanos() {
return isFlagSet(HAS_TIME_UNCERTAINTY);
@@ -158,9 +159,13 @@
/**
* 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 #hasTimeUncertaintyNanos()} is true.
+ * <p>The uncertainty is represented as an absolute (single sided) value.
+ *
+ * <p>The value is only available if {@link #hasTimeUncertaintyNanos()} is {@code true}.
+ *
+ * <p>This value is often effectively zero (it is the reference clock by which all other times
+ * and time uncertainties are measured), and thus this field may often be 0, or not provided.
*/
public double getTimeUncertaintyNanos() {
return mTimeUncertaintyNanos;
@@ -187,7 +192,7 @@
}
/**
- * Returns true if {@link #getFullBiasNanos()} is available, false otherwise.
+ * Returns {@code true} if {@link #getFullBiasNanos()} is available, {@code false} otherwise.
*/
public boolean hasFullBiasNanos() {
return isFlagSet(HAS_FULL_BIAS);
@@ -197,14 +202,18 @@
* 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 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.
+ * <p>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 is only available if {@link #hasFullBiasNanos()} is
+ * {@code true}.
*
- * The sign of the value is defined by the following equation:
- * local estimate of GPS time = time_ns + (full_bias_ns + bias_ns)
+ * <p>The error estimate for the sum of this field and {@link #getBiasNanos} is
+ * {@link #getBiasUncertaintyNanos()}.
+ *
+ * <p>The sign of the value is defined by the following equation:
+ *
+ * <pre>
+ * local estimate of GPS time = TimeNanos - (FullBiasNanos + BiasNanos)</pre>
*/
public long getFullBiasNanos() {
return mFullBiasNanos;
@@ -231,7 +240,7 @@
}
/**
- * Returns true if {@link #getBiasNanos()} is available, false otherwise.
+ * Returns {@code true} if {@link #getBiasNanos()} is available, {@code false} otherwise.
*/
public boolean hasBiasNanos() {
return isFlagSet(HAS_BIAS);
@@ -239,9 +248,14 @@
/**
* Gets the clock's sub-nanosecond bias.
- * The reported bias includes {@link #getBiasUncertaintyNanos()}.
*
- * The value is only available if {@link #hasBiasNanos()} is true.
+ * <p>See the description of how this field is part of converting from hardware clock time, to
+ * GPS time, in {@link #getFullBiasNanos()}.
+ *
+ * <p>The error estimate for the sum of this field and {@link #getFullBiasNanos} is
+ * {@link #getBiasUncertaintyNanos()}.
+ *
+ * <p>The value is only available if {@link #hasBiasNanos()} is {@code true}.
*/
public double getBiasNanos() {
return mBiasNanos;
@@ -268,7 +282,8 @@
}
/**
- * Returns true if {@link #getBiasUncertaintyNanos()} is available, false otherwise.
+ * Returns {@code true} if {@link #getBiasUncertaintyNanos()} is available, {@code false}
+ * otherwise.
*/
public boolean hasBiasUncertaintyNanos() {
return isFlagSet(HAS_BIAS_UNCERTAINTY);
@@ -277,7 +292,10 @@
/**
* Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
*
- * The value is only available if {@link #hasBiasUncertaintyNanos()} is true.
+ * <p>See the description of how this field provides the error estimate in the conversion from
+ * hardware clock time, to GPS time, in {@link #getFullBiasNanos()}.
+ *
+ * <p>The value is only available if {@link #hasBiasUncertaintyNanos()} is {@code true}.
*/
public double getBiasUncertaintyNanos() {
return mBiasUncertaintyNanos;
@@ -304,7 +322,8 @@
}
/**
- * Returns true if {@link #getDriftNanosPerSecond()} is available, false otherwise.
+ * Returns {@code true} if {@link #getDriftNanosPerSecond()} is available, {@code false}
+ * otherwise.
*/
public boolean hasDriftNanosPerSecond() {
return isFlagSet(HAS_DRIFT);
@@ -312,10 +331,12 @@
/**
* 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 #getDriftUncertaintyNanosPerSecond()}.
*
- * The value is only available if {@link #hasDriftNanosPerSecond()} is true.
+ * <p>A positive value indicates that the frequency is higher than the nominal (e.g. GPS master
+ * clock) frequency. The error estimate for this reported drift is
+ * {@link #getDriftUncertaintyNanosPerSecond()}.
+ *
+ * <p>The value is only available if {@link #hasDriftNanosPerSecond()} is {@code true}.
*/
public double getDriftNanosPerSecond() {
return mDriftNanosPerSecond;
@@ -342,7 +363,8 @@
}
/**
- * Returns true if {@link #getDriftUncertaintyNanosPerSecond()} is available, false otherwise.
+ * Returns {@code true} if {@link #getDriftUncertaintyNanosPerSecond()} is available,
+ * {@code false} otherwise.
*/
public boolean hasDriftUncertaintyNanosPerSecond() {
return isFlagSet(HAS_DRIFT_UNCERTAINTY);
@@ -351,7 +373,8 @@
/**
* Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
*
- * The value is only available if {@link #hasDriftUncertaintyNanosPerSecond()} is true.
+ * <p>The value is only available if {@link #hasDriftUncertaintyNanosPerSecond()} is
+ * {@code true}.
*/
public double getDriftUncertaintyNanosPerSecond() {
return mDriftUncertaintyNanosPerSecond;
@@ -368,7 +391,29 @@
}
/**
- * Gets count of last hardware clock discontinuity.
+ * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
+ * @hide
+ */
+ @TestApi
+ public void resetDriftUncertaintyNanosPerSecond() {
+ resetFlag(HAS_DRIFT_UNCERTAINTY);
+ mDriftUncertaintyNanosPerSecond = Double.NaN;
+ }
+
+ /**
+ * Gets count of hardware clock discontinuities.
+ *
+ * <p>When this value stays the same, vs. a value in a previously reported {@link GnssClock}, it
+ * can be safely assumed that the {@code TimeNanos} value has been derived from a clock that has
+ * been running continuously - e.g. a single continuously powered crystal oscillator, and thus
+ * the {@code (FullBiasNanos + BiasNanos)} offset can be modelled with traditional clock bias
+ * & drift models.
+ *
+ * <p>Each time this value changes, vs. the value in a previously reported {@link GnssClock},
+ * that suggests the hardware clock may have experienced a discontinuity (e.g. a power cycle or
+ * other anomaly), so that any assumptions about modelling a smoothly changing
+ * {@code (FullBiasNanos + BiasNanos)} offset, and a smoothly growing {@code (TimeNanos)}
+ * between this and the previously reported {@code GnssClock}, should be reset.
*/
public int getHardwareClockDiscontinuityCount() {
return mHardwareClockDiscontinuityCount;
@@ -383,16 +428,6 @@
mHardwareClockDiscontinuityCount = value;
}
- /**
- * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
- * @hide
- */
- @TestApi
- public void resetDriftUncertaintyNanosPerSecond() {
- resetFlag(HAS_DRIFT_UNCERTAINTY);
- mDriftUncertaintyNanosPerSecond = Double.NaN;
- }
-
public static final Creator<GnssClock> CREATOR = new Creator<GnssClock>() {
@Override
public GnssClock createFromParcel(Parcel parcel) {
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index d78ccee..761ee22 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -67,18 +67,21 @@
public @interface MultipathIndicator {}
/**
- * The indicator is not available or it is unknown.
+ * The indicator is not available or the presence or absence of multipath is unknown.
*/
public static final int MULTIPATH_INDICATOR_UNKNOWN = 0;
/**
- * The measurement has been indicated to use multi-path.
+ * The measurement shows signs of multi-path.
*/
public static final int MULTIPATH_INDICATOR_DETECTED = 1;
/**
- * The measurement has been indicated not tu use multi-path.
+ * The measurement shows no signs of multi-path.
*/
+ public static final int MULTIPATH_INDICATOR_NOT_DETECTED = 2;
+
+ /** @removed */
public static final int MULTIPATH_INDICATOR_NOT_USED = 2;
/** This GNSS measurement's tracking state is invalid or unknown. */
@@ -192,15 +195,17 @@
}
/**
- * Gets the Pseudo-random number (PRN).
- * Range: [1, 32]
+ * Gets the satellite ID.
+ *
+ * <p>Interpretation depends on {@link #getConstellationType()}.
+ * See {@link GnssStatus#getSvid(int)}.
*/
public int getSvid() {
return mSvid;
}
/**
- * Sets the Pseud-random number (PRN).
+ * Sets the Satellite ID.
* @hide
*/
@TestApi
@@ -209,7 +214,10 @@
}
/**
- * Getst the constellation type.
+ * Gets the constellation type.
+ *
+ * <p>The return value is one of those constants with {@code CONSTELLATION_} prefix in
+ * {@link GnssStatus}.
*/
@GnssStatus.ConstellationType
public int getConstellationType() {
@@ -228,13 +236,14 @@
/**
* Gets the time offset at which the measurement was taken in nanoseconds.
*
- * The reference receiver's time from which this is offset is specified by
+ * <p>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
+ * <p>The sign of this value is given by the following equation:
+ * <pre>
+ * measurement time = TimeNanos + TimeOffsetNanos</pre>
*
- * The value provides an individual time-stamp for the measurement, and allows sub-nanosecond
+ * <p>The value provides an individual time-stamp for the measurement, and allows sub-nanosecond
* accuracy.
*/
public double getTimeOffsetNanos() {
@@ -252,9 +261,10 @@
/**
* Gets per-satellite sync state.
- * It represents the current sync state for the associated satellite.
*
- * This value helps interpret {@link #getReceivedSvTimeNanos()}.
+ * <p>It represents the current sync state for the associated satellite.
+ *
+ * <p>This value helps interpret {@link #getReceivedSvTimeNanos()}.
*/
public int getState() {
return mState;
@@ -271,7 +281,8 @@
/**
* Gets a string representation of the 'sync state'.
- * For internal and logging use only.
+ *
+ * <p>For internal and logging use only.
*/
private String getStateString() {
if (mState == STATE_UNKNOWN) {
@@ -335,66 +346,79 @@
/**
* Gets the received GNSS satellite time, at the measurement time, in nanoseconds.
*
- * 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.
+ * <p>For GPS & QZSS, this is:
+ * <ul>
+ * <li>Received GPS Time-of-Week at the measurement time, in nanoseconds.</li>
+ * <li>The value is relative to the beginning of the current GPS week.</li>
+ * </ul>
*
- * Given the highest sync state that can be achieved, per each satellite, valid range
- * for this field can be:
+ * <p>Given the highest sync state that can be achieved, per each satellite, valid range
+ * for this field can be:
+ * <pre>
* 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
+ * TOW decoded : [ 0 1week ] : STATE_TOW_DECODED is set</pre>
*
- * Note well: if there is any ambiguity in integer millisecond,
- * STATE_MSEC_AMBIGUOUS should be set accordingly, in the 'state' field.
+ * <p>Note well: if there is any ambiguity in integer millisecond, {@code STATE_MSEC_AMBIGUOUS}
+ * should be set accordingly, in the 'state' field.
*
- * This value must be populated if 'state' != STATE_UNKNOWN.
+ * <p>This value must be populated if 'state' != {@code STATE_UNKNOWN}.
*
- * For Glonass, this is:
- * Received Glonass time of day, at the measurement time in nanoseconds.
+ * <p>For Glonass, this is:
+ * <ul>
+ * <li>Received Glonass time of day, at the measurement time in nanoseconds.</li>
+ * </ul>
*
- * Given the highest sync state that can be achieved, per each satellite, valid range for
- * this field can be:
+ * <p>Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * <pre>
* 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
+ * 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</pre>
*
- * For Beidou, this is:
- * Received Beidou time of week, at the measurement time in nanoseconds.
+ * <p>For Beidou, this is:
+ * <ul>
+ * <li>Received Beidou time of week, at the measurement time in nanoseconds.</li>
+ * </ul>
*
- * Given the highest sync state that can be achieved, per each satellite, valid range for
- * this field can be:
+ * <p>Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * <pre>
* 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
+ * Time of week : [ 0 1week ] : STATE_TOW_DECODED is set</pre>
*
- * For Galileo, this is:
- * Received Galileo time of week, at the measurement time in nanoseconds.
+ * <p>For Galileo, this is:
+ * <ul>
+ * <li>Received Galileo time of week, at the measurement time in nanoseconds.</li>
+ * </ul>
+ * <pre>
+ * 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</pre>
*
- * 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
+ * <p>For SBAS, this is:
+ * <ul>
+ * <li>Received SBAS time, at the measurement time in nanoseconds.</li>
+ * </ul>
*
- * 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:
+ * <p>Given the highest sync state that can be achieved, per each satellite, valid range for
+ * this field can be:
+ * <pre>
* 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
+ * Message : [ 0 1s ] : STATE_SBAS_SYNC is set</pre>
*/
public long getReceivedSvTimeNanos() {
return mReceivedSvTimeNanos;
@@ -410,7 +434,7 @@
}
/**
- * Gets the received GNSS time uncertainty (1-Sigma) in nanoseconds.
+ * Gets the error estimate (1-sigma) for the received GNSS time, in nanoseconds.
*/
public long getReceivedSvTimeUncertaintyNanos() {
return mReceivedSvTimeUncertaintyNanos;
@@ -427,9 +451,10 @@
/**
* Gets the Carrier-to-noise density in dB-Hz.
- * Range: [0, 63].
*
- * The value contains the measured C/N0 for the signal at the antenna input.
+ * <p>Typical range: 10-50 db-Hz.
+ *
+ * <p>The value contains the measured C/N0 for the signal at the antenna input.
*/
public double getCn0DbHz() {
return mCn0DbHz;
@@ -447,16 +472,18 @@
/**
* Gets the Pseudorange rate at the timestamp in m/s.
*
- * The reported value includes {@link #getPseudorangeRateUncertaintyMetersPerSecond()}.
+ * <p>The error estimate for this value is
+ * {@link #getPseudorangeRateUncertaintyMetersPerSecond()}.
*
- * The value is uncorrected, hence corrections for receiver and satellite clock frequency errors
- * should not be included.
+ * <p>The value is uncorrected, i.e. corrections for receiver and satellite clock frequency
+ * errors are not included.
*
- * A positive 'uncorrected' value indicates that the SV is moving away from the receiver. The
+ * <p>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)
+ * <pre>
+ * pseudorange rate = -k * doppler shift (where k is a constant)</pre>
*/
public double getPseudorangeRateMetersPerSecond() {
return mPseudorangeRateMetersPerSecond;
@@ -473,7 +500,8 @@
/**
* Gets the pseudorange's rate uncertainty (1-Sigma) in m/s.
- * The uncertainty is represented as an absolute (single sided) value.
+ *
+ * <p>The uncertainty is represented as an absolute (single sided) value.
*/
public double getPseudorangeRateUncertaintyMetersPerSecond() {
return mPseudorangeRateUncertaintyMetersPerSecond;
@@ -490,7 +518,8 @@
/**
* Gets 'Accumulated Delta Range' state.
- * It indicates whether {@link #getAccumulatedDeltaRangeMeters()} is reset or there is a
+ *
+ * <p>It indicates whether {@link #getAccumulatedDeltaRangeMeters()} is reset or there is a
* cycle slip (indicating 'loss of lock').
*/
public int getAccumulatedDeltaRangeState() {
@@ -508,7 +537,8 @@
/**
* Gets a string representation of the 'Accumulated Delta Range state'.
- * For internal and logging use only.
+ *
+ * <p>For internal and logging use only.
*/
private String getAccumulatedDeltaRangeStateString() {
if (mAccumulatedDeltaRangeState == ADR_STATE_UNKNOWN) {
@@ -536,14 +566,17 @@
/**
* Gets the accumulated delta range since the last channel reset, in meters.
- * The reported value includes {@link #getAccumulatedDeltaRangeUncertaintyMeters()}.
*
- * The availability of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
+ * <p>The error estimate for this value is {@link #getAccumulatedDeltaRangeUncertaintyMeters()}.
*
- * A positive value indicates that the SV is moving away from the receiver.
+ * <p>The availability of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
+ *
+ * <p>A positive value indicates that the SV is moving away from the receiver.
* 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)
+ *
+ * <pre>
+ * accumulated delta range = -k * carrier phase (where k is a constant)</pre>
*/
public double getAccumulatedDeltaRangeMeters() {
return mAccumulatedDeltaRangeMeters;
@@ -560,9 +593,10 @@
/**
* Gets the accumulated delta range's uncertainty (1-Sigma) in meters.
- * The uncertainty is represented as an absolute (single sided) value.
*
- * The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
+ * <p>The uncertainty is represented as an absolute (single sided) value.
+ *
+ * <p>The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
*/
public double getAccumulatedDeltaRangeUncertaintyMeters() {
return mAccumulatedDeltaRangeUncertaintyMeters;
@@ -571,7 +605,7 @@
/**
* Sets the accumulated delta range's uncertainty (1-sigma) in meters.
*
- * The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
+ * <p>The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
*
* @hide
*/
@@ -581,17 +615,20 @@
}
/**
- * Returns true if {@link #getCarrierFrequencyHz()} is available, false otherwise.
+ * Returns {@code true} if {@link #getCarrierFrequencyHz()} is available, {@code false}
+ * otherwise.
*/
public boolean hasCarrierFrequencyHz() {
return isFlagSet(HAS_CARRIER_FREQUENCY);
}
/**
- * 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.
+ * Gets the carrier frequency at which codes and messages are modulated.
*
- * The value is only available if {@link #hasCarrierFrequencyHz()} is true.
+ * <p>For GPS, e.g., it can be L1 or L2. If the field is not set, it is the primary common use
+ * frequency, e.g. L1 for GPS.
+ *
+ * <p>The value is only available if {@link #hasCarrierFrequencyHz()} is {@code true}.
*/
public float getCarrierFrequencyHz() {
return mCarrierFrequencyHz;
@@ -618,7 +655,7 @@
}
/**
- * Returns true if {@link #getCarrierCycles()} is available, false otherwise.
+ * Returns {@code true} if {@link #getCarrierCycles()} is available, {@code false} otherwise.
*/
public boolean hasCarrierCycles() {
return isFlagSet(HAS_CARRIER_CYCLES);
@@ -626,9 +663,10 @@
/**
* The number of full carrier cycles between the satellite and the receiver.
- * The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}.
*
- * The value is only available if {@link #hasCarrierCycles()} is true.
+ * <p>The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}.
+ *
+ * <p>The value is only available if {@link #hasCarrierCycles()} is {@code true}.
*/
public long getCarrierCycles() {
return mCarrierCycles;
@@ -655,7 +693,7 @@
}
/**
- * Returns true if {@link #getCarrierPhase()} is available, false otherwise.
+ * Returns {@code true} if {@link #getCarrierPhase()} is available, {@code false} otherwise.
*/
public boolean hasCarrierPhase() {
return isFlagSet(HAS_CARRIER_PHASE);
@@ -663,13 +701,16 @@
/**
* Gets the RF phase detected by the receiver.
- * 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 #getCarrierFrequencyHz()}.
- * The reported carrier-phase includes {@link #getCarrierPhaseUncertainty()}.
+ * <p>Range: [0.0, 1.0].
*
- * The value is only available if {@link #hasCarrierPhase()} is true.
+ * <p>This is the fractional part of the complete carrier phase measurement.
+ *
+ * <p>The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}.
+ *
+ * <p>The error estimate for this value is {@link #getCarrierPhaseUncertainty()}.
+ *
+ * <p>The value is only available if {@link #hasCarrierPhase()} is {@code true}.
*/
public double getCarrierPhase() {
return mCarrierPhase;
@@ -696,7 +737,8 @@
}
/**
- * Returns true if {@link #getCarrierPhaseUncertainty()} is available, false otherwise.
+ * Returns {@code true} if {@link #getCarrierPhaseUncertainty()} is available, {@code false}
+ * otherwise.
*/
public boolean hasCarrierPhaseUncertainty() {
return isFlagSet(HAS_CARRIER_PHASE_UNCERTAINTY);
@@ -704,9 +746,10 @@
/**
* Gets the carrier-phase's uncertainty (1-Sigma).
- * The uncertainty is represented as an absolute (single sided) value.
*
- * The value is only available if {@link #hasCarrierPhaseUncertainty()} is true.
+ * <p>The uncertainty is represented as an absolute (single sided) value.
+ *
+ * <p>The value is only available if {@link #hasCarrierPhaseUncertainty()} is {@code true}.
*/
public double getCarrierPhaseUncertainty() {
return mCarrierPhaseUncertainty;
@@ -751,7 +794,8 @@
/**
* Gets a string representation of the 'multi-path indicator'.
- * For internal and logging use only.
+ *
+ * <p>For internal and logging use only.
*/
private String getMultipathIndicatorString() {
switch(mMultipathIndicator) {
@@ -767,7 +811,7 @@
}
/**
- * Returns true if {@link #getSnrInDb()} is available, false otherwise.
+ * Returns {@code true} if {@link #getSnrInDb()} is available, {@code false} otherwise.
*/
public boolean hasSnrInDb() {
return isFlagSet(HAS_SNR);
@@ -776,7 +820,7 @@
/**
* Gets the Signal-to-Noise ratio (SNR) in dB.
*
- * The value is only available if {@link #hasSnrInDb()} is true.
+ * <p>The value is only available if {@link #hasSnrInDb()} is {@code true}.
*/
public double getSnrInDb() {
return mSnrInDb;
diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java
index ec252a8..3151694 100644
--- a/location/java/android/location/GnssMeasurementsEvent.java
+++ b/location/java/android/location/GnssMeasurementsEvent.java
@@ -16,6 +16,7 @@
package android.location;
+import android.annotation.TestApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.os.Parcel;
@@ -33,29 +34,11 @@
* Events are delivered to registered instances of {@link Callback}.
*/
public final class GnssMeasurementsEvent implements Parcelable {
- /**
- * The status of the GNSS measurements event.
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GNSS_LOCATION_DISABLED})
- public @interface GnssMeasurementsStatus {}
-
- /**
- * The system does not support tracking of GNSS Measurements. This status will not change in the
- * future.
- */
+ /** @removed */
public static final int STATUS_NOT_SUPPORTED = 0;
-
- /**
- * GNSS Measurements are successfully being tracked, it will receive updates once they are
- * available.
- */
+ /** @removed */
public static final int STATUS_READY = 1;
-
- /**
- * GNSS provider or Location is disabled, updates will not be received until they are enabled.
- */
+ /** @removed */
public static final int STATUS_GNSS_LOCATION_DISABLED = 2;
private final GnssClock mClock;
@@ -68,6 +51,32 @@
* {@link LocationManager#registerGnssMeasurementsCallback}.
*/
public static abstract class Callback {
+ /**
+ * The status of the GNSS measurements event.
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_LOCATION_DISABLED})
+ public @interface GnssMeasurementsStatus {}
+
+ /**
+ * The system does not support tracking of GNSS Measurements.
+ *
+ * <p>This status will not change in the future.
+ */
+ public static final int STATUS_NOT_SUPPORTED = 0;
+
+ /**
+ * 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.
+ */
+ public static final int STATUS_LOCATION_DISABLED = 2;
/**
* Reports the latest collected GNSS Measurements.
@@ -80,6 +89,10 @@
public void onStatusChanged(@GnssMeasurementsStatus int status) {}
}
+ /**
+ * @hide
+ */
+ @TestApi
public GnssMeasurementsEvent(GnssClock clock, GnssMeasurement[] measurements) {
if (clock == null) {
throw new InvalidParameterException("Parameter 'clock' must not be null.");
@@ -94,6 +107,10 @@
mReadOnlyMeasurements = Collections.unmodifiableCollection(measurementCollection);
}
+ /**
+ * Gets the GNSS receiver clock information associated with the measurements for the current
+ * event.
+ */
@NonNull
public GnssClock getClock() {
return mClock;
diff --git a/location/java/android/location/GnssNavigationMessage.aidl b/location/java/android/location/GnssNavigationMessage.aidl
new file mode 100644
index 0000000..1cdd510
--- /dev/null
+++ b/location/java/android/location/GnssNavigationMessage.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.location;
+
+parcelable GnssNavigationMessage;
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index a5eace8..aa26111 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -34,7 +34,7 @@
private static final byte[] EMPTY_ARRAY = new byte[0];
/**
- * The type of the GPS Clock.
+ * The type of the GNSS Navigation Message
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@@ -81,6 +81,51 @@
*/
public static final int STATUS_PARITY_REBUILT = (1<<1);
+ /**
+ * Used for receiving GNSS satellite Navigation Messages from the GNSS engine.
+ *
+ * <p>You can implement this interface and call
+ * {@link LocationManager#registerGnssNavigationMessageCallback}.
+ */
+ public static abstract class Callback {
+ /**
+ * The status of GNSS measurements event.
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_LOCATION_DISABLED})
+ public @interface GnssNavigationMessageStatus {}
+
+ /**
+ * The system does not support tracking of GNSS Navigation Messages.
+ *
+ * This status will not change in the future.
+ */
+ public static final int STATUS_NOT_SUPPORTED = 0;
+
+ /**
+ * GNSS Navigation Messages are successfully being tracked, it will receive updates once
+ * they are available.
+ */
+ public static final int STATUS_READY = 1;
+
+ /**
+ * GNSS provider or Location is disabled, updated will not be received until they are
+ * enabled.
+ */
+ public static final int STATUS_LOCATION_DISABLED = 2;
+
+ /**
+ * Returns the latest collected GNSS Navigation Message.
+ */
+ public void onGnssNavigationMessageReceived(GnssNavigationMessage event) {}
+
+ /**
+ * Returns the latest status of the GNSS Navigation Messages sub-system.
+ */
+ public void onStatusChanged(@GnssNavigationMessageStatus int status) {}
+ }
+
// End enumerations in sync with gps.h
private int mType;
@@ -170,15 +215,16 @@
}
/**
- * Gets the Pseudo-random number.
- * Range: [1, 32].
+ * Gets the satellite ID.
+ *
+ * <p>Range varies by constellation. See definition at {@code GnssStatus#getSvid(int)}
*/
public int getSvid() {
return mSvid;
}
/**
- * Sets the Pseud-random number.
+ * Sets the satellite ID.
* @hide
*/
@TestApi
@@ -187,10 +233,25 @@
}
/**
- * Gets the Message Identifier.
- * It provides an index so the complete Navigation Message can be assembled. i.e. for L1 C/A
- * 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.
+ * Gets the Message identifier.
+ *
+ * <p>This provides an index to help with complete Navigation Message assembly. Similar
+ * identifiers within the data bits themselves often supplement this information, in ways even
+ * more specific to each message type; see the relevant satellite constellation ICDs for
+ * details.
+ *
+ * <ul>
+ * <li> For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame id' of the
+ * navigation message, in the range of 1-25 (Subframe 1, 2, 3 does not contain a 'frame id' and
+ * this value can be set to -1.)</li>
+ * <li> For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.</li>
+ * <li> For BeiDou D1, this refers to the frame number in the range of 1-24</li>
+ * <li> For Beidou D2, this refers to the frame number, in the range of 1-120</li>
+ * <li> For Galileo F/NAV nominal frame structure, this refers to the subframe number, in the
+ * range of 1-12</li>
+ * <li> For Galileo I/NAV nominal frame structure, this refers to the subframe number in the
+ * range of 1-24</li>
+ * </ul>
*/
public int getMessageId() {
return mMessageId;
@@ -206,10 +267,18 @@
}
/**
- * Gets the Sub-message Identifier.
- * If required by {@link #getType()}, this value contains a sub-index within the current message
- * (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.
+ * Gets the sub-message identifier, relevant to the {@link #getType()} of the message.
+ *
+ * <ul>
+ * <li> For GPS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to the subframe
+ * number of the navigation message, in the range of 1-5.</li>
+ * <li>For Glonass L1 C/A, this refers to the String number, in the range from 1-15</li>
+ * <li>For Galileo F/NAV, this refers to the page type in the range 1-6</li>
+ * <li>For Galileo I/NAV, this refers to the word type in the range 1-10+</li>
+ * <li>For Galileo in particular, the type information embedded within the data bits may be even
+ * more useful in interpretation, than the nominal page and word types provided in this
+ * field.</li>
+ * </ul>
*/
public int getSubmessageId() {
return mSubmessageId;
@@ -225,8 +294,25 @@
}
/**
- * Gets the data associated with the Navigation Message.
- * The bytes (or words) specified using big endian format (MSB first).
+ * Gets the data of the reported GPS message.
+ *
+ * <p>The bytes (or words) specified using big endian format (MSB first).
+ *
+ * <ul>
+ * <li>For GPS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit words. Each
+ * word (30 bits) should be fit into the last 30 bits in a 4-byte word (skip B31 and B32), with
+ * MSB first, for a total of 40 bytes, covering a time period of 6, 6, and 0.6 seconds,
+ * respectively.</li>
+ * <li>For Glonass L1 C/A, each string contains 85 data bits, including the checksum. These
+ * bits should be fit into 11 bytes, with MSB first (skip B86-B88), covering a time period of 2
+ * seconds.</li>
+ * <li>For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols excluded). Each
+ * word should be fit into 30-bytes, with MSB first (skip B239, B240), covering a time period of
+ * 10 seconds.</li>
+ * <li>For Galileo I/NAV, each page contains 2 page parts, even and odd, with a total of 2x114 =
+ * 228 bits, (sync & tail excluded) that should be fit into 29 bytes, with MSB first (skip
+ * B229-B232).</li>
+ * </ul>
*/
@NonNull
public byte[] getData() {
diff --git a/location/java/android/location/GnssNavigationMessageCallbackTransport.java b/location/java/android/location/GnssNavigationMessageCallbackTransport.java
index 4204b99..1eafd02 100644
--- a/location/java/android/location/GnssNavigationMessageCallbackTransport.java
+++ b/location/java/android/location/GnssNavigationMessageCallbackTransport.java
@@ -20,12 +20,12 @@
import android.os.RemoteException;
/**
- * A handler class to manage transport callback for {@link GnssNavigationMessageEvent.Callback}.
+ * A handler class to manage transport callback for {@link GnssNavigationMessage.Callback}.
*
* @hide
*/
class GnssNavigationMessageCallbackTransport
- extends LocalListenerHelper<GnssNavigationMessageEvent.Callback> {
+ extends LocalListenerHelper<GnssNavigationMessage.Callback> {
private final ILocationManager mLocationManager;
private final IGnssNavigationMessageListener mListenerTransport = new ListenerTransport();
@@ -51,11 +51,11 @@
private class ListenerTransport extends IGnssNavigationMessageListener.Stub {
@Override
- public void onGnssNavigationMessageReceived(final GnssNavigationMessageEvent event) {
- ListenerOperation<GnssNavigationMessageEvent.Callback> operation =
- new ListenerOperation<GnssNavigationMessageEvent.Callback>() {
+ public void onGnssNavigationMessageReceived(final GnssNavigationMessage event) {
+ ListenerOperation<GnssNavigationMessage.Callback> operation =
+ new ListenerOperation<GnssNavigationMessage.Callback>() {
@Override
- public void execute(GnssNavigationMessageEvent.Callback callback)
+ public void execute(GnssNavigationMessage.Callback callback)
throws RemoteException {
callback.onGnssNavigationMessageReceived(event);
}
@@ -65,10 +65,10 @@
@Override
public void onStatusChanged(final int status) {
- ListenerOperation<GnssNavigationMessageEvent.Callback> operation =
- new ListenerOperation<GnssNavigationMessageEvent.Callback>() {
+ ListenerOperation<GnssNavigationMessage.Callback> operation =
+ new ListenerOperation<GnssNavigationMessage.Callback>() {
@Override
- public void execute(GnssNavigationMessageEvent.Callback callback)
+ public void execute(GnssNavigationMessage.Callback callback)
throws RemoteException {
callback.onStatusChanged(status);
}
diff --git a/location/java/android/location/GnssNavigationMessageEvent.java b/location/java/android/location/GnssNavigationMessageEvent.java
index 992dfc3..f7e5665 100644
--- a/location/java/android/location/GnssNavigationMessageEvent.java
+++ b/location/java/android/location/GnssNavigationMessageEvent.java
@@ -28,10 +28,11 @@
/**
* A class implementing a container for data associated with a navigation message event.
* Events are delivered to registered instances of {@link Callback}.
+ * @removed
*/
public final class GnssNavigationMessageEvent implements Parcelable {
/**
- * The status of GPS measurements event.
+ * The status of GNSS measurements event.
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@@ -39,38 +40,40 @@
public @interface GnssNavigationMessageStatus {}
/**
- * The system does not support tracking of GPS Navigation Messages. This status will not change
- * in the future.
+ * The system does not support tracking of GNSS Navigation Messages.
+ *
+ * This status will not change in the future.
*/
public static final int STATUS_NOT_SUPPORTED = 0;
/**
- * GPS Navigation Messages are successfully being tracked, it will receive updates once they are
- * available.
+ * GNSS Navigation Messages 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, updated will not be received until they are enabled.
+ * GNSS provider or Location is disabled, updated will not be received until they are enabled.
*/
public static final int STATUS_GNSS_LOCATION_DISABLED = 2;
private final GnssNavigationMessage mNavigationMessage;
/**
- * Used for receiving GPS satellite Navigation Messages from the GPS engine.
- * You can implement this interface and call
+ * Used for receiving GNSS satellite Navigation Messages from the GNSS engine.
+ *
+ * <p>You can implement this interface and call
* {@link LocationManager#registerGnssNavigationMessageCallback}.
*/
public static abstract class Callback {
/**
- * Returns the latest collected GPS Navigation Message.
+ * Returns the latest collected GNSS Navigation Message.
*/
public void onGnssNavigationMessageReceived(GnssNavigationMessageEvent event) {}
/**
- * Returns the latest status of the GPS Navigation Messages sub-system.
+ * Returns the latest status of the GNSS Navigation Messages sub-system.
*/
public void onStatusChanged(@GnssNavigationMessageStatus int status) {}
}
diff --git a/location/java/android/location/GnssNmeaListener.java b/location/java/android/location/GnssNmeaListener.java
index 6c9b08a..756ae49 100644
--- a/location/java/android/location/GnssNmeaListener.java
+++ b/location/java/android/location/GnssNmeaListener.java
@@ -23,8 +23,9 @@
* See <a href="http://en.wikipedia.org/wiki/NMEA_0183">NMEA 0183</a> for more details.
* You can implement this interface and call {@link LocationManager#addNmeaListener}
* to receive NMEA data from the GNSS engine.
+* @removed
*/
public interface GnssNmeaListener {
/** Called when an NMEA message is received. */
void onNmeaReceived(long timestamp, String nmea);
-}
\ No newline at end of file
+}
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index d76feec..e834c30 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -23,9 +23,11 @@
/**
* This class represents the current state of the GNSS engine.
- * This class is used in conjunction with the {@link GnssStatusCallback}.
+ * This class is used in conjunction with the {@link GnssStatus.Callback}.
*/
public final class GnssStatus {
+ // these must match the definitions in gps.h
+
/** Unknown constellation type. */
public static final int CONSTELLATION_UNKNOWN = 0;
/** Constellation type constant for GPS. */
@@ -41,16 +43,6 @@
/** Constellation type constant for Galileo. */
public static final int CONSTELLATION_GALILEO = 6;
- /**
- * Constellation type.
- * @hide
- */
- @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;
/** @hide */
@@ -67,6 +59,42 @@
/** @hide */
public static final int CONSTELLATION_TYPE_MASK = 0xf;
+ /**
+ * Used for receiving notifications when GNSS events happen.
+ */
+ public static abstract class Callback {
+ /**
+ * Called when GNSS system has started.
+ */
+ public void onStarted() {}
+
+ /**
+ * Called when GNSS system has stopped.
+ */
+ public void onStopped() {}
+
+ /**
+ * Called when the GNSS system has received its first fix since starting.
+ * @param ttffMillis the time from start to first fix in milliseconds.
+ */
+ 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) {}
+ }
+
+ /**
+ * Constellation type.
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({CONSTELLATION_UNKNOWN, CONSTELLATION_GPS, CONSTELLATION_SBAS, CONSTELLATION_GLONASS,
+ CONSTELLATION_QZSS, CONSTELLATION_BEIDOU, CONSTELLATION_GALILEO})
+ public @interface ConstellationType {}
+
/* These package private values are modified by the LocationManager class */
/* package */ int[] mSvidWithFlags;
/* package */ float[] mCn0DbHz;
@@ -83,15 +111,21 @@
mAzimuths = azimuths;
}
+ /** @removed */
+ public int getNumSatellites() {
+ return getSatelliteCount();
+ }
+
/**
* Gets the total number of satellites in satellite list.
*/
- public int getNumSatellites() {
+ public int getSatelliteCount() {
return mSvCount;
}
/**
- * Retrieves the constellation type of the satellite at the specified position.
+ * Retrieves the constellation type of the satellite at the specified index.
+ *
* @param satIndex the index of the satellite in the list.
*/
@ConstellationType
@@ -101,7 +135,30 @@
}
/**
- * Retrieves the pseudo-random number of the satellite at the specified position.
+ * Gets the identification number for the satellite at the specific index.
+ *
+ * <p>This svid is pseudo-random number for most constellations. It is FCN & OSN number for
+ * Glonass.
+ *
+ * <p>The distinction is made by looking at constellation field
+ * {@link #getConstellationType(int)} Expected values are in the range of:
+ *
+ * <ul>
+ * <li>GPS: 1-32</li>
+ * <li>SBAS: 120-151, 183-192</li>
+ * <li>GLONASS:
+ * <ul>
+ * <li>The least significant 8 bits, signed, are the orbital slot number (OSN) in the range
+ * from 1-24, if known, or -127 if unknown</li>
+ * <li>The next least signficant 8 bits, signed, are the frequency channel number (FCN) in the
+ * range from -7 to +6, if known, and -127, if unknown</li>
+ * <li>At least one of the two (FCN & OSN) shall be set to a known value</li>
+ * </ul></li>
+ * <li>QZSS: 193-200</li>
+ * <li>Galileo: 1-36</li>
+ * <li>Beidou: 1-37</li>
+ * </ul>
+ *
* @param satIndex the index of the satellite in the list.
*/
public int getSvid(int satIndex) {
@@ -109,7 +166,9 @@
}
/**
- * Retrieves the signal-noise ration of the satellite at the specified position.
+ * Retrieves the carrier-to-noise density at the antenna of the satellite at the specified index
+ * in dB-Hz.
+ *
* @param satIndex the index of the satellite in the list.
*/
public float getCn0DbHz(int satIndex) {
@@ -117,7 +176,8 @@
}
/**
- * Retrieves the elevation of the satellite at the specified position.
+ * Retrieves the elevation of the satellite at the specified index.
+ *
* @param satIndex the index of the satellite in the list.
*/
public float getElevationDegrees(int satIndex) {
@@ -125,31 +185,46 @@
}
/**
- * Retrieves the azimuth the satellite at the specified position.
+ * Retrieves the azimuth the satellite at the specified index.
+ *
* @param satIndex the index of the satellite in the list.
*/
public float getAzimuthDegrees(int satIndex) {
return mAzimuths[satIndex];
}
- /**
- * Detects whether the satellite at the specified position has ephemeris data.
- * @param satIndex the index of the satellite in the list.
- */
+ /** @removed */
public boolean hasEphemeris(int satIndex) {
- return (mSvidWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0;
+ return hasEphemerisData(satIndex);
}
/**
- * Detects whether the satellite at the specified position has almanac data.
+ * Reports whether the satellite at the specified index has ephemeris data.
+ *
* @param satIndex the index of the satellite in the list.
*/
+ public boolean hasEphemerisData(int satIndex) {
+ return (mSvidWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0;
+ }
+
+ /** @removed */
public boolean hasAlmanac(int satIndex) {
+ return hasAlmanacData(satIndex);
+ }
+
+ /**
+ * Reports whether the satellite at the specified index has almanac data.
+ *
+ * @param satIndex the index of the satellite in the list.
+ */
+ public boolean hasAlmanacData(int satIndex) {
return (mSvidWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_ALMANAC_DATA) != 0;
}
/**
- * Detects whether the satellite at the specified position is used in fix.
+ * Reports whether the satellite at the specified index was used in the calculation of the most
+ * recent position fix.
+ *
* @param satIndex the index of the satellite in the list.
*/
public boolean usedInFix(int satIndex) {
diff --git a/location/java/android/location/GnssStatusCallback.java b/location/java/android/location/GnssStatusCallback.java
index 0d2955a..bf295ef 100644
--- a/location/java/android/location/GnssStatusCallback.java
+++ b/location/java/android/location/GnssStatusCallback.java
@@ -18,6 +18,7 @@
/**
* Used for receiving notifications when GNSS events happen.
+ * @removed
*/
public abstract class GnssStatusCallback {
/**
diff --git a/location/java/android/location/GpsSatellite.java b/location/java/android/location/GpsSatellite.java
index 820f5746..788d01e 100644
--- a/location/java/android/location/GpsSatellite.java
+++ b/location/java/android/location/GpsSatellite.java
@@ -18,8 +18,12 @@
/**
* This class represents the current state of a GPS satellite.
+ *
* This class is used in conjunction with the {@link GpsStatus} class.
+ *
+ * @deprecated use {@link GnssStatus} and {@link GnssStatus.Callback}.
*/
+@Deprecated
public final class GpsSatellite {
/* These package private values are modified by the GpsStatus class */
boolean mValid;
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index bc518f9..038247b 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -24,8 +24,12 @@
/**
* This class represents the current state of the GPS engine.
- * This class is used in conjunction with the {@link Listener} interface.
+ *
+ * <p>This class is used in conjunction with the {@link Listener} interface.
+ *
+ * @deprecated use {@link GnssStatus} and {@link GnssStatus.Callback}.
*/
+@Deprecated
public final class GpsStatus {
private static final int NUM_SATELLITES = 255;
@@ -102,7 +106,9 @@
/**
* Used for receiving notifications when GPS status has changed.
+ * @deprecated use {@link GnssStatus.Callback} instead.
*/
+ @Deprecated
public interface Listener {
/**
* Called to report changes in the GPS status.
@@ -130,7 +136,9 @@
* See <a href="http://en.wikipedia.org/wiki/NMEA_0183">NMEA 0183</a> for more details.
* You can implement this interface and call {@link LocationManager#addNmeaListener}
* to receive NMEA data from the GPS engine.
+ * @deprecated use {@link OnNmeaMessageListener} instead.
*/
+ @Deprecated
public interface NmeaListener {
void onNmeaReceived(long timestamp, String nmea);
}
diff --git a/location/java/android/location/IGnssNavigationMessageListener.aidl b/location/java/android/location/IGnssNavigationMessageListener.aidl
index de6129c..3e49b5b 100644
--- a/location/java/android/location/IGnssNavigationMessageListener.aidl
+++ b/location/java/android/location/IGnssNavigationMessageListener.aidl
@@ -16,12 +16,12 @@
package android.location;
-import android.location.GnssNavigationMessageEvent;
+import android.location.GnssNavigationMessage;
/**
* {@hide}
*/
oneway interface IGnssNavigationMessageListener {
- void onGnssNavigationMessageReceived(in GnssNavigationMessageEvent event);
+ void onGnssNavigationMessageReceived(in GnssNavigationMessage event);
void onStatusChanged(in int status);
}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 28db099..b246360 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -70,10 +70,16 @@
new HashMap<>();
private final HashMap<GpsStatus.NmeaListener, GnssStatusListenerTransport> mGpsNmeaListeners =
new HashMap<>();
- private final HashMap<GnssStatusCallback, GnssStatusListenerTransport> mGnssStatusListeners =
+ private final HashMap<GnssStatusCallback, GnssStatusListenerTransport>
+ mOldGnssStatusListeners = new HashMap<>();
+ private final HashMap<GnssStatus.Callback, GnssStatusListenerTransport> mGnssStatusListeners =
new HashMap<>();
- private final HashMap<GnssNmeaListener, GnssStatusListenerTransport> mGnssNmeaListeners =
+ private final HashMap<GnssNmeaListener, GnssStatusListenerTransport> mOldGnssNmeaListeners =
new HashMap<>();
+ private final HashMap<OnNmeaMessageListener, GnssStatusListenerTransport> mGnssNmeaListeners =
+ new HashMap<>();
+ private final HashMap<GnssNavigationMessageEvent.Callback, GnssNavigationMessage.Callback>
+ mNavigationMessageBridge = new HashMap<>();
private GnssStatus mGnssStatus;
private int mTimeToFirstFix;
@@ -1392,8 +1398,10 @@
private final GpsStatus.Listener mGpsListener;
private final GpsStatus.NmeaListener mGpsNmeaListener;
- private final GnssStatusCallback mGnssCallback;
- private final GnssNmeaListener mGnssNmeaListener;
+ private final GnssStatusCallback mOldGnssCallback;
+ private final GnssStatus.Callback mGnssCallback;
+ private final GnssNmeaListener mOldGnssNmeaListener;
+ private final OnNmeaMessageListener mGnssNmeaListener;
private class GnssHandler extends Handler {
public GnssHandler(Handler handler) {
@@ -1408,7 +1416,7 @@
int length = mNmeaBuffer.size();
for (int i = 0; i < length; i++) {
Nmea nmea = mNmeaBuffer.get(i);
- mGnssNmeaListener.onNmeaReceived(nmea.mTimestamp, nmea.mNmea);
+ mGnssNmeaListener.onNmeaMessage(nmea.mNmea, nmea.mTimestamp);
}
mNmeaBuffer.clear();
}
@@ -1456,7 +1464,8 @@
mGnssHandler = new GnssHandler(handler);
mGpsNmeaListener = null;
mNmeaBuffer = null;
- mGnssCallback = new GnssStatusCallback() {
+ mOldGnssCallback = null;
+ mGnssCallback = new GnssStatus.Callback() {
@Override
public void onStarted() {
mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_STARTED);
@@ -1477,6 +1486,7 @@
mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_SATELLITE_STATUS);
}
};
+ mOldGnssNmeaListener = null;
mGnssNmeaListener = null;
}
@@ -1489,10 +1499,12 @@
mGnssHandler = new GnssHandler(handler);
mGpsNmeaListener = listener;
mNmeaBuffer = new ArrayList<Nmea>();
+ mOldGnssCallback = null;
mGnssCallback = null;
- mGnssNmeaListener = new GnssNmeaListener() {
+ mOldGnssNmeaListener = null;
+ mGnssNmeaListener = new OnNmeaMessageListener() {
@Override
- public void onNmeaReceived(long timestamp, String nmea) {
+ public void onNmeaMessage(String nmea, long timestamp) {
mGpsNmeaListener.onNmeaReceived(timestamp, nmea);
}
};
@@ -1503,8 +1515,45 @@
}
GnssStatusListenerTransport(GnssStatusCallback callback, Handler handler) {
+ mOldGnssCallback = callback;
+ mGnssCallback = new GnssStatus.Callback() {
+ @Override
+ public void onStarted() {
+ mOldGnssCallback.onStarted();
+ }
+
+ @Override
+ public void onStopped() {
+ mOldGnssCallback.onStopped();
+ }
+
+ @Override
+ public void onFirstFix(int ttff) {
+ mOldGnssCallback.onFirstFix(ttff);
+ }
+
+ @Override
+ public void onSatelliteStatusChanged(GnssStatus status) {
+ mOldGnssCallback.onSatelliteStatusChanged(status);
+ }
+ };
+ mGnssHandler = new GnssHandler(handler);
+ mOldGnssNmeaListener = null;
+ mGnssNmeaListener = null;
+ mNmeaBuffer = null;
+ mGpsListener = null;
+ mGpsNmeaListener = null;
+ }
+
+ GnssStatusListenerTransport(GnssStatus.Callback callback) {
+ this(callback, null);
+ }
+
+ GnssStatusListenerTransport(GnssStatus.Callback callback, Handler handler) {
+ mOldGnssCallback = null;
mGnssCallback = callback;
mGnssHandler = new GnssHandler(handler);
+ mOldGnssNmeaListener = null;
mGnssNmeaListener = null;
mNmeaBuffer = null;
mGpsListener = null;
@@ -1517,7 +1566,29 @@
GnssStatusListenerTransport(GnssNmeaListener listener, Handler handler) {
mGnssCallback = null;
+ mOldGnssCallback = null;
mGnssHandler = new GnssHandler(handler);
+ mOldGnssNmeaListener = listener;
+ mGnssNmeaListener = new OnNmeaMessageListener() {
+ @Override
+ public void onNmeaMessage(String message, long timestamp) {
+ mOldGnssNmeaListener.onNmeaReceived(timestamp, message);
+ }
+ };
+ mGpsListener = null;
+ mGpsNmeaListener = null;
+ mNmeaBuffer = new ArrayList<Nmea>();
+ }
+
+ GnssStatusListenerTransport(OnNmeaMessageListener listener) {
+ this(listener, null);
+ }
+
+ GnssStatusListenerTransport(OnNmeaMessageListener listener, Handler handler) {
+ mOldGnssCallback = null;
+ mGnssCallback = null;
+ mGnssHandler = new GnssHandler(handler);
+ mOldGnssNmeaListener = null;
mGnssNmeaListener = listener;
mGpsListener = null;
mGpsNmeaListener = null;
@@ -1589,7 +1660,7 @@
* @return true if the listener was successfully added
*
* @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
- * @deprecated use {@link #registerGnssStatusCallback(GnssStatusCallback)} instead.
+ * @deprecated use {@link #registerGnssStatusCallback(GnssStatus.Callback)} instead.
*/
@Deprecated
@RequiresPermission(ACCESS_FINE_LOCATION)
@@ -1617,6 +1688,7 @@
* Removes a GPS status listener.
*
* @param listener GPS status listener object to remove
+ * @deprecated use {@link #unregisterGnssStatusCallback(GnssStatus.Callback)} instead.
*/
@Deprecated
public void removeGpsStatusListener(GpsStatus.Listener listener) {
@@ -1630,7 +1702,6 @@
}
}
-
/**
* Registers a GNSS status listener.
*
@@ -1639,6 +1710,7 @@
* @return true if the listener was successfully added
*
* @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+ * @removed
*/
@RequiresPermission(ACCESS_FINE_LOCATION)
public boolean registerGnssStatusCallback(GnssStatusCallback callback) {
@@ -1654,10 +1726,73 @@
* @return true if the listener was successfully added
*
* @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+ * @removed
*/
@RequiresPermission(ACCESS_FINE_LOCATION)
public boolean registerGnssStatusCallback(GnssStatusCallback callback, Handler handler) {
boolean result;
+ if (mOldGnssStatusListeners.get(callback) != null) {
+ // listener is already registered
+ return true;
+ }
+ try {
+ GnssStatusListenerTransport transport =
+ new GnssStatusListenerTransport(callback, handler);
+ result = mService.registerGnssStatusCallback(transport, mContext.getPackageName());
+ if (result) {
+ mOldGnssStatusListeners.put(callback, transport);
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+
+ return result;
+ }
+
+ /**
+ * Removes a GNSS status listener.
+ *
+ * @param callback GNSS status listener object to remove
+ * @removed
+ */
+ public void unregisterGnssStatusCallback(GnssStatusCallback callback) {
+ try {
+ GnssStatusListenerTransport transport = mOldGnssStatusListeners.remove(callback);
+ if (transport != null) {
+ mService.unregisterGnssStatusCallback(transport);
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Registers a GNSS status listener.
+ *
+ * @param callback GNSS status listener object to register
+ *
+ * @return true if the listener was successfully added
+ *
+ * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+ */
+ @RequiresPermission(ACCESS_FINE_LOCATION)
+ public boolean registerGnssStatusCallback(GnssStatus.Callback callback) {
+ return registerGnssStatusCallback(callback, null);
+ }
+
+ /**
+ * Registers a GNSS status listener.
+ *
+ * @param callback GNSS status listener object to register
+ * @param handler the handler that the callback runs on.
+ *
+ * @return true if the listener was successfully added
+ *
+ * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+ */
+ @RequiresPermission(ACCESS_FINE_LOCATION)
+ public boolean registerGnssStatusCallback(GnssStatus.Callback callback, Handler handler) {
+ boolean result;
if (mGnssStatusListeners.get(callback) != null) {
// listener is already registered
return true;
@@ -1681,7 +1816,7 @@
*
* @param callback GNSS status listener object to remove
*/
- public void unregisterGnssStatusCallback(GnssStatusCallback callback) {
+ public void unregisterGnssStatusCallback(GnssStatus.Callback callback) {
try {
GnssStatusListenerTransport transport = mGnssStatusListeners.remove(callback);
if (transport != null) {
@@ -1700,7 +1835,7 @@
* @return true if the listener was successfully added
*
* @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
- * @deprecated use {@link #addNmeaListener(GnssNmeaListener)} instead.
+ * @deprecated use {@link #addNmeaListener(OnNmeaMessageListener)} instead.
*/
@Deprecated
@RequiresPermission(ACCESS_FINE_LOCATION)
@@ -1728,6 +1863,7 @@
* Removes an NMEA listener.
*
* @param listener a {@link GpsStatus.NmeaListener} object to remove
+ * @deprecated use {@link #removeNmeaListener(OnNmeaMessageListener)} instead.
*/
@Deprecated
public void removeNmeaListener(GpsStatus.NmeaListener listener) {
@@ -1749,6 +1885,7 @@
* @return true if the listener was successfully added
*
* @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+ * @removed
*/
@RequiresPermission(ACCESS_FINE_LOCATION)
public boolean addNmeaListener(GnssNmeaListener listener) {
@@ -1764,6 +1901,7 @@
* @return true if the listener was successfully added
*
* @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+ * @removed
*/
@RequiresPermission(ACCESS_FINE_LOCATION)
public boolean addNmeaListener(GnssNmeaListener listener, Handler handler) {
@@ -1778,6 +1916,69 @@
new GnssStatusListenerTransport(listener, handler);
result = mService.registerGnssStatusCallback(transport, mContext.getPackageName());
if (result) {
+ mOldGnssNmeaListeners.put(listener, transport);
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+
+ return result;
+ }
+
+ /**
+ * Removes an NMEA listener.
+ *
+ * @param listener a {@link GnssNmeaListener} object to remove
+ * @removed
+ */
+ public void removeNmeaListener(GnssNmeaListener listener) {
+ try {
+ GnssStatusListenerTransport transport = mOldGnssNmeaListeners.remove(listener);
+ if (transport != null) {
+ mService.unregisterGnssStatusCallback(transport);
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Adds an NMEA listener.
+ *
+ * @param listener a {@link OnNmeaMessageListener} object to register
+ *
+ * @return true if the listener was successfully added
+ *
+ * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+ */
+ @RequiresPermission(ACCESS_FINE_LOCATION)
+ public boolean addNmeaListener(OnNmeaMessageListener listener) {
+ return addNmeaListener(listener, null);
+ }
+
+ /**
+ * Adds an NMEA listener.
+ *
+ * @param listener a {@link OnNmeaMessageListener} object to register
+ * @param handler the handler that the listener runs on.
+ *
+ * @return true if the listener was successfully added
+ *
+ * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+ */
+ @RequiresPermission(ACCESS_FINE_LOCATION)
+ public boolean addNmeaListener(OnNmeaMessageListener listener, Handler handler) {
+ boolean result;
+
+ if (mGpsNmeaListeners.get(listener) != null) {
+ // listener is already registered
+ return true;
+ }
+ try {
+ GnssStatusListenerTransport transport =
+ new GnssStatusListenerTransport(listener, handler);
+ result = mService.registerGnssStatusCallback(transport, mContext.getPackageName());
+ if (result) {
mGnssNmeaListeners.put(listener, transport);
}
} catch (RemoteException e) {
@@ -1790,9 +1991,9 @@
/**
* Removes an NMEA listener.
*
- * @param listener a {@link GnssNmeaListener} object to remove
+ * @param listener a {@link OnNmeaMessageListener} object to remove
*/
- public void removeNmeaListener(GnssNmeaListener listener) {
+ public void removeNmeaListener(OnNmeaMessageListener listener) {
try {
GnssStatusListenerTransport transport = mGnssNmeaListeners.remove(listener);
if (transport != null) {
@@ -1843,7 +2044,8 @@
* No-op method to keep backward-compatibility.
* Don't use it. Use {@link #unregisterGnssMeasurementsCallback} instead.
* @hide
- * @deprecated
+ * @deprecated use {@link #unregisterGnssMeasurementsCallback(GnssMeasurementsEvent.Callback)}
+ * instead.
*/
@Deprecated
@SystemApi
@@ -1872,10 +2074,23 @@
}
/**
- * Registers a GPS Navigation Message callback.
+ * No-op method to keep backward-compatibility.
+ * Don't use it. Use {@link #unregisterGnssNavigationMessageCallback} instead.
+ * @hide
+ * @deprecated use {@link #unregisterGnssNavigationMessageCallback(GnssMeasurements.Callback)}
+ * instead
+ */
+ @Deprecated
+ @SystemApi
+ public void removeGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {
+ }
+
+ /**
+ * Registers a GNSS Navigation Message callback.
*
* @param callback a {@link GnssNavigationMessageEvent.Callback} object to register.
* @return {@code true} if the callback was added successfully, {@code false} otherwise.
+ * @removed
*/
public boolean registerGnssNavigationMessageCallback(
GnssNavigationMessageEvent.Callback callback) {
@@ -1883,40 +2098,80 @@
}
/**
- * Registers a GPS Navigation Message callback.
+ * Registers a GNSS Navigation Message callback.
*
* @param callback a {@link GnssNavigationMessageEvent.Callback} object to register.
* @param handler the handler that the callback runs on.
* @return {@code true} if the callback was added successfully, {@code false} otherwise.
+ * @removed
+ */
+ @RequiresPermission(ACCESS_FINE_LOCATION)
+ public boolean registerGnssNavigationMessageCallback(
+ final GnssNavigationMessageEvent.Callback callback, Handler handler) {
+ GnssNavigationMessage.Callback bridge = new GnssNavigationMessage.Callback() {
+ @Override
+ public void onGnssNavigationMessageReceived(GnssNavigationMessage message) {
+ GnssNavigationMessageEvent event = new GnssNavigationMessageEvent(message);
+ callback.onGnssNavigationMessageReceived(event);
+ }
+
+ @Override
+ public void onStatusChanged(int status) {
+ callback.onStatusChanged(status);
+ }
+ };
+ mNavigationMessageBridge.put(callback, bridge);
+ return mGnssNavigationMessageCallbackTransport.add(bridge, handler);
+ }
+
+ /**
+ * Unregisters a GNSS Navigation Message callback.
+ *
+ * @param callback a {@link GnssNavigationMessageEvent.Callback} object to remove.
+ * @removed
+ */
+ public void unregisterGnssNavigationMessageCallback(
+ GnssNavigationMessageEvent.Callback callback) {
+ mGnssNavigationMessageCallbackTransport.remove(
+ mNavigationMessageBridge.remove(
+ callback));
+ }
+
+ /**
+ * Registers a GNSS Navigation Message callback.
+ *
+ * @param callback a {@link GnssNavigationMessage.Callback} object to register.
+ * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+ */
+ public boolean registerGnssNavigationMessageCallback(
+ GnssNavigationMessage.Callback callback) {
+ return registerGnssNavigationMessageCallback(callback, null);
+ }
+
+ /**
+ * Registers a GNSS Navigation Message callback.
+ *
+ * @param callback a {@link GnssNavigationMessage.Callback} object to register.
+ * @param handler the handler that the callback runs on.
+ * @return {@code true} if the callback was added successfully, {@code false} otherwise.
*/
@RequiresPermission(ACCESS_FINE_LOCATION)
public boolean registerGnssNavigationMessageCallback(
- GnssNavigationMessageEvent.Callback callback, Handler handler) {
+ GnssNavigationMessage.Callback callback, Handler handler) {
return mGnssNavigationMessageCallbackTransport.add(callback, handler);
}
/**
- * Unregisters a GPS Navigation Message callback.
+ * Unregisters a GNSS Navigation Message callback.
*
- * @param callback a {@link GnssNavigationMessageEvent.Callback} object to remove.
+ * @param callback a {@link GnssNavigationMessage.Callback} object to remove.
*/
public void unregisterGnssNavigationMessageCallback(
- GnssNavigationMessageEvent.Callback callback) {
+ GnssNavigationMessage.Callback callback) {
mGnssNavigationMessageCallbackTransport.remove(callback);
}
/**
- * No-op method to keep backward-compatibility.
- * Don't use it. Use {@link #unregisterGnssNavigationMessageCallback} instead.
- * @hide
- * @deprecated
- */
- @Deprecated
- @SystemApi
- public void removeGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {
- }
-
- /**
* Retrieves information about the current status of the GPS engine.
* This should only be called from the {@link GpsStatus.Listener#onGpsStatusChanged}
* callback to ensure that the data is copied atomically.
diff --git a/location/java/android/location/OnNmeaMessageListener.java b/location/java/android/location/OnNmeaMessageListener.java
new file mode 100644
index 0000000..ccf6ce8
--- /dev/null
+++ b/location/java/android/location/OnNmeaMessageListener.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 android.location;
+
+/**
+* Used for receiving NMEA sentences from the GNSS.
+* NMEA 0183 is a standard for communicating with marine electronic devices
+* and is a common method for receiving data from a GNSS, typically over a serial port.
+* See <a href="http://en.wikipedia.org/wiki/NMEA_0183">NMEA 0183</a> for more details.
+* You can implement this interface and call {@link LocationManager#addNmeaListener}
+* to receive NMEA data from the GNSS engine.
+*/
+public interface OnNmeaMessageListener {
+ /**
+ * Called when an NMEA message is received.
+ * @param message NMEA message
+ * @param timestamp milliseconds since January 1, 1970.
+ */
+ void onNmeaMessage(String message, long timestamp);
+}
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 3d7e744..72f5742 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -697,7 +697,8 @@
/**
* Reads Exif tags from the specified image file descriptor. Attribute mutation is supported
- * for writable and seekable file descriptors only.
+ * for writable and seekable file descriptors only. This constructor will not rewind the offset
+ * of the given file descriptor. Developers should close the file descriptor after use.
*/
public ExifInterface(FileDescriptor fileDescriptor) throws IOException {
if (fileDescriptor == null) {
@@ -730,7 +731,8 @@
/**
* Reads Exif tags from the specified image input stream. Attribute mutation is not supported
- * for input streams.
+ * for input streams. The given input stream will proceed its current position. Developers
+ * should close the input stream after use.
*/
public ExifInterface(InputStream inputStream) throws IOException {
if (inputStream == null) {
diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java
index a5ff29f..2613376 100644
--- a/media/java/android/media/tv/TvRecordingClient.java
+++ b/media/java/android/media/tv/TvRecordingClient.java
@@ -158,7 +158,7 @@
* <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
+ * program, whereas null {@code programUri} does not impose such a requirement and the
* recording can span across multiple TV programs. In either case, the application must call
* {@link TvRecordingClient#stopRecording()} to stop the recording.
*
diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java
index 3814630..61fbfb9 100644
--- a/media/java/android/mtp/MtpServer.java
+++ b/media/java/android/mtp/MtpServer.java
@@ -23,12 +23,14 @@
public class MtpServer implements Runnable {
private long mNativeContext; // accessed by native methods
+ private final MtpDatabase mDatabase;
static {
System.loadLibrary("media_jni");
}
public MtpServer(MtpDatabase database, boolean usePtp) {
+ mDatabase = database;
native_setup(database, usePtp);
database.setServer(this);
}
@@ -42,6 +44,7 @@
public void run() {
native_run();
native_cleanup();
+ mDatabase.close();
}
public void sendObjectAdded(int handle) {
diff --git a/media/jni/android_media_MediaDataSource.cpp b/media/jni/android_media_MediaDataSource.cpp
index 537b56d..d07942b 100644
--- a/media/jni/android_media_MediaDataSource.cpp
+++ b/media/jni/android_media_MediaDataSource.cpp
@@ -155,4 +155,8 @@
return 0;
}
+String8 JMediaDataSource::toString() {
+ return String8::format("JMediaDataSource(pid %d, uid %d)", getpid(), getuid());
+}
+
} // namespace android
diff --git a/media/jni/android_media_MediaDataSource.h b/media/jni/android_media_MediaDataSource.h
index 34624eb..378baf4 100644
--- a/media/jni/android_media_MediaDataSource.h
+++ b/media/jni/android_media_MediaDataSource.h
@@ -46,6 +46,7 @@
virtual status_t getSize(off64_t* size);
virtual void close();
virtual uint32_t getFlags();
+ virtual String8 toString();
private:
// Protect all member variables with mLock because this object will be
diff --git a/packages/DocumentsUI/res/values-af/strings.xml b/packages/DocumentsUI/res/values-af/strings.xml
index 1a7c620..27c4bbc 100644
--- a/packages/DocumentsUI/res/values-af/strings.xml
+++ b/packages/DocumentsUI/res/values-af/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumente"</string>
- <string name="files_label" msgid="6051402950202690279">"Lêers"</string>
<string name="downloads_label" msgid="959113951084633612">"Aflaaie"</string>
<string name="title_open" msgid="4353228937663917801">"Maak oop vanuit"</string>
<string name="title_save" msgid="2433679664882857999">"Stoor na"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Vee \"<xliff:g id="NAME">%1$s</xliff:g>\" uit?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Vee vouer \"<xliff:g id="NAME">%1$s</xliff:g>\" en sy inhoud uit?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-am/strings.xml b/packages/DocumentsUI/res/values-am/strings.xml
index ca43dab..0e1a34d 100644
--- a/packages/DocumentsUI/res/values-am/strings.xml
+++ b/packages/DocumentsUI/res/values-am/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"ሰነዶች"</string>
- <string name="files_label" msgid="6051402950202690279">"ፋይሎች"</string>
<string name="downloads_label" msgid="959113951084633612">"የወረዱ"</string>
<string name="title_open" msgid="4353228937663917801">"ክፈት ከ"</string>
<string name="title_save" msgid="2433679664882857999">"አስቀምጥ ወደ"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"«<xliff:g id="NAME">%1$s</xliff:g>» ይሰረዝ?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"አቃፊ «<xliff:g id="NAME">%1$s</xliff:g>» እና ይዘቶቹ ይሰረዙ?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-ar/strings.xml b/packages/DocumentsUI/res/values-ar/strings.xml
index e6fac50..264a275 100644
--- a/packages/DocumentsUI/res/values-ar/strings.xml
+++ b/packages/DocumentsUI/res/values-ar/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"مستندات"</string>
- <string name="files_label" msgid="6051402950202690279">"الملفات"</string>
<string name="downloads_label" msgid="959113951084633612">"التنزيلات"</string>
<string name="title_open" msgid="4353228937663917801">"فتح من"</string>
<string name="title_save" msgid="2433679664882857999">"حفظ في"</string>
@@ -152,6 +151,14 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"هل تريد حذف \"<xliff:g id="NAME">%1$s</xliff:g>\"؟"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"هل تريد حذف المجلد \"<xliff:g id="NAME">%1$s</xliff:g>\" ومحتوياته؟"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-az-rAZ/strings.xml b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
index 75a0686..e1d6050 100644
--- a/packages/DocumentsUI/res/values-az-rAZ/strings.xml
+++ b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Sənədlər"</string>
- <string name="files_label" msgid="6051402950202690279">"Fayllar"</string>
<string name="downloads_label" msgid="959113951084633612">"Endirmələr"</string>
<string name="title_open" msgid="4353228937663917801">"Vasitəsilə açın"</string>
<string name="title_save" msgid="2433679664882857999">"buraya saxlayın"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> element</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> element</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" silinsin?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" qovluğu və onun məzmunu silinsin?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
index 34c08bd..83f2763 100644
--- a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumenti"</string>
- <string name="files_label" msgid="6051402950202690279">"Datoteke"</string>
<string name="downloads_label" msgid="959113951084633612">"Preuzimanja"</string>
<string name="title_open" msgid="4353228937663917801">"Otvori sa"</string>
<string name="title_save" msgid="2433679664882857999">"Sačuvaj u"</string>
@@ -128,6 +127,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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> stavka</item>
+ <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> stavke</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> stavki</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Želite li da izbrišete „<xliff:g id="NAME">%1$s</xliff:g>“?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Želite li da izbrišete direktorijum „<xliff:g id="NAME">%1$s</xliff:g>“ i njegov sadržaj?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-be-rBY/strings.xml b/packages/DocumentsUI/res/values-be-rBY/strings.xml
index 8493c477..1c06cd1 100644
--- a/packages/DocumentsUI/res/values-be-rBY/strings.xml
+++ b/packages/DocumentsUI/res/values-be-rBY/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Дакументы"</string>
- <string name="files_label" msgid="6051402950202690279">"Файлы"</string>
<string name="downloads_label" msgid="959113951084633612">"Спампоўкі"</string>
<string name="title_open" msgid="4353228937663917801">"Адкрыць з"</string>
<string name="title_save" msgid="2433679664882857999">"Захаваць у"</string>
@@ -125,7 +124,7 @@
<string name="rename_error" msgid="4203041674883412606">"Не атрымалася перайменаваць дакумент"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Некаторыя файлы былі сканвертаваныя"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Даць праграме <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ да дырэкторыі <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> у <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
- <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Даць праграме <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ да дырэкторыі <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Даць праграме <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ да каталога <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Даць <xliff:g id="APPNAME"><b>^1</b></xliff:g> доступ да вашых даных, у тым ліку фатаграфій і відэа, на <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Больш не пытацца"</string>
<string name="allow" msgid="7225948811296386551">"Дазволіць"</string>
@@ -136,6 +135,12 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Выдаліць \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Выдаліць папку \"<xliff:g id="NAME">%1$s</xliff:g>\" і яе змесціва?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-bg/strings.xml b/packages/DocumentsUI/res/values-bg/strings.xml
index 1914bf5..16922c8 100644
--- a/packages/DocumentsUI/res/values-bg/strings.xml
+++ b/packages/DocumentsUI/res/values-bg/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Документи"</string>
- <string name="files_label" msgid="6051402950202690279">"Файлове"</string>
<string name="downloads_label" msgid="959113951084633612">"Изтегляния"</string>
<string name="title_open" msgid="4353228937663917801">"Отваряне от"</string>
<string name="title_save" msgid="2433679664882857999">"Запазване във:"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"Искате ли да изтриете „<xliff:g id="NAME">%1$s</xliff:g>“?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Искате ли да изтриете папката „<xliff:g id="NAME">%1$s</xliff:g>“ и съдържанието в нея?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-bn-rBD/strings.xml b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
index d931c2b..4be7dc80 100644
--- a/packages/DocumentsUI/res/values-bn-rBD/strings.xml
+++ b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"দস্তাবেজগুলি"</string>
- <string name="files_label" msgid="6051402950202690279">"ফাইলগুলি"</string>
<string name="downloads_label" msgid="959113951084633612">"ডাউনলোডগুলি"</string>
<string name="title_open" msgid="4353228937663917801">"এখান থেকে খুলুন"</string>
<string name="title_save" msgid="2433679664882857999">"এতে সংরক্ষণ করুন"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" মুছবেন?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" ফোল্ডার এবং এটির সামগ্রীগুলিকে মুছবেন?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-bs-rBA/strings.xml b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
index 47ff436..aae7986 100644
--- a/packages/DocumentsUI/res/values-bs-rBA/strings.xml
+++ b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumenti"</string>
- <string name="files_label" msgid="6051402950202690279">"Fajlovi"</string>
<string name="downloads_label" msgid="959113951084633612">"Preuzimanja"</string>
<string name="title_open" msgid="4353228937663917801">"Otvori iz"</string>
<string name="title_save" msgid="2433679664882857999">"Sačuvaj u"</string>
@@ -128,6 +127,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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> stavka</item>
+ <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> stavke</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> stavki</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Želite li izbrisati \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Želite li izbrisati folder \"<xliff:g id="NAME">%1$s</xliff:g>\" i njegov sadržaj?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-ca/strings.xml b/packages/DocumentsUI/res/values-ca/strings.xml
index 09af97d..85b42076 100644
--- a/packages/DocumentsUI/res/values-ca/strings.xml
+++ b/packages/DocumentsUI/res/values-ca/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Documents"</string>
- <string name="files_label" msgid="6051402950202690279">"Fitxers"</string>
<string name="downloads_label" msgid="959113951084633612">"Baixades"</string>
<string name="title_open" msgid="4353228937663917801">"Obre des de"</string>
<string name="title_save" msgid="2433679664882857999">"Desa a"</string>
@@ -120,6 +119,10 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elements seleccionats</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> element seleccionat</item>
</plurals>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elements</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> element</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Vols suprimir el fitxer <xliff:g id="NAME">%1$s</xliff:g>?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Vols suprimir la carpeta <xliff:g id="NAME">%1$s</xliff:g> i el seu contingut?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml
index cba2e0e..5ab5a41 100644
--- a/packages/DocumentsUI/res/values-cs/strings.xml
+++ b/packages/DocumentsUI/res/values-cs/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumenty"</string>
- <string name="files_label" msgid="6051402950202690279">"Soubory"</string>
<string name="downloads_label" msgid="959113951084633612">"Stahování"</string>
<string name="title_open" msgid="4353228937663917801">"Otevřít"</string>
<string name="title_save" msgid="2433679664882857999">"Uložit do"</string>
@@ -136,6 +135,12 @@
<item quantity="other">Vybráno <xliff:g id="COUNT_1">%1$d</xliff:g> položek</item>
<item quantity="one">Vybrána <xliff:g id="COUNT_0">%1$d</xliff:g> položka</item>
</plurals>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> položky</item>
+ <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> položky</item>
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"Smazat soubor <xliff:g id="NAME">%1$s</xliff:g>?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Smazat složku <xliff:g id="NAME">%1$s</xliff:g> a její obsah?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-da/strings.xml b/packages/DocumentsUI/res/values-da/strings.xml
index f048e34..840dc00 100644
--- a/packages/DocumentsUI/res/values-da/strings.xml
+++ b/packages/DocumentsUI/res/values-da/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumenter"</string>
- <string name="files_label" msgid="6051402950202690279">"Filer"</string>
<string name="downloads_label" msgid="959113951084633612">"Downloads"</string>
<string name="title_open" msgid="4353228937663917801">"Åbn fra"</string>
<string name="title_save" msgid="2433679664882857999">"Gem i"</string>
@@ -120,6 +119,10 @@
<item quantity="one">Der er valgt <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="other">Der er valgt <xliff:g id="COUNT_1">%1$d</xliff:g></item>
</plurals>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> element</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementer</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Vil du slette \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Vil du slette mappen \"<xliff:g id="NAME">%1$s</xliff:g>\" og dens indhold?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-de/strings.xml b/packages/DocumentsUI/res/values-de/strings.xml
index a6eae70..eb81827 100644
--- a/packages/DocumentsUI/res/values-de/strings.xml
+++ b/packages/DocumentsUI/res/values-de/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumente"</string>
- <string name="files_label" msgid="6051402950202690279">"Dateien"</string>
<string name="downloads_label" msgid="959113951084633612">"Downloads"</string>
<string name="title_open" msgid="4353228937663917801">"Öffnen von"</string>
<string name="title_save" msgid="2433679664882857999">"Speichern unter"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> Einträge</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> Eintrag</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" löschen?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Ordner \"<xliff:g id="NAME">%1$s</xliff:g>\" und dessen Inhalte löschen?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-el/strings.xml b/packages/DocumentsUI/res/values-el/strings.xml
index 7dc2067..ad681bd 100644
--- a/packages/DocumentsUI/res/values-el/strings.xml
+++ b/packages/DocumentsUI/res/values-el/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Έγγραφα"</string>
- <string name="files_label" msgid="6051402950202690279">"Αρχεία"</string>
<string name="downloads_label" msgid="959113951084633612">"Λήψεις"</string>
<string name="title_open" msgid="4353228937663917801">"Άνοιγμα από"</string>
<string name="title_save" msgid="2433679664882857999">"Αποθήκευση σε"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"Να διαγραφεί το αρχείο \"<xliff:g id="NAME">%1$s</xliff:g>\";"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Να διαγραφεί ο φάκελος \"<xliff:g id="NAME">%1$s</xliff:g>\" και τα περιεχόμενά του;"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-en-rAU/strings.xml b/packages/DocumentsUI/res/values-en-rAU/strings.xml
index 8524de5..406d2ec 100644
--- a/packages/DocumentsUI/res/values-en-rAU/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rAU/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Documents"</string>
- <string name="files_label" msgid="6051402950202690279">"Files"</string>
<string name="downloads_label" msgid="959113951084633612">"Downloads"</string>
<string name="title_open" msgid="4353228937663917801">"Open from"</string>
<string name="title_save" msgid="2433679664882857999">"Save to"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Delete \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Delete folder \"<xliff:g id="NAME">%1$s</xliff:g>\" and its contents?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-en-rGB/strings.xml b/packages/DocumentsUI/res/values-en-rGB/strings.xml
index 8524de5..406d2ec 100644
--- a/packages/DocumentsUI/res/values-en-rGB/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rGB/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Documents"</string>
- <string name="files_label" msgid="6051402950202690279">"Files"</string>
<string name="downloads_label" msgid="959113951084633612">"Downloads"</string>
<string name="title_open" msgid="4353228937663917801">"Open from"</string>
<string name="title_save" msgid="2433679664882857999">"Save to"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Delete \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Delete folder \"<xliff:g id="NAME">%1$s</xliff:g>\" and its contents?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-en-rIN/strings.xml b/packages/DocumentsUI/res/values-en-rIN/strings.xml
index 8524de5..406d2ec 100644
--- a/packages/DocumentsUI/res/values-en-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rIN/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Documents"</string>
- <string name="files_label" msgid="6051402950202690279">"Files"</string>
<string name="downloads_label" msgid="959113951084633612">"Downloads"</string>
<string name="title_open" msgid="4353228937663917801">"Open from"</string>
<string name="title_save" msgid="2433679664882857999">"Save to"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Delete \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Delete folder \"<xliff:g id="NAME">%1$s</xliff:g>\" and its contents?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-es-rUS/strings.xml b/packages/DocumentsUI/res/values-es-rUS/strings.xml
index 87641a7..bb471f7 100644
--- a/packages/DocumentsUI/res/values-es-rUS/strings.xml
+++ b/packages/DocumentsUI/res/values-es-rUS/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Documentos"</string>
- <string name="files_label" msgid="6051402950202690279">"Archivos"</string>
<string name="downloads_label" msgid="959113951084633612">"Descargas"</string>
<string name="title_open" msgid="4353228937663917801">"Abrir desde"</string>
<string name="title_save" msgid="2433679664882857999">"Guardar en"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementos</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elemento</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"¿Deseas borrar \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"¿Deseas borrar la carpeta \"<xliff:g id="NAME">%1$s</xliff:g>\" y su contenido?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-es/strings.xml b/packages/DocumentsUI/res/values-es/strings.xml
index 9054561..2373e60 100644
--- a/packages/DocumentsUI/res/values-es/strings.xml
+++ b/packages/DocumentsUI/res/values-es/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Documentos"</string>
- <string name="files_label" msgid="6051402950202690279">"Archivos"</string>
<string name="downloads_label" msgid="959113951084633612">"Descargas"</string>
<string name="title_open" msgid="4353228937663917801">"Abrir desde"</string>
<string name="title_save" msgid="2433679664882857999">"Guardar en"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementos</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elemento</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"¿Eliminar <xliff:g id="NAME">%1$s</xliff:g>?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"¿Eliminar la carpeta <xliff:g id="NAME">%1$s</xliff:g> y su contenido?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-et-rEE/strings.xml b/packages/DocumentsUI/res/values-et-rEE/strings.xml
index 4bb2a9b..6bc3942 100644
--- a/packages/DocumentsUI/res/values-et-rEE/strings.xml
+++ b/packages/DocumentsUI/res/values-et-rEE/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumendid"</string>
- <string name="files_label" msgid="6051402950202690279">"Failid"</string>
<string name="downloads_label" msgid="959113951084633612">"Allalaadimised"</string>
<string name="title_open" msgid="4353228937663917801">"Ava:"</string>
<string name="title_save" msgid="2433679664882857999">"Salvesta:"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> üksust</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> üksus</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Kas kustutada fail „<xliff:g id="NAME">%1$s</xliff:g>”?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Kas kustutada kaust „<xliff:g id="NAME">%1$s</xliff:g>” ja selle sisu?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-eu-rES/strings.xml b/packages/DocumentsUI/res/values-eu-rES/strings.xml
index d2bf89d..da11c5c 100644
--- a/packages/DocumentsUI/res/values-eu-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-eu-rES/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumentuak"</string>
- <string name="files_label" msgid="6051402950202690279">"Fitxategiak"</string>
<string name="downloads_label" msgid="959113951084633612">"Deskargak"</string>
<string name="title_open" msgid="4353228937663917801">"Ireki hemendik"</string>
<string name="title_save" msgid="2433679664882857999">"Gorde hemen"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementu</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elementu</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" ezabatu nahi duzu?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" karpeta eta bertako edukia ezabatu nahi duzu?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-fa/strings.xml b/packages/DocumentsUI/res/values-fa/strings.xml
index 1a4c035..fb4b487 100644
--- a/packages/DocumentsUI/res/values-fa/strings.xml
+++ b/packages/DocumentsUI/res/values-fa/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"اسناد"</string>
- <string name="files_label" msgid="6051402950202690279">"فایلها"</string>
<string name="downloads_label" msgid="959113951084633612">"بارگیریها"</string>
<string name="title_open" msgid="4353228937663917801">"باز کردن از"</string>
<string name="title_save" msgid="2433679664882857999">"ذخیره در"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"«<xliff:g id="NAME">%1$s</xliff:g>» حذف شود؟"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"پوشه «<xliff:g id="NAME">%1$s</xliff:g>» و محتوای آن حذف شود؟"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml
index dfcfe89..21c0ce2 100644
--- a/packages/DocumentsUI/res/values-fi/strings.xml
+++ b/packages/DocumentsUI/res/values-fi/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Asiakirjat"</string>
- <string name="files_label" msgid="6051402950202690279">"Tiedostot"</string>
<string name="downloads_label" msgid="959113951084633612">"Lataukset"</string>
<string name="title_open" msgid="4353228937663917801">"Avaa sijainnista"</string>
<string name="title_save" msgid="2433679664882857999">"Tallenna kohteeseen"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> kohdetta</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> kohde</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Poistetaanko <xliff:g id="NAME">%1$s</xliff:g>?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Poistetaanko kansio <xliff:g id="NAME">%1$s</xliff:g> ja sen sisältö?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-fr-rCA/strings.xml b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
index 543e226..a741e6b 100644
--- a/packages/DocumentsUI/res/values-fr-rCA/strings.xml
+++ b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Documents"</string>
- <string name="files_label" msgid="6051402950202690279">"Fichiers"</string>
<string name="downloads_label" msgid="959113951084633612">"Téléchargements"</string>
<string name="title_open" msgid="4353228937663917801">"Ouvrir à partir de"</string>
<string name="title_save" msgid="2433679664882857999">"Enregistrer dans"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> article</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> articles</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Supprimer « <xliff:g id="NAME">%1$s</xliff:g> »?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Supprimer le dossier « <xliff:g id="NAME">%1$s</xliff:g> » et son contenu?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml
index 05716d7..d41137e 100644
--- a/packages/DocumentsUI/res/values-fr/strings.xml
+++ b/packages/DocumentsUI/res/values-fr/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Docs"</string>
- <string name="files_label" msgid="6051402950202690279">"Fichiers"</string>
<string name="downloads_label" msgid="959113951084633612">"Téléchargements"</string>
<string name="title_open" msgid="4353228937663917801">"Ouvrir à partir de"</string>
<string name="title_save" msgid="2433679664882857999">"Enregistrer sous"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Supprimer \"<xliff:g id="NAME">%1$s</xliff:g>\" ?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Supprimer le dossier \"<xliff:g id="NAME">%1$s</xliff:g>\" et son contenu ?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-gl-rES/strings.xml b/packages/DocumentsUI/res/values-gl-rES/strings.xml
index 5797a96..77cc59d6 100644
--- a/packages/DocumentsUI/res/values-gl-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-gl-rES/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Documentos"</string>
- <string name="files_label" msgid="6051402950202690279">"Ficheiros"</string>
<string name="downloads_label" msgid="959113951084633612">"Descargas"</string>
<string name="title_open" msgid="4353228937663917801">"Abrir desde"</string>
<string name="title_save" msgid="2433679664882857999">"Gardar en"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementos</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elemento</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Queres eliminar \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Queres eliminar o cartafol \"<xliff:g id="NAME">%1$s</xliff:g>\" e o seu contido?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-gu-rIN/strings.xml b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
index 48e43c4..e3cd4cf 100644
--- a/packages/DocumentsUI/res/values-gu-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"દસ્તાવેજો"</string>
- <string name="files_label" msgid="6051402950202690279">"ફાઇલો"</string>
<string name="downloads_label" msgid="959113951084633612">"ડાઉનલોડ્સ"</string>
<string name="title_open" msgid="4353228937663917801">"અહીંથી ખોલો"</string>
<string name="title_save" msgid="2433679664882857999">"આમાં સાચવો"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" ને કાઢી નાખીએ?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" ફોલ્ડર અને તેની સામગ્રીઓને કાઢી નાખીએ?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-hi/strings.xml b/packages/DocumentsUI/res/values-hi/strings.xml
index fa82ee8..fa27dff 100644
--- a/packages/DocumentsUI/res/values-hi/strings.xml
+++ b/packages/DocumentsUI/res/values-hi/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"दस्तावेज़"</string>
- <string name="files_label" msgid="6051402950202690279">"फ़ाइलें"</string>
<string name="downloads_label" msgid="959113951084633612">"डाउनलोड"</string>
<string name="title_open" msgid="4353228937663917801">"यहां से खोलें"</string>
<string name="title_save" msgid="2433679664882857999">"यहां सहेजें"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" को हटाएं?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" फ़ोल्डर और उसकी सामग्रियां हटाएं?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-hr/strings.xml b/packages/DocumentsUI/res/values-hr/strings.xml
index 7988c71..66a8329 100644
--- a/packages/DocumentsUI/res/values-hr/strings.xml
+++ b/packages/DocumentsUI/res/values-hr/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumenti"</string>
- <string name="files_label" msgid="6051402950202690279">"Datoteke"</string>
<string name="downloads_label" msgid="959113951084633612">"Preuzimanja"</string>
<string name="title_open" msgid="4353228937663917801">"Otvori iz"</string>
<string name="title_save" msgid="2433679664882857999">"Spremi u"</string>
@@ -128,6 +127,11 @@
<item quantity="few">Odabrano: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="other">Odabrano: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
</plurals>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> stavka</item>
+ <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> stavke</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> stavki</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Želite li izbrisati datoteku \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Želite li izbrisati mapu \"<xliff:g id="NAME">%1$s</xliff:g>\" i njezin sadržaj?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-hu/strings.xml b/packages/DocumentsUI/res/values-hu/strings.xml
index fb666b5..962653c 100644
--- a/packages/DocumentsUI/res/values-hu/strings.xml
+++ b/packages/DocumentsUI/res/values-hu/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumentumok"</string>
- <string name="files_label" msgid="6051402950202690279">"Fájlok"</string>
<string name="downloads_label" msgid="959113951084633612">"Letöltések"</string>
<string name="title_open" msgid="4353228937663917801">"Megnyitás innen"</string>
<string name="title_save" msgid="2433679664882857999">"Mentés ide"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elem</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elem</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Törli a következőt: „<xliff:g id="NAME">%1$s</xliff:g>”?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Törli „<xliff:g id="NAME">%1$s</xliff:g>” mappát a tartalmával együtt?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-hy-rAM/strings.xml b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
index f6c3ad5..ab83358 100644
--- a/packages/DocumentsUI/res/values-hy-rAM/strings.xml
+++ b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Փաստաթղթեր"</string>
- <string name="files_label" msgid="6051402950202690279">"Ֆայլեր"</string>
<string name="downloads_label" msgid="959113951084633612">"Ներբեռնումներ"</string>
<string name="title_open" msgid="4353228937663917801">"Բացել այստեղից"</string>
<string name="title_save" msgid="2433679664882857999">"Պահել այստեղ"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"Ջնջե՞լ «<xliff:g id="NAME">%1$s</xliff:g>» ֆայլը:"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Ջնջե՞լ «<xliff:g id="NAME">%1$s</xliff:g>» պանակը՝ բովանդակության հետ մեկտեղ:"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-in/strings.xml b/packages/DocumentsUI/res/values-in/strings.xml
index a8aee52..745bf45 100644
--- a/packages/DocumentsUI/res/values-in/strings.xml
+++ b/packages/DocumentsUI/res/values-in/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumen"</string>
- <string name="files_label" msgid="6051402950202690279">"File"</string>
<string name="downloads_label" msgid="959113951084633612">"Unduhan"</string>
<string name="title_open" msgid="4353228937663917801">"Buka dari"</string>
<string name="title_save" msgid="2433679664882857999">"Simpan ke"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> item</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Hapus \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Hapus folder \"<xliff:g id="NAME">%1$s</xliff:g>\" dan kontennya?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-is-rIS/strings.xml b/packages/DocumentsUI/res/values-is-rIS/strings.xml
index 88aaced..47c3d35 100644
--- a/packages/DocumentsUI/res/values-is-rIS/strings.xml
+++ b/packages/DocumentsUI/res/values-is-rIS/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Skjöl"</string>
- <string name="files_label" msgid="6051402950202690279">"Skrár"</string>
<string name="downloads_label" msgid="959113951084633612">"Niðurhal"</string>
<string name="title_open" msgid="4353228937663917801">"Opna frá"</string>
<string name="title_save" msgid="2433679664882857999">"Vista í"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> atriði</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> atriði</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Eyða „<xliff:g id="NAME">%1$s</xliff:g>“?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Eyða möppunni „<xliff:g id="NAME">%1$s</xliff:g>“ og öllu innihaldi hennar?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index b7497db..0321fb1 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Documenti"</string>
- <string name="files_label" msgid="6051402950202690279">"File"</string>
<string name="downloads_label" msgid="959113951084633612">"Download"</string>
<string name="title_open" msgid="4353228937663917801">"Apri da"</string>
<string name="title_save" msgid="2433679664882857999">"Salva in"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementi</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elemento</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Eliminare \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Eliminare la cartella \"<xliff:g id="NAME">%1$s</xliff:g>\" e i relativi contenuti?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-iw/strings.xml b/packages/DocumentsUI/res/values-iw/strings.xml
index 4498f8c..4e69606 100644
--- a/packages/DocumentsUI/res/values-iw/strings.xml
+++ b/packages/DocumentsUI/res/values-iw/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"מסמכים"</string>
- <string name="files_label" msgid="6051402950202690279">"קבצים"</string>
<string name="downloads_label" msgid="959113951084633612">"הורדות"</string>
<string name="title_open" msgid="4353228937663917801">"פתח מ-"</string>
<string name="title_save" msgid="2433679664882857999">"שמור ב-"</string>
@@ -136,6 +135,12 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"האם למחוק את \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"האם למחוק את התיקייה \"<xliff:g id="NAME">%1$s</xliff:g>\" ואת התוכן שלה?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-ja/strings.xml b/packages/DocumentsUI/res/values-ja/strings.xml
index bfb1c3a..027bc03 100644
--- a/packages/DocumentsUI/res/values-ja/strings.xml
+++ b/packages/DocumentsUI/res/values-ja/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"ドキュメント"</string>
- <string name="files_label" msgid="6051402950202690279">"ファイル"</string>
<string name="downloads_label" msgid="959113951084633612">"ダウンロード"</string>
<string name="title_open" msgid="4353228937663917801">"次から開く:"</string>
<string name="title_save" msgid="2433679664882857999">"次に保存:"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"「<xliff:g id="NAME">%1$s</xliff:g>」を削除しますか?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"フォルダ「<xliff:g id="NAME">%1$s</xliff:g>」とそのコンテンツを削除しますか?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-ka-rGE/strings.xml b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
index f0e9e86..4ac61f2 100644
--- a/packages/DocumentsUI/res/values-ka-rGE/strings.xml
+++ b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"დოკუმენტები"</string>
- <string name="files_label" msgid="6051402950202690279">"ფაილები"</string>
<string name="downloads_label" msgid="959113951084633612">"ჩამოტვირთვები"</string>
<string name="title_open" msgid="4353228937663917801">"გახსნა აქედან:"</string>
<string name="title_save" msgid="2433679664882857999">"შენახვა აქ:"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"გსურთ, წაშალოთ „<xliff:g id="NAME">%1$s</xliff:g>“?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"გსურთ, წაშალოთ საქაღალდე „<xliff:g id="NAME">%1$s</xliff:g>“ და მისი შიგთავსი?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
index 2687900..1babc72 100644
--- a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
+++ b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Құжаттар"</string>
- <string name="files_label" msgid="6051402950202690279">"Файлдар"</string>
<string name="downloads_label" msgid="959113951084633612">"Жүктеулер"</string>
<string name="title_open" msgid="4353228937663917801">"Мынадан ашу:"</string>
<string name="title_save" msgid="2433679664882857999">"Сақталатын орны"</string>
@@ -111,7 +110,7 @@
<string name="rename_error" msgid="4203041674883412606">"Құжат қайта аталмады"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Кейбір файлдар түрлендірілді"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> қолданбасына <xliff:g id="STORAGE"><i>^3</i></xliff:g> қоймасындағы <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> каталогына өтуге рұқсат беру керек пе?"</string>
- <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> қолданбасына <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> каталогына қатынас беру керек пе?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> қолданбасына <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> каталогына кіруге рұқсат беру керек пе?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"<xliff:g id="APPNAME"><b>^1</b></xliff:g> <xliff:g id="STORAGE"><i>^2</i></xliff:g> қоймасындағы деректерге, соның ішінде фотосуреттерге және бейнелерге кіру мүмкіндігін беру керек пе?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Қайта сұралмасын"</string>
<string name="allow" msgid="7225948811296386551">"Рұқсат беру"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" жою керек пе?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" қалтасын және оның мазмұнын жою керек пе?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml
index ea24043..37eb3cb 100644
--- a/packages/DocumentsUI/res/values-km-rKH/strings.xml
+++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"ឯកសារ"</string>
- <string name="files_label" msgid="6051402950202690279">"ឯកសារ"</string>
<string name="downloads_label" msgid="959113951084633612">"ដោនឡូត"</string>
<string name="title_open" msgid="4353228937663917801">"បើកពី"</string>
<string name="title_save" msgid="2433679664882857999">"រក្សាទុកទៅ"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"លុប \"<xliff:g id="NAME">%1$s</xliff:g>\" ឬ?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"លុបថតឯកសារ \"<xliff:g id="NAME">%1$s</xliff:g>\" និងមាតិការបស់វាឬ?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-kn-rIN/strings.xml b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
index c756009..ad287d4 100644
--- a/packages/DocumentsUI/res/values-kn-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"ಡಾಕ್ಯುಮೆಂಟ್ಗಳು"</string>
- <string name="files_label" msgid="6051402950202690279">"ಫೈಲ್ಗಳು"</string>
<string name="downloads_label" msgid="959113951084633612">"ಡೌನ್ಲೋಡ್ಗಳು"</string>
<string name="title_open" msgid="4353228937663917801">"ಇದರ ಮೂಲಕ ತೆರೆಯಿರಿ"</string>
<string name="title_save" msgid="2433679664882857999">"ಇವುಗಳಲ್ಲಿ ಉಳಿಸಿ"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" ಅಳಿಸುವುದೇ?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" ಫೋಲ್ಡರ್ ಮತ್ತು ಅದರ ವಿಷಯಗಳನ್ನು ಅಳಿಸುವುದೇ?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-ko/strings.xml b/packages/DocumentsUI/res/values-ko/strings.xml
index 4d5dcf9..9441a10 100644
--- a/packages/DocumentsUI/res/values-ko/strings.xml
+++ b/packages/DocumentsUI/res/values-ko/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"문서"</string>
- <string name="files_label" msgid="6051402950202690279">"파일"</string>
<string name="downloads_label" msgid="959113951084633612">"다운로드"</string>
<string name="title_open" msgid="4353228937663917801">"열기:"</string>
<string name="title_save" msgid="2433679664882857999">"저장 위치:"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"<xliff:g id="NAME">%1$s</xliff:g>을(를) 삭제하시겠습니까?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\'<xliff:g id="NAME">%1$s</xliff:g>\' 폴더와 폴더에 포함된 콘텐츠를 삭제하시겠습니까?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-ky-rKG/strings.xml b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
index 1b39039..1856eeb 100644
--- a/packages/DocumentsUI/res/values-ky-rKG/strings.xml
+++ b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Документтер"</string>
- <string name="files_label" msgid="6051402950202690279">"Файлдар"</string>
<string name="downloads_label" msgid="959113951084633612">"Жүктөлүп алынгандар"</string>
<string name="title_open" msgid="4353228937663917801">"Кийинкиден ачуу:"</string>
<string name="title_save" msgid="2433679664882857999">"Кийинкиге сактоо:"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" жок кылынсынбы?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" куржуну мазмуну менен жок кылынсынбы?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-lo-rLA/strings.xml b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
index a4f381d..1923940 100644
--- a/packages/DocumentsUI/res/values-lo-rLA/strings.xml
+++ b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"ເອກະສານ"</string>
- <string name="files_label" msgid="6051402950202690279">"ໄຟລ໌"</string>
<string name="downloads_label" msgid="959113951084633612">"ການດາວໂຫລດ"</string>
<string name="title_open" msgid="4353228937663917801">"ເປີດຈາກ"</string>
<string name="title_save" msgid="2433679664882857999">"ບັນທຶກໄປທີ່"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"ລຶບ \"<xliff:g id="NAME">%1$s</xliff:g>\" ອອກບໍ?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"ລຶບໂຟນເດີ \"<xliff:g id="NAME">%1$s</xliff:g>\" ແລະ ເນື້ອຫາທັງໝົດຂອງມັນອອກບໍ?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-lt/strings.xml b/packages/DocumentsUI/res/values-lt/strings.xml
index 2e0df93..d7d6c69 100644
--- a/packages/DocumentsUI/res/values-lt/strings.xml
+++ b/packages/DocumentsUI/res/values-lt/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumentai"</string>
- <string name="files_label" msgid="6051402950202690279">"Failai"</string>
<string name="downloads_label" msgid="959113951084633612">"Atsisiuntimai"</string>
<string name="title_open" msgid="4353228937663917801">"Atidaryti iš"</string>
<string name="title_save" msgid="2433679664882857999">"Išsaugoti į"</string>
@@ -136,6 +135,12 @@
<item quantity="many">Pasirinkta <xliff:g id="COUNT_1">%1$d</xliff:g> elemento</item>
<item quantity="other">Pasirinkta <xliff:g id="COUNT_1">%1$d</xliff:g> elementų</item>
</plurals>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> elementas</item>
+ <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> elementai</item>
+ <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> elemento</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementų</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Ištrinti „<xliff:g id="NAME">%1$s</xliff:g>“?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Ištrinti aplanką „<xliff:g id="NAME">%1$s</xliff:g>“ ir jo turinį?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-lv/strings.xml b/packages/DocumentsUI/res/values-lv/strings.xml
index fb81aa0..ef2e6e6 100644
--- a/packages/DocumentsUI/res/values-lv/strings.xml
+++ b/packages/DocumentsUI/res/values-lv/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumenti"</string>
- <string name="files_label" msgid="6051402950202690279">"Faili"</string>
<string name="downloads_label" msgid="959113951084633612">"Lejupielādes"</string>
<string name="title_open" msgid="4353228937663917801">"Atvēršana no:"</string>
<string name="title_save" msgid="2433679664882857999">"Saglabāšana:"</string>
@@ -128,6 +127,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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="zero"><xliff:g id="COUNT_1">%1$d</xliff:g> vienumu</item>
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> vienums</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> vienumi</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Vai izdzēst failu “<xliff:g id="NAME">%1$s</xliff:g>”?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Vai izdzēst mapi “<xliff:g id="NAME">%1$s</xliff:g>” un tās saturu?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-mk-rMK/strings.xml b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
index ad428a0..c6f58c0 100644
--- a/packages/DocumentsUI/res/values-mk-rMK/strings.xml
+++ b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Документи"</string>
- <string name="files_label" msgid="6051402950202690279">"Датотеки"</string>
<string name="downloads_label" msgid="959113951084633612">"Преземања"</string>
<string name="title_open" msgid="4353228937663917801">"Отвори од"</string>
<string name="title_save" msgid="2433679664882857999">"Зачувај во"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"Да се избрише „<xliff:g id="NAME">%1$s</xliff:g>“?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Да се избрише папката „<xliff:g id="NAME">%1$s</xliff:g>“ и нејзините содржини?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-ml-rIN/strings.xml b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
index 5a16512..5bafacd 100644
--- a/packages/DocumentsUI/res/values-ml-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"പ്രമാണങ്ങൾ"</string>
- <string name="files_label" msgid="6051402950202690279">"ഫയലുകൾ"</string>
<string name="downloads_label" msgid="959113951084633612">"ഡൗണ്ലോഡുകൾ"</string>
<string name="title_open" msgid="4353228937663917801">"ഇതിൽ നിന്നും തുറക്കുക"</string>
<string name="title_save" msgid="2433679664882857999">"ഇതില് സംരക്ഷിക്കുക"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" ഇല്ലാതാക്കണോ?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" എന്ന ഫോൾഡറും അതിലെ ഉള്ളടങ്ങളും ഇല്ലാതാക്കണോ?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-mn-rMN/strings.xml b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
index cf2c2d4..2323d23 100644
--- a/packages/DocumentsUI/res/values-mn-rMN/strings.xml
+++ b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Документүүд"</string>
- <string name="files_label" msgid="6051402950202690279">"Файл"</string>
<string name="downloads_label" msgid="959113951084633612">"Таталт"</string>
<string name="title_open" msgid="4353228937663917801">"Нээх"</string>
<string name="title_save" msgid="2433679664882857999">"Хадгалах"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\"-г устгах уу?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" фолдер болон үүний агуулгыг устгах уу?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-mr-rIN/strings.xml b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
index 09dd133..eb7dab3 100644
--- a/packages/DocumentsUI/res/values-mr-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"दस्तऐवज"</string>
- <string name="files_label" msgid="6051402950202690279">"फायली"</string>
<string name="downloads_label" msgid="959113951084633612">"डाउनलोड"</string>
<string name="title_open" msgid="4353228937663917801">"वरून उघडा"</string>
<string name="title_save" msgid="2433679664882857999">"येथे जतन करा"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" हटवायची?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" फोल्डर आणि त्यामधील सामग्री हटवायची?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-ms-rMY/strings.xml b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
index 9eb3d49..71118d8 100644
--- a/packages/DocumentsUI/res/values-ms-rMY/strings.xml
+++ b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumen"</string>
- <string name="files_label" msgid="6051402950202690279">"Fail"</string>
<string name="downloads_label" msgid="959113951084633612">"Muat turun"</string>
<string name="title_open" msgid="4353228937663917801">"Buka dari"</string>
<string name="title_save" msgid="2433679664882857999">"Simpan ke"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> item</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Padamkan \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Padamkan folder \"<xliff:g id="NAME">%1$s</xliff:g>\" dan kandungannya?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-my-rMM/strings.xml b/packages/DocumentsUI/res/values-my-rMM/strings.xml
index 7c637c4..a0b1777 100644
--- a/packages/DocumentsUI/res/values-my-rMM/strings.xml
+++ b/packages/DocumentsUI/res/values-my-rMM/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"စာရွက်စာတန်းများ"</string>
- <string name="files_label" msgid="6051402950202690279">"ဖိုင်များ"</string>
<string name="downloads_label" msgid="959113951084633612">"ဒေါင်းလုဒ်များ"</string>
<string name="title_open" msgid="4353228937663917801">"မှ ဖွင့်ပါ"</string>
<string name="title_save" msgid="2433679664882857999">"သို့ သိမ်းပါ"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" ကိုဖျက်မလား။"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" ဖိုင်တွဲနှင့် ၎င်းတွင်ပါဝင်သည့် အကြောင်းအရာများကို ဖျက်မလား။"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml
index 3c344eb..fd07c8d 100644
--- a/packages/DocumentsUI/res/values-nb/strings.xml
+++ b/packages/DocumentsUI/res/values-nb/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumenter"</string>
- <string name="files_label" msgid="6051402950202690279">"Filer"</string>
<string name="downloads_label" msgid="959113951084633612">"Nedlastinger"</string>
<string name="title_open" msgid="4353228937663917801">"Åpne fra"</string>
<string name="title_save" msgid="2433679664882857999">"Lagre i"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> varer</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> vare</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Vil du slette «<xliff:g id="NAME">%1$s</xliff:g>»?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Vil du slette «<xliff:g id="NAME">%1$s</xliff:g>»-mappen og innholdet i den?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-ne-rNP/strings.xml b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
index 9fef037..31085d5 100644
--- a/packages/DocumentsUI/res/values-ne-rNP/strings.xml
+++ b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"कागजातहरू"</string>
- <string name="files_label" msgid="6051402950202690279">"फाइलहरू"</string>
<string name="downloads_label" msgid="959113951084633612">"डाउनलोडहरू"</string>
<string name="title_open" msgid="4353228937663917801">"यसबाट खोल्नुहोस्"</string>
<string name="title_save" msgid="2433679664882857999">"यसमा सुरक्षित गर्नुहोस्"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" लाई मेट्ने हो?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"फोल्डर \"<xliff:g id="NAME">%1$s</xliff:g>\" र यसका सामग्रीहरूलाई मेट्ने हो?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-nl/strings.xml b/packages/DocumentsUI/res/values-nl/strings.xml
index c5b9d76..7b0ce93 100644
--- a/packages/DocumentsUI/res/values-nl/strings.xml
+++ b/packages/DocumentsUI/res/values-nl/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Documenten"</string>
- <string name="files_label" msgid="6051402950202690279">"Bestanden"</string>
<string name="downloads_label" msgid="959113951084633612">"Downloads"</string>
<string name="title_open" msgid="4353228937663917801">"Openen vanuit"</string>
<string name="title_save" msgid="2433679664882857999">"Opslaan in"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> items</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"<xliff:g id="NAME">%1$s</xliff:g> verwijderen?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Map <xliff:g id="NAME">%1$s</xliff:g> en de bijbehorende inhoud verwijderen?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-pa-rIN/strings.xml b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
index 7d5e14a..25e4cd6 100644
--- a/packages/DocumentsUI/res/values-pa-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"ਦਸਤਾਵੇਜ਼"</string>
- <string name="files_label" msgid="6051402950202690279">"ਫਾਈਲਾਂ"</string>
<string name="downloads_label" msgid="959113951084633612">"ਡਾਊਨਲੋਡ"</string>
<string name="title_open" msgid="4353228937663917801">"ਤੋਂ ਖੋਲ੍ਹੋ"</string>
<string name="title_save" msgid="2433679664882857999">"ਇਸ ਵਿੱਚ ਸੁਰੱਖਿਅਤ ਕਰੋ"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"ਕੀ \"<xliff:g id="NAME">%1$s</xliff:g>\" ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"ਫੋਲਡਰ \"<xliff:g id="NAME">%1$s</xliff:g>\" ਅਤੇ ਉਸ ਦੀਆਂ ਸਮੱਗਰੀਆਂ ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index ca007d7..09ca839 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumenty"</string>
- <string name="files_label" msgid="6051402950202690279">"Pliki"</string>
<string name="downloads_label" msgid="959113951084633612">"Pobrane"</string>
<string name="title_open" msgid="4353228937663917801">"Otwórz z"</string>
<string name="title_save" msgid="2433679664882857999">"Zapisz w"</string>
@@ -136,6 +135,12 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> elementy</item>
+ <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> elementów</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementu</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> element</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Usunąć „<xliff:g id="NAME">%1$s</xliff:g>”?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Usunąć folder „<xliff:g id="NAME">%1$s</xliff:g>” i jego zawartość?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-pt-rBR/strings.xml b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
index 21359c7..921be33 100644
--- a/packages/DocumentsUI/res/values-pt-rBR/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Documentos"</string>
- <string name="files_label" msgid="6051402950202690279">"Arquivos"</string>
<string name="downloads_label" msgid="959113951084633612">"Downloads"</string>
<string name="title_open" msgid="4353228937663917801">"Abrir de"</string>
<string name="title_save" msgid="2433679664882857999">"Salvar em"</string>
@@ -111,7 +110,7 @@
<string name="rename_error" msgid="4203041674883412606">"Falha ao renomear documento"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Conceder ao <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> no <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
- <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Conceder acesso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Conceder acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> para <xliff:g id="APPNAME"><b>^1</b></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso aos seus dados, incluindo fotos e vídeos, no/na <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Não perguntar novamente"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> itens</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> itens</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Excluir \" <xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Excluir pasta \"<xliff:g id="NAME">%1$s</xliff:g>\" e o respectivo conteúdo?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-pt-rPT/strings.xml b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
index aea1249..c80bdd2 100644
--- a/packages/DocumentsUI/res/values-pt-rPT/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Documentos"</string>
- <string name="files_label" msgid="6051402950202690279">"Ficheiros"</string>
<string name="downloads_label" msgid="959113951084633612">"Transferências"</string>
<string name="title_open" msgid="4353228937663917801">"Abrir de"</string>
<string name="title_save" msgid="2433679664882857999">"Guardar em"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> itens</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> item</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Pretende eliminar \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Pretende eliminar a pasta \"<xliff:g id="NAME">%1$s</xliff:g>\" e os respetivos conteúdos?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-pt/strings.xml b/packages/DocumentsUI/res/values-pt/strings.xml
index 21359c7..921be33 100644
--- a/packages/DocumentsUI/res/values-pt/strings.xml
+++ b/packages/DocumentsUI/res/values-pt/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Documentos"</string>
- <string name="files_label" msgid="6051402950202690279">"Arquivos"</string>
<string name="downloads_label" msgid="959113951084633612">"Downloads"</string>
<string name="title_open" msgid="4353228937663917801">"Abrir de"</string>
<string name="title_save" msgid="2433679664882857999">"Salvar em"</string>
@@ -111,7 +110,7 @@
<string name="rename_error" msgid="4203041674883412606">"Falha ao renomear documento"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"Conceder ao <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> no <xliff:g id="STORAGE"><i>^3</i></xliff:g>?"</string>
- <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Conceder acesso a <xliff:g id="APPNAME"><b>^1</b></xliff:g> ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g>?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"Conceder acesso ao diretório <xliff:g id="DIRECTORY"><i>^2</i></xliff:g> para <xliff:g id="APPNAME"><b>^1</b></xliff:g>?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"Conceder a <xliff:g id="APPNAME"><b>^1</b></xliff:g> acesso aos seus dados, incluindo fotos e vídeos, no/na <xliff:g id="STORAGE"><i>^2</i></xliff:g>?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"Não perguntar novamente"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> itens</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> itens</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Excluir \" <xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Excluir pasta \"<xliff:g id="NAME">%1$s</xliff:g>\" e o respectivo conteúdo?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml
index 4b833b1..ced834c 100644
--- a/packages/DocumentsUI/res/values-ro/strings.xml
+++ b/packages/DocumentsUI/res/values-ro/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Documente"</string>
- <string name="files_label" msgid="6051402950202690279">"Fișiere"</string>
<string name="downloads_label" msgid="959113951084633612">"Descărcări"</string>
<string name="title_open" msgid="4353228937663917801">"Deschideți din"</string>
<string name="title_save" msgid="2433679664882857999">"Salvați în"</string>
@@ -128,6 +127,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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> elemente</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> de elemente</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> element</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Ștergeți „<xliff:g id="NAME">%1$s</xliff:g>”?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Ștergeți dosarul „<xliff:g id="NAME">%1$s</xliff:g>” și conținutul acestuia?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml
index 6ba635d..02077cf 100644
--- a/packages/DocumentsUI/res/values-ru/strings.xml
+++ b/packages/DocumentsUI/res/values-ru/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Документы"</string>
- <string name="files_label" msgid="6051402950202690279">"Файлы"</string>
<string name="downloads_label" msgid="959113951084633612">"Загрузки"</string>
<string name="title_open" msgid="4353228937663917801">"Открыть"</string>
<string name="title_save" msgid="2433679664882857999">"Сохранить"</string>
@@ -136,6 +135,12 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Удалить файл \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Удалить папку \"<xliff:g id="NAME">%1$s</xliff:g>\" со всем содержимым?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-si-rLK/strings.xml b/packages/DocumentsUI/res/values-si-rLK/strings.xml
index 41c9d4a..d39e853 100644
--- a/packages/DocumentsUI/res/values-si-rLK/strings.xml
+++ b/packages/DocumentsUI/res/values-si-rLK/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"ලේඛන"</string>
- <string name="files_label" msgid="6051402950202690279">"ගොනු"</string>
<string name="downloads_label" msgid="959113951084633612">"බාගැනීම්"</string>
<string name="title_open" msgid="4353228937663917801">"විවෘත වන්නේ"</string>
<string name="title_save" msgid="2433679664882857999">"සුරකින්නේ"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" මකන්නද?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" ෆෝල්ඩරය හා එහි අන්තර්ගත මකන්නද?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-sk/strings.xml b/packages/DocumentsUI/res/values-sk/strings.xml
index 1ff01b0..eb59a51 100644
--- a/packages/DocumentsUI/res/values-sk/strings.xml
+++ b/packages/DocumentsUI/res/values-sk/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumenty"</string>
- <string name="files_label" msgid="6051402950202690279">"Súbory"</string>
<string name="downloads_label" msgid="959113951084633612">"Stiahnuté súbory"</string>
<string name="title_open" msgid="4353228937663917801">"Otvoriť z"</string>
<string name="title_save" msgid="2433679664882857999">"Uložiť do"</string>
@@ -136,6 +135,12 @@
<item quantity="other">Vybraté: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="one">Vybraté: <xliff:g id="COUNT_0">%1$d</xliff:g></item>
</plurals>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> položky</item>
+ <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> položky</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> položiek</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> položka</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Odstrániť <xliff:g id="NAME">%1$s</xliff:g>?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Odstrániť priečinok <xliff:g id="NAME">%1$s</xliff:g> a jeho obsah?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-sl/strings.xml b/packages/DocumentsUI/res/values-sl/strings.xml
index d8b983c..d3daabb 100644
--- a/packages/DocumentsUI/res/values-sl/strings.xml
+++ b/packages/DocumentsUI/res/values-sl/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumenti"</string>
- <string name="files_label" msgid="6051402950202690279">"Datoteke"</string>
<string name="downloads_label" msgid="959113951084633612">"Prenosi"</string>
<string name="title_open" msgid="4353228937663917801">"Odpri iz mape"</string>
<string name="title_save" msgid="2433679664882857999">"Shrani v"</string>
@@ -136,6 +135,12 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> element</item>
+ <item quantity="two"><xliff:g id="COUNT_1">%1$d</xliff:g> elementa</item>
+ <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> elementi</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementov</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Ali želite izbrisati »<xliff:g id="NAME">%1$s</xliff:g>«?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Ali želite izbrisati mapo »<xliff:g id="NAME">%1$s</xliff:g>« in njeno vsebino?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-sq-rAL/strings.xml b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
index 933a537..fe93300 100644
--- a/packages/DocumentsUI/res/values-sq-rAL/strings.xml
+++ b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumente"</string>
- <string name="files_label" msgid="6051402950202690279">"Skedarët"</string>
<string name="downloads_label" msgid="959113951084633612">"Shkarkimet"</string>
<string name="title_open" msgid="4353228937663917801">"Hap nga"</string>
<string name="title_save" msgid="2433679664882857999">"Ruaje te"</string>
@@ -120,6 +119,10 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> të zgjedhur</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> i zgjedhur</item>
</plurals>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> artikuj</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> artikull</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Të fshihet \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Të fshihet dosja \"<xliff:g id="NAME">%1$s</xliff:g>\" dhe përmbajtja e saj?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml
index 0505f42..95af81f 100644
--- a/packages/DocumentsUI/res/values-sr/strings.xml
+++ b/packages/DocumentsUI/res/values-sr/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Документи"</string>
- <string name="files_label" msgid="6051402950202690279">"Датотеке"</string>
<string name="downloads_label" msgid="959113951084633612">"Преузимања"</string>
<string name="title_open" msgid="4353228937663917801">"Отвори са"</string>
<string name="title_save" msgid="2433679664882857999">"Сачувај у"</string>
@@ -128,6 +127,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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Желите ли да избришете „<xliff:g id="NAME">%1$s</xliff:g>“?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Желите ли да избришете директоријум „<xliff:g id="NAME">%1$s</xliff:g>“ и његов садржај?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-sv/strings.xml b/packages/DocumentsUI/res/values-sv/strings.xml
index 99f334b..17dfffd 100644
--- a/packages/DocumentsUI/res/values-sv/strings.xml
+++ b/packages/DocumentsUI/res/values-sv/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokument"</string>
- <string name="files_label" msgid="6051402950202690279">"Filer"</string>
<string name="downloads_label" msgid="959113951084633612">"Nedladdningar"</string>
<string name="title_open" msgid="4353228937663917801">"Öppna från"</string>
<string name="title_save" msgid="2433679664882857999">"Spara till"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> objekt</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> objekt</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Vill du radera <xliff:g id="NAME">%1$s</xliff:g>?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Vill du radera mappen <xliff:g id="NAME">%1$s</xliff:g> och dess innehåll?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-sw/strings.xml b/packages/DocumentsUI/res/values-sw/strings.xml
index 566e6a4..cf9c8c7 100644
--- a/packages/DocumentsUI/res/values-sw/strings.xml
+++ b/packages/DocumentsUI/res/values-sw/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Hati"</string>
- <string name="files_label" msgid="6051402950202690279">"Faili"</string>
<string name="downloads_label" msgid="959113951084633612">"Vipakuliwa"</string>
<string name="title_open" msgid="4353228937663917801">"Fungua kutoka"</string>
<string name="title_save" msgid="2433679664882857999">"Hifadhi kwenye"</string>
@@ -120,6 +119,10 @@
<item quantity="other">Imechagua <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="one">Imechagua <xliff:g id="COUNT_0">%1$d</xliff:g></item>
</plurals>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other">Vipengee <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+ <item quantity="one">Kipengee <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Ungependa kufuta \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Ungependa kufuta folda ya \"<xliff:g id="NAME">%1$s</xliff:g>\" na maudhui yake?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-ta-rIN/strings.xml b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
index 9a8b4ec..d4c2f6a 100644
--- a/packages/DocumentsUI/res/values-ta-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"ஆவணங்கள்"</string>
- <string name="files_label" msgid="6051402950202690279">"கோப்புகள்"</string>
<string name="downloads_label" msgid="959113951084633612">"இறக்கங்கள்"</string>
<string name="title_open" msgid="4353228937663917801">"இதில் திற"</string>
<string name="title_save" msgid="2433679664882857999">"இதில் சேமி"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\"ஐ நீக்கவா?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" கோப்புறையையும் அதன் உள்ளடக்கத்தையும் நீக்கவா?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-te-rIN/strings.xml b/packages/DocumentsUI/res/values-te-rIN/strings.xml
index 224d0db..3a91252 100644
--- a/packages/DocumentsUI/res/values-te-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-te-rIN/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"పత్రాలు"</string>
- <string name="files_label" msgid="6051402950202690279">"ఫైల్లు"</string>
<string name="downloads_label" msgid="959113951084633612">"డౌన్లోడ్లు"</string>
<string name="title_open" msgid="4353228937663917801">"ఇక్కడి నుండి తెరువు"</string>
<string name="title_save" msgid="2433679664882857999">"ఇందులో సేవ్ చేయి"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\"ని తొలగించాలా?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" ఫోల్డర్ని మరియు అందులోని కంటెంట్లను తొలగించాలా?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-th/strings.xml b/packages/DocumentsUI/res/values-th/strings.xml
index af07584..f739eda 100644
--- a/packages/DocumentsUI/res/values-th/strings.xml
+++ b/packages/DocumentsUI/res/values-th/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"เอกสาร"</string>
- <string name="files_label" msgid="6051402950202690279">"ไฟล์"</string>
<string name="downloads_label" msgid="959113951084633612">"การดาวน์โหลด"</string>
<string name="title_open" msgid="4353228937663917801">"เปิดจาก"</string>
<string name="title_save" msgid="2433679664882857999">"บันทึกไปยัง"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"ลบ \"<xliff:g id="NAME">%1$s</xliff:g>\" ไหม"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"ลบโฟลเดอร์ \"<xliff:g id="NAME">%1$s</xliff:g>\" และเนื้อหาข้างในไหม"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-tl/strings.xml b/packages/DocumentsUI/res/values-tl/strings.xml
index b2acf05..3474be8 100644
--- a/packages/DocumentsUI/res/values-tl/strings.xml
+++ b/packages/DocumentsUI/res/values-tl/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Mga Dokumento"</string>
- <string name="files_label" msgid="6051402950202690279">"Mga File"</string>
<string name="downloads_label" msgid="959113951084633612">"Mga Download"</string>
<string name="title_open" msgid="4353228937663917801">"Buksan mula sa"</string>
<string name="title_save" msgid="2433679664882857999">"I-save sa"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> item</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> na item</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Gusto mo bang i-delete ang \"<xliff:g id="NAME">%1$s</xliff:g>?\""</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Gusto mo bang i-delete ang folder na \"<xliff:g id="NAME">%1$s</xliff:g>\" at ang mga content nito?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-tr/strings.xml b/packages/DocumentsUI/res/values-tr/strings.xml
index c5653c9..b685568 100644
--- a/packages/DocumentsUI/res/values-tr/strings.xml
+++ b/packages/DocumentsUI/res/values-tr/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokümanlar"</string>
- <string name="files_label" msgid="6051402950202690279">"Dosyalar"</string>
<string name="downloads_label" msgid="959113951084633612">"İndirilenler"</string>
<string name="title_open" msgid="4353228937663917801">"Şuradan aç:"</string>
<string name="title_save" msgid="2433679664882857999">"Şuraya kaydet:"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> öğe</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> öğe</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" silinsin mi?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" adlı klasör ve içindekiler silinsin mi?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-uk/strings.xml b/packages/DocumentsUI/res/values-uk/strings.xml
index 21532b6..b255459 100644
--- a/packages/DocumentsUI/res/values-uk/strings.xml
+++ b/packages/DocumentsUI/res/values-uk/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Документи"</string>
- <string name="files_label" msgid="6051402950202690279">"Файли"</string>
<string name="downloads_label" msgid="959113951084633612">"Завантаження"</string>
<string name="title_open" msgid="4353228937663917801">"Відкрити"</string>
<string name="title_save" msgid="2433679664882857999">"Зберегти в"</string>
@@ -136,6 +135,12 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Видалити файл <xliff:g id="NAME">%1$s</xliff:g>?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Видалити папку \"<xliff:g id="NAME">%1$s</xliff:g>\" та її вміст?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-ur-rPK/strings.xml b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
index eb0cfc8..8d85a2b 100644
--- a/packages/DocumentsUI/res/values-ur-rPK/strings.xml
+++ b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"دستاویزات"</string>
- <string name="files_label" msgid="6051402950202690279">"فائلیں"</string>
<string name="downloads_label" msgid="959113951084633612">"ڈاؤن لوڈز"</string>
<string name="title_open" msgid="4353228937663917801">"کھولیں از"</string>
<string name="title_save" msgid="2433679664882857999">"اس میں محفوظ کریں"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" حذف کریں؟"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" فولڈر اور اس کی مشمولات حذف کریں؟"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
index 2654308..76e82da 100644
--- a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
+++ b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Hujjatlar"</string>
- <string name="files_label" msgid="6051402950202690279">"Fayllar"</string>
<string name="downloads_label" msgid="959113951084633612">"Yuklanishlar"</string>
<string name="title_open" msgid="4353228937663917801">"Ochish"</string>
<string name="title_save" msgid="2433679664882857999">"Saqlash"</string>
@@ -120,6 +119,10 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ta belgilandi</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta belgilandi</item>
</plurals>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ta element</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta element</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"“<xliff:g id="NAME">%1$s</xliff:g>” fayli o‘chirib tashlansinmi?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"“<xliff:g id="NAME">%1$s</xliff:g>” jildi ichidagi kontentlari bilan o‘chirib tashlansinmi?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-vi/strings.xml b/packages/DocumentsUI/res/values-vi/strings.xml
index 9af7db0..9e69e0f 100644
--- a/packages/DocumentsUI/res/values-vi/strings.xml
+++ b/packages/DocumentsUI/res/values-vi/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Tài liệu"</string>
- <string name="files_label" msgid="6051402950202690279">"Tệp"</string>
<string name="downloads_label" msgid="959113951084633612">"Tài nguyên đã tải xuống"</string>
<string name="title_open" msgid="4353228937663917801">"Mở từ"</string>
<string name="title_save" msgid="2433679664882857999">"Lưu vào"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> mục</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> mục</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Xóa \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Xóa thư mục \"<xliff:g id="NAME">%1$s</xliff:g>\" và nội dung của thư mục?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
index e3db1a0..00e4c91 100644
--- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"文档"</string>
- <string name="files_label" msgid="6051402950202690279">"文件"</string>
<string name="downloads_label" msgid="959113951084633612">"下载"</string>
<string name="title_open" msgid="4353228937663917801">"打开文件"</string>
<string name="title_save" msgid="2433679664882857999">"保存文件"</string>
@@ -111,7 +110,7 @@
<string name="rename_error" msgid="4203041674883412606">"无法重命名文档"</string>
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分文件已转换成其他格式"</string>
<string name="open_external_dialog_request" msgid="5789329484285817629">"要授权<xliff:g id="APPNAME"><b>^1</b></xliff:g>访问 <xliff:g id="STORAGE"><i>^3</i></xliff:g>上的“<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>”目录吗?"</string>
- <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"要授权<xliff:g id="APPNAME"><b>^1</b></xliff:g>访问<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>目录吗?"</string>
+ <string name="open_external_dialog_request_primary_volume" msgid="6635562535713428688">"要授权<xliff:g id="APPNAME"><b>^1</b></xliff:g>访问“<xliff:g id="DIRECTORY"><i>^2</i></xliff:g>”目录吗?"</string>
<string name="open_external_dialog_root_request" msgid="8899108702926347720">"要授权<xliff:g id="APPNAME"><b>^1</b></xliff:g>访问您 <xliff:g id="STORAGE"><i>^2</i></xliff:g>上的数据(包括照片和视频)吗?"</string>
<string name="never_ask_again" msgid="4295278542972859268">"不再询问"</string>
<string name="allow" msgid="7225948811296386551">"允许"</string>
@@ -120,6 +119,7 @@
<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>
+ <!-- no translation found for elements_dragged (3727204615215602228) -->
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"要删除“<xliff:g id="NAME">%1$s</xliff:g>”吗?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"要删除文件夹“<xliff:g id="NAME">%1$s</xliff:g>”及其中的内容吗?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
index f13a4bd1..4b0f4e2 100644
--- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"文件"</string>
- <string name="files_label" msgid="6051402950202690279">"檔案"</string>
<string name="downloads_label" msgid="959113951084633612">"下載"</string>
<string name="title_open" msgid="4353228937663917801">"開啟檔案"</string>
<string name="title_save" msgid="2433679664882857999">"儲存至"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"要刪除「<xliff:g id="NAME">%1$s</xliff:g>」嗎?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"要刪除「<xliff:g id="NAME">%1$s</xliff:g>」資料夾及其內容嗎?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
index f8f8282..07c5c2a 100644
--- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"文件"</string>
- <string name="files_label" msgid="6051402950202690279">"檔案"</string>
<string name="downloads_label" msgid="959113951084633612">"下載內容"</string>
<string name="title_open" msgid="4353228937663917801">"開啟檔案"</string>
<string name="title_save" msgid="2433679664882857999">"儲存至"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <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="delete_filename_confirmation_message" msgid="5312817725577537488">"要刪除「<xliff:g id="NAME">%1$s</xliff:g>」嗎?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"要刪除「<xliff:g id="NAME">%1$s</xliff:g>」資料夾和當中的內容嗎?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values-zu/strings.xml b/packages/DocumentsUI/res/values-zu/strings.xml
index a0b9f7f..095d275 100644
--- a/packages/DocumentsUI/res/values-zu/strings.xml
+++ b/packages/DocumentsUI/res/values-zu/strings.xml
@@ -17,7 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Amadokhumenti"</string>
- <string name="files_label" msgid="6051402950202690279">"Amafayela"</string>
<string name="downloads_label" msgid="959113951084633612">"Okulandiwe"</string>
<string name="title_open" msgid="4353228937663917801">"Vula kusuka ku-"</string>
<string name="title_save" msgid="2433679664882857999">"Londoloza ku-"</string>
@@ -120,6 +119,10 @@
<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>
+ <plurals name="elements_dragged" formatted="false" msgid="3727204615215602228">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> izinto</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> izinto</item>
+ </plurals>
<string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Susa i-\"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
<string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Susa ifolda engu-\"<xliff:g id="NAME">%1$s</xliff:g>\" nokuqukethwe kwalo?"</string>
<plurals name="delete_files_confirmation_message" formatted="false" msgid="8417505791395471802">
diff --git a/packages/DocumentsUI/res/values/colors.xml b/packages/DocumentsUI/res/values/colors.xml
index 1660e26..cf0643d 100644
--- a/packages/DocumentsUI/res/values/colors.xml
+++ b/packages/DocumentsUI/res/values/colors.xml
@@ -31,6 +31,7 @@
<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="status_bar_color">@*android:color/material_blue_grey_950</color>
<color name="band_select_background">#88ffffff</color>
<color name="band_select_border">#44000000</color>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index b0996aa..9f09ebc 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -30,6 +30,7 @@
<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:statusBarColor">@color/status_bar_color</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 0d6ddf2..3b0be57 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -101,16 +101,6 @@
@CallSuper
@Override
public void onCreate(Bundle icicle) {
- // This flag is being set here as a result of the bug. When the flag was set in the
- // styles.xml keyboard was messing the layout of dialogs (create dir, rename).
- // Attempts were made to keep the flag in the main theme and to override it in the dialog
- // layout xml or to create separate style for dialog and assign it in styles.xml.
- // None of this brought successful results.
- // Setting the flag works here most probably because of the timing when it is set. Also the
- // setting might not affect the dialogs that are created in new windows or it affects them
- // in the different way that having this in the style.
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
-
// Record the time when onCreate is invoked for metric.
mStartTime = new Date().getTime();
@@ -140,7 +130,6 @@
mSearchManager = new SearchViewManager(this, icicle);
DocumentsToolbar toolbar = (DocumentsToolbar) findViewById(R.id.toolbar);
- Display.adjustToolbar(toolbar, this);
setActionBar(toolbar);
mNavigator = new NavigationView(
mDrawer,
@@ -268,7 +257,6 @@
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- Metrics.logMenuAction(this, item.getItemId());
switch (item.getItemId()) {
case android.R.id.home:
@@ -290,6 +278,7 @@
case R.id.menu_sort_date:
setUserSortOrder(State.SORT_ORDER_LAST_MODIFIED);
return true;
+
case R.id.menu_sort_size:
setUserSortOrder(State.SORT_ORDER_SIZE);
return true;
@@ -318,6 +307,8 @@
return true;
case R.id.menu_settings:
+ Metrics.logUserAction(this, Metrics.USER_ACTION_SETTINGS);
+
final RootInfo root = getCurrentRoot();
final Intent intent = new Intent(DocumentsContract.ACTION_DOCUMENT_ROOT_SETTINGS);
intent.setDataAndType(root.getUri(), DocumentsContract.Root.MIME_TYPE_ITEM);
@@ -334,6 +325,8 @@
}
void showCreateDirectoryDialog() {
+ Metrics.logUserAction(this, Metrics.USER_ACTION_CREATE_DIR);
+
CreateDirectoryFragment.show(getFragmentManager());
}
@@ -480,13 +473,25 @@
"com.android.providers.downloads.documents", "downloads");
}
+ /**
+ * Set internal storage visible based on explicit user action.
+ */
void setDisplayAdvancedDevices(boolean display) {
+ Metrics.logUserAction(this,
+ display ? Metrics.USER_ACTION_SHOW_ADVANCED : Metrics.USER_ACTION_HIDE_ADVANCED);
+
mState.showAdvanced = display;
RootsFragment.get(getFragmentManager()).onDisplayStateChanged();
invalidateOptionsMenu();
}
+ /**
+ * Set file size visible based on explicit user action.
+ */
void setDisplayFileSize(boolean display) {
+ Metrics.logUserAction(this,
+ display ? Metrics.USER_ACTION_SHOW_SIZE : Metrics.USER_ACTION_HIDE_SIZE);
+
LocalPreferences.setDisplayFileSize(this, display);
mState.showSize = display;
DirectoryFragment dir = getDirectoryFragment();
@@ -500,6 +505,18 @@
* Set state sort order based on explicit user action.
*/
void setUserSortOrder(int sortOrder) {
+ switch(sortOrder) {
+ case State.SORT_ORDER_DISPLAY_NAME:
+ Metrics.logUserAction(this, Metrics.USER_ACTION_SORT_NAME);
+ break;
+ case State.SORT_ORDER_LAST_MODIFIED:
+ Metrics.logUserAction(this, Metrics.USER_ACTION_SORT_DATE);
+ break;
+ case State.SORT_ORDER_SIZE:
+ Metrics.logUserAction(this, Metrics.USER_ACTION_SORT_SIZE);
+ break;
+ }
+
mState.userSortOrder = sortOrder;
DirectoryFragment dir = getDirectoryFragment();
if (dir != null) {
@@ -511,6 +528,12 @@
* Set mode based on explicit user action.
*/
void setViewMode(@ViewMode int mode) {
+ if (mode == State.MODE_GRID) {
+ Metrics.logUserAction(this, Metrics.USER_ACTION_GRID);
+ } else if (mode == State.MODE_LIST) {
+ Metrics.logUserAction(this, Metrics.USER_ACTION_LIST);
+ }
+
LocalPreferences.setViewMode(this, getCurrentRoot(), mode);
mState.derivedMode = mode;
@@ -632,12 +655,10 @@
return true;
}
} else if (keyCode == KeyEvent.KEYCODE_TAB) {
- Metrics.logKeyboardAction(this, Metrics.ACTION_KEYBOARD_SWITCH_FOCUS);
// Tab toggles focus on the navigation drawer.
toggleNavDrawerFocus();
return true;
} else if (keyCode == KeyEvent.KEYCODE_DEL) {
- Metrics.logKeyboardAction(this, Metrics.ACTION_KEYBOARD_BACK);
popDir();
return true;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Display.java b/packages/DocumentsUI/src/com/android/documentsui/Display.java
index d46a3ea..8b13222 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Display.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Display.java
@@ -20,8 +20,6 @@
import android.content.Context;
import android.graphics.Point;
import android.util.TypedValue;
-import android.view.WindowManager;
-import android.widget.Toolbar;
/*
* Convenience class for getting display related attributes
@@ -47,41 +45,12 @@
* Returns action bar height in raw pixels.
*/
public static float actionBarHeight(Context context) {
- int height = 0;
+ int actionBarHeight = 0;
TypedValue tv = new TypedValue();
if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
- height = TypedValue.complexToDimensionPixelSize(tv.data,
+ actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,
context.getResources().getDisplayMetrics());
}
- return height;
- }
-
- /*
- * Returns status bar height in raw pixels.
- */
- private static int statusBarHeight(Context context) {
- int height = 0;
- int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen",
- "android");
- if (resourceId > 0) {
- height = context.getResources().getDimensionPixelSize(resourceId);
- }
- return height;
- }
-
- /*
- * Adjusts toolbar for the layout with translucent status bar. Increases the
- * height of the toolbar and adds padding at the top to accommodate status bar visible above
- * toolbar.
- */
- public static void adjustToolbar(Toolbar toolbar, Activity activity) {
- if ((activity.getWindow().getAttributes().flags
- & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) != 0) {
- int statusBarHeight = Display.statusBarHeight(activity);
- toolbar.getLayoutParams().height = (int) (Display.actionBarHeight(activity)
- + statusBarHeight);
- toolbar.setPadding(toolbar.getPaddingLeft(), statusBarHeight, toolbar.getPaddingRight(),
- toolbar.getPaddingBottom());
- }
+ return actionBarHeight;
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
index 7a4099a..14e6b69 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
@@ -84,7 +84,7 @@
View drawer = activity.findViewById(R.id.drawer_roots);
Toolbar toolbar = (Toolbar) activity.findViewById(R.id.roots_toolbar);
- Display.adjustToolbar(toolbar, activity);
+
drawer.getLayoutParams().width = calculateDrawerWidth(activity);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 527eb78..84fc6fe 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -98,7 +98,7 @@
assert(uri == null || uri.getAuthority() == null ||
LauncherActivity.isLaunchUri(uri));
refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE);
- } else if (intent.getAction() == Intent.ACTION_VIEW) {
+ } else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
assert(uri != null);
new OpenUriForViewTask(this).executeOnExecutor(
ProviderExecutor.forAuthority(uri.getAuthority()), uri);
@@ -228,13 +228,12 @@
default:
return super.onOptionsItemSelected(item);
}
-
- Metrics.logMenuAction(this, item.getItemId());
return true;
}
private void createNewWindow() {
- Metrics.logMultiWindow(this);
+ Metrics.logUserAction(this, Metrics.USER_ACTION_NEW_WINDOW);
+
Intent intent = LauncherActivity.createLaunchIntent(this);
intent.putExtra(Shared.EXTRA_STACK, (Parcelable) mState.stack);
@@ -277,18 +276,6 @@
@Override
public void onDocumentPicked(DocumentInfo doc, Model model) {
- if (doc.isContainer()) {
- openContainerDocument(doc);
- } else {
- openDocument(doc, model);
- }
- }
-
- /**
- * Launches an intent to view the specified document.
- */
- private void openDocument(DocumentInfo doc, Model model) {
-
// Anything on downloads goes through the back through downloads manager
// (that's the MANAGE_DOCUMENT bit).
// This is done for two reasons:
@@ -298,7 +285,13 @@
// like origin URL.
// All other files not on downloads, event APKs, would get no benefit from this
// treatment, thusly the "isDownloads" check.
- if (getCurrentRoot().isDownloads()) {
+
+ // Launch MANAGE_DOCUMENTS only for the root level files, so it's not called for
+ // files in archives. Also, if the activity is already browsing a ZIP from downloads,
+ // then skip MANAGE_DOCUMENTS.
+ final boolean isViewing = Intent.ACTION_VIEW.equals(getIntent().getAction());
+ final boolean isInArchive = mState.stack.size() > 1;
+ if (getCurrentRoot().isDownloads() && !isInArchive && !isViewing) {
// 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);
@@ -312,6 +305,17 @@
}
}
+ if (doc.isContainer()) {
+ openContainerDocument(doc);
+ } else {
+ openDocument(doc, model);
+ }
+ }
+
+ /**
+ * Launches an intent to view the specified document.
+ */
+ private void openDocument(DocumentInfo doc, Model model) {
Intent intent = new QuickViewIntentBuilder(
getPackageManager(), getResources(), doc, model).build();
@@ -352,21 +356,18 @@
case KeyEvent.KEYCODE_A:
dir = getDirectoryFragment();
if (dir != null) {
- Metrics.logKeyboardAction(this, Metrics.ACTION_KEYBOARD_SELECT_ALL);
dir.selectAllFiles();
}
return true;
case KeyEvent.KEYCODE_C:
dir = getDirectoryFragment();
if (dir != null) {
- Metrics.logKeyboardAction(this, Metrics.ACTION_KEYBOARD_COPY);
dir.copySelectedToClipboard();
}
return true;
case KeyEvent.KEYCODE_V:
dir = getDirectoryFragment();
if (dir != null) {
- Metrics.logKeyboardAction(this, Metrics.ACTION_KEYBOARD_PASTE);
dir.pasteFromClipboard();
}
return true;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
index 05cc7e6..69a6e1f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
@@ -62,16 +62,13 @@
private static final String COUNT_GET_CONTENT_MIME = "docsui_get_content_mime";
private static final String COUNT_BROWSE_ROOT = "docsui_browse_root";
@Deprecated private static final String COUNT_MANAGE_ROOT = "docsui_manage_root";
- private static final String COUNT_MULTI_WINDOW = "docsui_multi_window";
+ @Deprecated private static final String COUNT_MULTI_WINDOW = "docsui_multi_window";
private static final String COUNT_FILEOP_SYSTEM = "docsui_fileop_system";
private static final String COUNT_FILEOP_EXTERNAL = "docsui_fileop_external";
private static final String COUNT_FILEOP_CANCELED = "docsui_fileop_canceled";
private static final String COUNT_STARTUP_MS = "docsui_startup_ms";
private static final String COUNT_DRAWER_OPENED = "docsui_drawer_opened";
- private static final String COUNT_DRAG_N_DROP = "docsui_drag_n_drop";
- private static final String COUNT_SEARCH = "docsui_search";
- private static final String COUNT_MENU_ACTION = "docsui_menu_action";
- private static final String COUNT_KEYBOARD_ACTION = "docsui_keyboard_action";
+ private static final String COUNT_USER_ACTION = "docsui_menu_action";
// 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
@@ -215,54 +212,67 @@
public @interface Provider {}
- // Codes representing different menu actions. These are used for bucketing stats in the
- // COUNT_MENU_ACTION histogram.
- // Both regular toolbar menu and action mode menu operations are included.
+ // Codes representing different user actions. These are used for bucketing stats in the
+ // COUNT_USER_ACTION histogram.
+ // The historgram includes action triggered from menu or invoked by keyboard shortcut.
// 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_MENU_OTHER = 1;
- private static final int ACTION_MENU_GRID = 2;
- private static final int ACTION_MENU_LIST = 3;
- private static final int ACTION_MENU_SORT = 4;
- private static final int ACTION_MENU_SORT_NAME = 5;
- private static final int ACTION_MENU_SORT_DATE = 6;
- private static final int ACTION_MENU_SORT_SIZE = 7;
- private static final int ACTION_MENU_SEARCH = 8;
- private static final int ACTION_MENU_SHOW_SIZE = 9;
- private static final int ACTION_MENU_SETTINGS = 10;
- private static final int ACTION_MENU_COPY_TO = 11;
- private static final int ACTION_MENU_MOVE_TO = 12;
- private static final int ACTION_MENU_DELETE = 13;
- private static final int ACTION_MENU_RENAME = 14;
- private static final int ACTION_MENU_CREATE_DIR = 15;
- private static final int ACTION_MENU_SELECT_ALL = 16;
- private static final int ACTION_MENU_SHARE = 17;
- private static final int ACTION_MENU_OPEN = 18;
- private static final int ACTION_MENU_ADVANCED = 19;
+ public static final int USER_ACTION_OTHER = 1;
+ public static final int USER_ACTION_GRID = 2;
+ public static final int USER_ACTION_LIST = 3;
+ public static final int USER_ACTION_SORT_NAME = 4;
+ public static final int USER_ACTION_SORT_DATE = 5;
+ public static final int USER_ACTION_SORT_SIZE = 6;
+ public static final int USER_ACTION_SEARCH = 7;
+ public static final int USER_ACTION_SHOW_SIZE = 8;
+ public static final int USER_ACTION_HIDE_SIZE = 9;
+ public static final int USER_ACTION_SETTINGS = 10;
+ public static final int USER_ACTION_COPY_TO = 11;
+ public static final int USER_ACTION_MOVE_TO = 12;
+ public static final int USER_ACTION_DELETE = 13;
+ public static final int USER_ACTION_RENAME = 14;
+ public static final int USER_ACTION_CREATE_DIR = 15;
+ public static final int USER_ACTION_SELECT_ALL = 16;
+ public static final int USER_ACTION_SHARE = 17;
+ public static final int USER_ACTION_OPEN = 18;
+ public static final int USER_ACTION_SHOW_ADVANCED = 19;
+ public static final int USER_ACTION_HIDE_ADVANCED = 20;
+ public static final int USER_ACTION_NEW_WINDOW = 21;
+ public static final int USER_ACTION_PASTE_CLIPBOARD = 22;
+ public static final int USER_ACTION_COPY_CLIPBOARD = 23;
+ public static final int USER_ACTION_DRAG_N_DROP = 24;
+ public static final int USER_ACTION_DRAG_N_DROP_MULTI_WINDOW = 25;
@IntDef(flag = false, value = {
- ACTION_MENU_OTHER,
- ACTION_MENU_GRID,
- ACTION_MENU_LIST,
- ACTION_MENU_SORT,
- ACTION_MENU_SORT_NAME,
- ACTION_MENU_SORT_DATE,
- ACTION_MENU_SORT_SIZE,
- ACTION_MENU_SHOW_SIZE,
- ACTION_MENU_SETTINGS,
- ACTION_MENU_COPY_TO,
- ACTION_MENU_MOVE_TO,
- ACTION_MENU_DELETE,
- ACTION_MENU_RENAME,
- ACTION_MENU_CREATE_DIR,
- ACTION_MENU_SELECT_ALL,
- ACTION_MENU_SHARE,
- ACTION_MENU_OPEN,
- ACTION_MENU_ADVANCED
+ USER_ACTION_OTHER,
+ USER_ACTION_GRID,
+ USER_ACTION_LIST,
+ USER_ACTION_SORT_NAME,
+ USER_ACTION_SORT_DATE,
+ USER_ACTION_SORT_SIZE,
+ USER_ACTION_SEARCH,
+ USER_ACTION_SHOW_SIZE,
+ USER_ACTION_HIDE_SIZE,
+ USER_ACTION_SETTINGS,
+ USER_ACTION_COPY_TO,
+ USER_ACTION_MOVE_TO,
+ USER_ACTION_DELETE,
+ USER_ACTION_RENAME,
+ USER_ACTION_CREATE_DIR,
+ USER_ACTION_SELECT_ALL,
+ USER_ACTION_SHARE,
+ USER_ACTION_OPEN,
+ USER_ACTION_SHOW_ADVANCED,
+ USER_ACTION_HIDE_ADVANCED,
+ USER_ACTION_NEW_WINDOW,
+ USER_ACTION_PASTE_CLIPBOARD,
+ USER_ACTION_COPY_CLIPBOARD,
+ USER_ACTION_DRAG_N_DROP,
+ USER_ACTION_DRAG_N_DROP_MULTI_WINDOW
})
@Retention(RetentionPolicy.SOURCE)
- public @interface MenuAction {}
+ public @interface UserAction {}
// Codes representing different menu actions. These are used for bucketing stats in the
// COUNT_MENU_ACTION histogram.
@@ -291,31 +301,6 @@
@Retention(RetentionPolicy.SOURCE)
public @interface MetricsAction {}
- // Codes representing different keyboard shortcut triggered actions. These are used for
- // bucketing stats in the COUNT_KEYBOARD_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.
- public static final int ACTION_KEYBOARD_OTHER = 1;
- public static final int ACTION_KEYBOARD_PASTE = 2;
- public static final int ACTION_KEYBOARD_COPY = 3;
- public static final int ACTION_KEYBOARD_DELETE = 4;
- public static final int ACTION_KEYBOARD_SELECT_ALL = 5;
- public static final int ACTION_KEYBOARD_BACK = 6;
- public static final int ACTION_KEYBOARD_SWITCH_FOCUS = 7;
-
- @IntDef(flag = false, value = {
- ACTION_KEYBOARD_OTHER,
- ACTION_KEYBOARD_PASTE,
- ACTION_KEYBOARD_COPY,
- ACTION_KEYBOARD_DELETE,
- ACTION_KEYBOARD_SELECT_ALL,
- ACTION_KEYBOARD_BACK,
- ACTION_KEYBOARD_SWITCH_FOCUS
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface KeyboardAction {}
-
// Codes representing different actions to open the drawer. They are used for bucketing stats in
// the COUNT_DRAWER_OPENED histogram.
// Do not change or rearrange these values, that will break historical data. Only add to the
@@ -382,15 +367,6 @@
}
/**
- * Logs a multi-window start. Call this when the user spawns a new DocumentsUI window.
- *
- * @param context
- */
- public static void logMultiWindow(Context context) {
- logCount(context, COUNT_MULTI_WINDOW);
- }
-
- /**
* Logs a drawer opened event. Call this when the user opens drawer by swipe or by clicking the
* hamburger icon.
* @param context
@@ -496,7 +472,7 @@
* @param context
*/
public static void logCreateDirError(Context context) {
- logHistogram(context, COUNT_FILEOP_SYSTEM, FILEOP_CREATE_DIR);
+ logHistogram(context, COUNT_FILEOP_SYSTEM, FILEOP_CREATE_DIR_ERROR);
}
/**
@@ -520,16 +496,6 @@
}
/**
- * Logs keyboard shortcut actions. Since keyboard shortcuts have their corresponding menu items,
- * they are identified by menu item resource id for convenience.
- * @param context
- * @param keyCode
- */
- public static void logKeyboardAction(Context context, @KeyboardAction int action) {
- logHistogram(context, COUNT_KEYBOARD_ACTION, action);
- }
-
- /**
* Logs startup time in milliseconds.
* @param context
* @param startupMs Startup time in milliseconds.
@@ -538,25 +504,6 @@
logHistogram(context, COUNT_STARTUP_MS, startupMs);
}
- /**
- * Logs a drag and drop action. Call this when the user drops the content triggering copy.
- * operation.
- *
- * @param context
- */
- public static void logDragNDrop(Context context) {
- logCount(context, COUNT_DRAG_N_DROP);
- }
-
- /**
- * Logs a search. Call this when the search operation is finished.
- *
- * @param context
- */
- public static void logSearch(Context context) {
- logCount(context, COUNT_SEARCH);
- }
-
private static void logInterProviderFileOps(
Context context,
String histogram,
@@ -677,71 +624,12 @@
}
/**
- * Logs menu action that was selected by user.
+ * Logs the action that was started by user.
* @param context
- * @param id Resource id of the menu item.
+ * @param userAction
*/
- public static void logMenuAction(Context context, int id) {
- @MenuAction int menuAction = ACTION_MENU_OTHER;
- switch (id) {
- case R.id.menu_grid:
- menuAction = ACTION_MENU_GRID;
- break;
- case R.id.menu_list:
- menuAction = ACTION_MENU_LIST;
- break;
- case R.id.menu_sort:
- menuAction = ACTION_MENU_SORT;
- break;
- case R.id.menu_sort_name:
- menuAction = ACTION_MENU_SORT_NAME;
- break;
- case R.id.menu_sort_date:
- menuAction = ACTION_MENU_SORT_DATE;
- break;
- case R.id.menu_sort_size:
- menuAction = ACTION_MENU_SORT_SIZE;
- break;
- case R.id.menu_search:
- menuAction = ACTION_MENU_SEARCH;
- break;
- case R.id.menu_file_size:
- menuAction = ACTION_MENU_SHOW_SIZE;
- break;
- case R.id.menu_settings:
- menuAction = ACTION_MENU_SETTINGS;
- break;
- case R.id.menu_copy_to:
- menuAction = ACTION_MENU_COPY_TO;
- break;
- case R.id.menu_move_to:
- menuAction = ACTION_MENU_MOVE_TO;
- break;
- case R.id.menu_delete:
- menuAction = ACTION_MENU_DELETE;
- break;
- case R.id.menu_rename:
- menuAction = ACTION_MENU_RENAME;
- break;
- case R.id.menu_create_dir:
- menuAction = ACTION_MENU_CREATE_DIR;
- break;
- case R.id.menu_select_all:
- menuAction = ACTION_MENU_SELECT_ALL;
- break;
- case R.id.menu_share:
- menuAction = ACTION_MENU_SHARE;
- break;
- case R.id.menu_open:
- menuAction = ACTION_MENU_OPEN;
- break;
- case R.id.menu_advanced:
- menuAction = ACTION_MENU_ADVANCED;
- break;
- default:
- break;
- }
- logHistogram(context, COUNT_MENU_ACTION, menuAction);
+ public static void logUserAction(Context context, @UserAction int userAction) {
+ logHistogram(context, COUNT_USER_ACTION, userAction);
}
/**
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java b/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
index 945ed34..11b8891 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
@@ -185,9 +185,6 @@
if(mFullBar) {
Menu menu = mActionBar.getMenu();
menu.setGroupVisible(R.id.group_hide_when_searching, false);
- } else {
- // If search in full-bar mode it will be logged in FilesActivity#onOptionsItemSelected
- Metrics.logMenuAction(mActionBar.getContext(), R.id.menu_search);
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/State.java b/packages/DocumentsUI/src/com/android/documentsui/State.java
index c7d60e3..f239eb4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/State.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/State.java
@@ -123,9 +123,6 @@
/** Instance state for every shown directory */
public HashMap<String, SparseArray<Parcelable>> dirState = new HashMap<>();
- /** UI selection */
- public Selection selectedDocuments = new Selection();
-
/** Currently copying file */
public List<DocumentInfo> selectedDocumentsForCopy = new ArrayList<>();
@@ -202,7 +199,6 @@
out.writeInt(external ? 1 : 0);
DurableUtils.writeToParcel(out, stack);
out.writeMap(dirState);
- out.writeParcelable(selectedDocuments, 0);
out.writeList(selectedDocumentsForCopy);
out.writeList(excludedAuthorities);
out.writeInt(openableOnly ? 1 : 0);
@@ -233,7 +229,6 @@
state.external = in.readInt() != 0;
DurableUtils.readFromParcel(in, state.stack);
in.readMap(state.dirState, loader);
- state.selectedDocuments = in.readParcelable(loader);
in.readList(state.selectedDocumentsForCopy, loader);
in.readList(state.excludedAuthorities, loader);
state.openableOnly = in.readInt() != 0;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 630f359..bc2133e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -45,6 +45,7 @@
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Parcel;
import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
@@ -226,7 +227,8 @@
mStateKey = buildStateKey(mRoot, mDocument);
mQuery = args.getString(Shared.EXTRA_QUERY);
mType = args.getInt(Shared.EXTRA_TYPE);
- mSelection = args.getParcelable(Shared.EXTRA_SELECTION);
+ final Selection selection = args.getParcelable(Shared.EXTRA_SELECTION);
+ mSelection = selection != null ? selection : new Selection();
mSearchMode = args.getBoolean(Shared.EXTRA_SEARCH_MODE);
mIconHelper = new IconHelper(context, MODE_GRID);
@@ -290,14 +292,25 @@
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);
+ // Workaround. To avoid crash, write only up to 512 KB of selection.
+ // If more files are selected, then the selection will be lost.
+ final Parcel parcel = Parcel.obtain();
+ try {
+ mSelection.writeToParcel(parcel, 0);
+ if (parcel.dataSize() <= 512 * 1024) {
+ outState.putParcelable(Shared.EXTRA_SELECTION, mSelection);
+ }
+ } finally {
+ parcel.recycle();
+ }
+
+ outState.putBoolean(Shared.EXTRA_SEARCH_MODE, mSearchMode);
}
@Override
public void onActivityResult(@RequestCode int requestCode, int resultCode, Intent data) {
- switch(requestCode) {
+ switch (requestCode) {
case REQUEST_COPY_DESTINATION:
handleCopyResult(resultCode, data);
break;
@@ -490,24 +503,19 @@
@Override
public void onSelectionChanged() {
mSelectionManager.getSelection(mSelected);
- TypedValue color = new TypedValue();
if (mSelected.size() > 0) {
if (DEBUG) Log.d(TAG, "Maybe starting action mode.");
if (mActionMode == null) {
if (DEBUG) Log.d(TAG, "Yeah. Starting action mode.");
mActionMode = getActivity().startActionMode(this);
}
- getActivity().getTheme().resolveAttribute(R.attr.colorActionMode, color, true);
updateActionMenu();
} else {
if (DEBUG) Log.d(TAG, "Finishing action mode.");
if (mActionMode != null) {
mActionMode.finish();
}
- getActivity().getTheme().resolveAttribute(
- android.R.attr.colorPrimaryDark, color, true);
}
- getActivity().getWindow().setStatusBarColor(color.data);
if (mActionMode != null) {
final String title = Shared.getQuantityString(getActivity(),
@@ -597,8 +605,6 @@
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- Metrics.logMenuAction(getContext(), item.getItemId());
-
Selection selection = mSelectionManager.getSelection(new Selection());
switch (item.getItemId()) {
@@ -666,6 +672,8 @@
}
private void openDocuments(final Selection selected) {
+ Metrics.logUserAction(getContext(), Metrics.USER_ACTION_OPEN);
+
new GetDocumentsTask() {
@Override
void onDocumentsReady(List<DocumentInfo> docs) {
@@ -676,6 +684,8 @@
}
private void shareDocuments(final Selection selected) {
+ Metrics.logUserAction(getContext(), Metrics.USER_ACTION_SHARE);
+
new GetDocumentsTask() {
@Override
void onDocumentsReady(List<DocumentInfo> docs) {
@@ -757,6 +767,8 @@
}
private void deleteDocuments(final Selection selected) {
+ Metrics.logUserAction(getContext(), Metrics.USER_ACTION_DELETE);
+
assert(!selected.isEmpty());
final DocumentInfo srcParent = getDisplayState().stack.peek();
@@ -807,6 +819,12 @@
}
private void transferDocuments(final Selection selected, final @OpType int mode) {
+ if(mode == FileOperationService.OPERATION_COPY) {
+ Metrics.logUserAction(getContext(), Metrics.USER_ACTION_COPY_TO);
+ } else if (mode == FileOperationService.OPERATION_MOVE) {
+ Metrics.logUserAction(getContext(), Metrics.USER_ACTION_MOVE_TO);
+ }
+
// Pop up a dialog to pick a destination. This is inadequate but works for now.
// TODO: Implement a picker that is to spec.
final Intent intent = new Intent(
@@ -853,6 +871,8 @@
}
private void renameDocuments(Selection selected) {
+ Metrics.logUserAction(getContext(), Metrics.USER_ACTION_RENAME);
+
// Batch renaming not supported
// Rename option is only available in menu when 1 document selected
assert(selected.size() == 1);
@@ -1012,6 +1032,8 @@
}
public void copySelectedToClipboard() {
+ Metrics.logUserAction(getContext(), Metrics.USER_ACTION_COPY_CLIPBOARD);
+
Selection selection = mSelectionManager.getSelection(new Selection());
if (!selection.isEmpty()) {
copySelectionToClipboard(selection);
@@ -1035,6 +1057,8 @@
}
public void pasteFromClipboard() {
+ Metrics.logUserAction(getContext(), Metrics.USER_ACTION_PASTE_CLIPBOARD);
+
copyFromClipboard();
getActivity().invalidateOptionsMenu();
}
@@ -1065,6 +1089,8 @@
}
public void selectAllFiles() {
+ Metrics.logUserAction(getContext(), Metrics.USER_ACTION_SELECT_ALL);
+
// Exclude disabled files
List<String> enabled = new ArrayList<String>();
for (String id : mAdapter.getModelIds()) {
@@ -1139,7 +1165,14 @@
if (Objects.equals(src, dst)) {
return false;
}
- Metrics.logDragNDrop(getContext());
+ // Recognize multi-window drag and drop based on the fact that localState is not
+ // carried between processes. It will stop working when the localsState behavior
+ // is changed. The info about window should be passed in the localState then.
+ // The localState could also be null for copying from Recents in single window
+ // mode, but Recents doesn't offer this functionality (no directories).
+ Metrics.logUserAction(getContext(),
+ src == null ? Metrics.USER_ACTION_DRAG_N_DROP_MULTI_WINDOW
+ : Metrics.USER_ACTION_DRAG_N_DROP);
copyFromClipData(event.getClipData(), dst);
return true;
}
@@ -1379,7 +1412,6 @@
// This has to be handled here instead of in a keyboard shortcut, because
// keyboard shortcuts all have to be modified with the 'Ctrl' key.
if (mSelectionManager.hasSelection()) {
- Metrics.logKeyboardAction(getContext(), Metrics.ACTION_KEYBOARD_DELETE);
deleteDocuments(mSelectionManager.getSelection());
}
// Always handle the key, even if there was nothing to delete. This is a
@@ -1666,8 +1698,9 @@
@Override
public void onLoadFinished(Loader<DirectoryResult> loader, DirectoryResult result) {
if (!isAdded()) return;
+
if (mSearchMode) {
- Metrics.logSearch(getContext());
+ Metrics.logUserAction(getContext(), Metrics.USER_ACTION_SEARCH);
}
State state = getDisplayState();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
index b80486d..1285b34 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
@@ -672,9 +672,9 @@
/**
* Used by CREATOR.
*/
- private Selection(String directoryKey, List<String> selection) {
+ private Selection(String directoryKey, Set<String> selection) {
mDirectoryKey = directoryKey;
- mSelection = new HashSet<String>(selection);
+ mSelection = selection;
mProvisionalSelection = new HashSet<String>();
}
@@ -887,7 +887,7 @@
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mDirectoryKey);
- dest.writeList(new ArrayList<>(mSelection));
+ dest.writeStringList(new ArrayList<>(mSelection));
// We don't include provisional selection since it is
// typically coupled to some other runtime state (like a band).
}
@@ -901,9 +901,12 @@
@Override
public Selection createFromParcel(Parcel in, ClassLoader loader) {
- return new Selection(
- in.readString(),
- in.readArrayList(loader));
+ String directoryKey = in.readString();
+
+ ArrayList<String> selected = new ArrayList<>();
+ in.readStringList(selected);
+
+ return new Selection(directoryKey, new HashSet<String>(selected));
}
@Override
diff --git a/packages/ExtServices/res/values/strings.xml b/packages/ExtServices/res/values/strings.xml
index 0763403..b77ff10 100644
--- a/packages/ExtServices/res/values/strings.xml
+++ b/packages/ExtServices/res/values/strings.xml
@@ -17,4 +17,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name">Android Services Library</string>
<string name="notification_ranker">Android Notification Ranking Service</string>
+ <string name="notification_ranker_autobundle_explanation">Auto-grouping updated by Ranking Service</string>
</resources>
diff --git a/packages/ExtServices/src/android/ext/services/notification/Ranker.java b/packages/ExtServices/src/android/ext/services/notification/Ranker.java
index 0b2b1a4..3ef2aea 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Ranker.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Ranker.java
@@ -16,16 +16,36 @@
package android.ext.services.notification;
+import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+
+import android.os.Bundle;
+import android.service.notification.Adjustment;
import android.service.notification.NotificationRankerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
+import android.util.Slog;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+
+import android.ext.services.R;
/**
* Class that provides an updatable ranker module for the notification manager..
*/
public final class Ranker extends NotificationRankerService {
private static final String TAG = "RocketRanker";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);;
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private static final int AUTOBUNDLE_AT_COUNT = 4;
+ private static final String AUTOBUNDLE_KEY = "ranker_bundle";
+
+ // Map of package : notification keys. Only contains notifications that are not bundled
+ // by the app (aka no group or sort key).
+ Map<String, LinkedHashSet<String>> mUnbundledNotifications;
@Override
public Adjustment onNotificationEnqueued(StatusBarNotification sbn, int importance,
@@ -37,10 +57,146 @@
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
if (DEBUG) Log.i(TAG, "POSTED " + sbn.getKey());
+ try {
+ List<String> notificationsToBundle = new ArrayList<>();
+ if (!sbn.isGroup()) {
+ // Not grouped by the app, add to the list of notifications for the app;
+ // send bundling update if app exceeds the autobundling limit.
+ synchronized (mUnbundledNotifications) {
+ LinkedHashSet<String> notificationsForPackage
+ = mUnbundledNotifications.get(sbn.getPackageName());
+ if (notificationsForPackage == null) {
+ notificationsForPackage = new LinkedHashSet<>();
+ }
+ if (notificationsForPackage.contains(sbn.getKey())) {
+ return;
+ }
+ notificationsForPackage.add(sbn.getKey());
+ mUnbundledNotifications.put(sbn.getPackageName(), notificationsForPackage);
+
+ if (notificationsForPackage.size() >= AUTOBUNDLE_AT_COUNT) {
+ // Autobundle all but the most recently posted (not updated) notification.
+ int count = 0;
+ for (String key : notificationsForPackage) {
+ if (count < notificationsForPackage.size() - 1) {
+ notificationsToBundle.add(key);
+ }
+ count++;
+ }
+ }
+ }
+ if (notificationsToBundle.size() > 0) {
+ adjustAutobundlingSummary(sbn.getPackageName(), notificationsToBundle.get(0),
+ true);
+ adjustNotificationBundling(sbn.getPackageName(), notificationsToBundle, true);
+ }
+ } else {
+ // Grouped, but not by us. Send updates to unautobundle, if we bundled it.
+ maybeUnbundle(sbn, false);
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Failure processing new notification", e);
+ }
+ }
+
+ @Override
+ public void onNotificationRemoved(StatusBarNotification sbn) {
+ try {
+ maybeUnbundle(sbn, true);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error processing canceled notification", e);
+ }
+ }
+
+ /**
+ * Un-autobundles notifications that are now grouped by the app. Additionally cancels
+ * autobundling if the status change of this notification resulted in the loose notification
+ * count being under the limit.
+ */
+ private void maybeUnbundle(StatusBarNotification sbn, boolean notificationGone) {
+ List<String> notificationsToUnAutobundle = new ArrayList<>();
+ boolean removeSummary = false;
+ synchronized (mUnbundledNotifications) {
+ LinkedHashSet<String> notificationsForPackage
+ = mUnbundledNotifications.get(sbn.getPackageName());
+ if (notificationsForPackage == null || notificationsForPackage.size() == 0) {
+ return;
+ }
+ if (notificationsForPackage.remove(sbn.getKey())) {
+ if (!notificationGone) {
+ // Add the current notification to the unbundling list if it still exists.
+ notificationsToUnAutobundle.add(sbn.getKey());
+ }
+ // If the status change of this notification has brought the number of loose
+ // notifications back below the limit, remove the summary and un-autobundle.
+ if (notificationsForPackage.size() == AUTOBUNDLE_AT_COUNT - 1) {
+ removeSummary = true;
+ for (String key : notificationsForPackage) {
+ notificationsToUnAutobundle.add(key);
+ }
+ }
+ }
+ }
+ if (notificationsToUnAutobundle.size() > 0) {
+ if (removeSummary) {
+ adjustAutobundlingSummary(sbn.getPackageName(), null, false);
+ }
+ adjustNotificationBundling(sbn.getPackageName(), notificationsToUnAutobundle, false);
+ }
}
@Override
public void onListenerConnected() {
if (DEBUG) Log.i(TAG, "CONNECTED");
+ mUnbundledNotifications = new HashMap<>();
+ for (StatusBarNotification sbn : getActiveNotifications()) {
+ onNotificationPosted(sbn);
+ }
}
+
+ private void adjustAutobundlingSummary(String packageName, String key, boolean summaryNeeded) {
+ Bundle signals = new Bundle();
+ if (summaryNeeded) {
+ signals.putBoolean(Adjustment.NEEDS_AUTOGROUPING_KEY, true);
+ signals.putString(Adjustment.GROUP_KEY_OVERRIDE_KEY, AUTOBUNDLE_KEY);
+ } else {
+ signals.putBoolean(Adjustment.NEEDS_AUTOGROUPING_KEY, false);
+ }
+ Adjustment adjustment = new Adjustment(packageName, key, IMPORTANCE_UNSPECIFIED, signals,
+ getContext().getString(R.string.notification_ranker_autobundle_explanation), null);
+ if (DEBUG) {
+ Log.i(TAG, "Summary update for: " + packageName + " "
+ + (summaryNeeded ? "adding" : "removing"));
+ }
+ try {
+ adjustNotification(adjustment);
+ } catch (Exception e) {
+ Slog.e(TAG, "Adjustment failed", e);
+ }
+
+ }
+ private void adjustNotificationBundling(String packageName, List<String> keys, boolean bundle) {
+ List<Adjustment> adjustments = new ArrayList<>();
+ for (String key : keys) {
+ adjustments.add(createBundlingAdjustment(packageName, key, bundle));
+ if (DEBUG) Log.i(TAG, "Sending bundling adjustment for: " + key);
+ }
+ try {
+ adjustNotifications(adjustments);
+ } catch (Exception e) {
+ Slog.e(TAG, "Adjustments failed", e);
+ }
+ }
+
+ private Adjustment createBundlingAdjustment(String packageName, String key, boolean bundle) {
+ Bundle signals = new Bundle();
+ if (bundle) {
+ signals.putString(Adjustment.GROUP_KEY_OVERRIDE_KEY, AUTOBUNDLE_KEY);
+ } else {
+ signals.putString(Adjustment.GROUP_KEY_OVERRIDE_KEY, null);
+ }
+ return new Adjustment(packageName, key, IMPORTANCE_UNSPECIFIED, signals,
+ getContext().getString(R.string.notification_ranker_autobundle_explanation), null);
+ }
+
}
\ No newline at end of file
diff --git a/packages/Keyguard/res/values-ar/strings.xml b/packages/Keyguard/res/values-ar/strings.xml
index 442f29e..426d60f 100644
--- a/packages/Keyguard/res/values-ar/strings.xml
+++ b/packages/Keyguard/res/values-ar/strings.xml
@@ -72,8 +72,8 @@
<string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"إدخال رمز رمز PIN المراد"</string>
<string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"تأكيد رمز رمز PIN المراد"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"جارٍ إلغاء تأمين شريحة SIM…"</string>
- <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"اكتب رمز PIN المكون من 4 إلى 8 أرقام."</string>
- <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"يجب أن يتضمن رمز PUK 8 أرقام أو أكثر."</string>
+ <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"اكتب رقم التعريف الشخصي المكون من ٤ إلى ٨ أرقام."</string>
+ <string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"يجب أن يتضمن رمز PUK ۸ أرقام أو أكثر."</string>
<string name="kg_invalid_puk" msgid="3638289409676051243">"أعد إدخال رمز PUK الصحيح. وستؤدي المحاولات المتكررة إلى تعطيل شريحة SIM نهائيًا."</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"لا يتطابق رمزا رمز PIN"</string>
<string name="kg_login_too_many_attempts" msgid="6486842094005698475">"محاولات النقش كثيرة جدًا"</string>
diff --git a/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
index 6eea81b..7dba545 100644
--- a/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java
@@ -148,8 +148,9 @@
protected void onDraw(Canvas canvas) {
float totalDrawingWidth = getDrawingWidth();
float currentDrawPosition;
- if ((mGravity & Gravity.START) != 0) {
- if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+ if ((mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.LEFT) {
+ if ((mGravity & Gravity.RELATIVE_LAYOUT_DIRECTION) != 0
+ && getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
currentDrawPosition = getWidth() - getPaddingRight() - totalDrawingWidth;
} else {
currentDrawPosition = getPaddingLeft();
@@ -163,7 +164,7 @@
float yPosition =
(getHeight() - getPaddingBottom() - getPaddingTop()) / 2 + getPaddingTop();
canvas.clipRect(getPaddingLeft(), getPaddingTop(),
- getWidth()-getPaddingRight(), getHeight()-getPaddingBottom());
+ getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
float charLength = bounds.right - bounds.left;
for (int i = 0; i < length; i++) {
CharState charState = mTextChars.get(i);
diff --git a/packages/MtpDocumentsProvider/jni/com_android_mtp_AppFuse.cpp b/packages/MtpDocumentsProvider/jni/com_android_mtp_AppFuse.cpp
index eb96015..7c8806e 100644
--- a/packages/MtpDocumentsProvider/jni/com_android_mtp_AppFuse.cpp
+++ b/packages/MtpDocumentsProvider/jni/com_android_mtp_AppFuse.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#define LOG_NDEBUG 0
#define LOG_TAG "AppFuseJNI"
#include "utils/Log.h"
@@ -451,7 +450,7 @@
ScopedFd fd(static_cast<int>(jfd));
AppFuse appfuse(env, self);
- ALOGD("Start fuse loop.");
+ ALOGV("Start fuse loop.");
while (true) {
FuseRequest request;
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
index 246b95de..329afdd 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
@@ -33,7 +33,6 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
@@ -118,9 +117,10 @@
synchronized @Nullable LoaderTask getNextTaskOrReleaseBackgroundThread() {
Preconditions.checkState(mBackgroundThread != null);
- final LoaderTask task = mTaskList.findRunningTask();
- if (task != null) {
- return task;
+ for (final LoaderTask task : mTaskList) {
+ if (task.getState() == LoaderTask.STATE_LOADING) {
+ return task;
+ }
}
final Identifier identifier = mDatabase.getUnmappedDocumentsParent(mDevice.deviceId);
@@ -161,8 +161,21 @@
mTaskList.clearCompletedTasks();
}
- synchronized void clearTask(Identifier parentIdentifier) {
- mTaskList.clearTask(parentIdentifier);
+ /**
+ * Cancels the task for |parentIdentifier|.
+ *
+ * Task is removed from the cached list and it will create new task when |parentIdentifier|'s
+ * children are queried next.
+ */
+ void cancelTask(Identifier parentIdentifier) {
+ final LoaderTask task;
+ synchronized (this) {
+ task = mTaskList.findTask(parentIdentifier);
+ }
+ if (task != null) {
+ task.cancel();
+ mTaskList.remove(task);
+ }
}
/**
@@ -205,14 +218,6 @@
return null;
}
- LoaderTask findRunningTask() {
- for (int i = 0; i < size(); i++) {
- if (get(i).getState() == LoaderTask.STATE_LOADING)
- return get(i);
- }
- return null;
- }
-
void clearCompletedTasks() {
int i = 0;
while (i < size()) {
@@ -223,17 +228,6 @@
}
}
}
-
- void clearTask(Identifier parentIdentifier) {
- for (int i = 0; i < size(); i++) {
- final LoaderTask task = get(i);
- if (task.mIdentifier.mDeviceId == parentIdentifier.mDeviceId &&
- task.mIdentifier.mObjectHandle == parentIdentifier.mObjectHandle) {
- remove(i);
- return;
- }
- }
- }
}
/**
@@ -245,6 +239,7 @@
static final int STATE_LOADING = 1;
static final int STATE_COMPLETED = 2;
static final int STATE_ERROR = 3;
+ static final int STATE_CANCELLED = 4;
final MtpManager mManager;
final MtpDatabase mDatabase;
@@ -272,6 +267,7 @@
synchronized void loadObjectHandles() {
assert mState == STATE_START;
+ mPosition = 0;
int parentHandle = mIdentifier.mObjectHandle;
// Need to pass the special value MtpManager.OBJECT_HANDLE_ROOT_CHILDREN to
// getObjectHandles if we would like to obtain children under the root.
@@ -303,12 +299,10 @@
case STATE_ERROR:
throw mError;
}
-
final Cursor cursor =
mDatabase.queryChildDocuments(columnNames, mIdentifier.mDocumentId);
+ cursor.setExtras(extras);
cursor.setNotificationUri(resolver, createUri());
- cursor.respond(extras);
-
return cursor;
}
@@ -374,6 +368,10 @@
}
}
synchronized (this) {
+ // Check if the task is cancelled or not.
+ if (mState != STATE_LOADING) {
+ return;
+ }
try {
mDatabase.getMapper().putChildDocuments(
mIdentifier.mDeviceId,
@@ -403,6 +401,14 @@
}
/**
+ * Cancels the task.
+ */
+ synchronized void cancel() {
+ mDatabase.getMapper().cancelAddingDocuments(mIdentifier.mDocumentId);
+ mState = STATE_CANCELLED;
+ }
+
+ /**
* Returns a state of the task.
*/
int getState() {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
index adc71ae..63f18f3 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
@@ -363,6 +363,41 @@
}
/**
+ * Cancels adding documents.
+ * @param parentId
+ */
+ void cancelAddingDocuments(@Nullable String parentId) {
+ final String selection;
+ final String[] args;
+ if (parentId != null) {
+ selection = COLUMN_PARENT_DOCUMENT_ID + " = ?";
+ args = strings(parentId);
+ } else {
+ selection = COLUMN_PARENT_DOCUMENT_ID + " IS NULL";
+ args = EMPTY_ARGS;
+ }
+
+ final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
+ database.beginTransaction();
+ try {
+ if (!mInMappingIds.contains(parentId)) {
+ return;
+ }
+ mInMappingIds.remove(parentId);
+ final ContentValues values = new ContentValues();
+ values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
+ mDatabase.getSQLiteDatabase().update(
+ TABLE_DOCUMENTS,
+ values,
+ selection + " AND " + COLUMN_ROW_STATE + " = ?",
+ DatabaseUtils.appendSelectionArgs(args, strings(ROW_STATE_INVALIDATED)));
+ database.setTransactionSuccessful();
+ } finally {
+ database.endTransaction();
+ }
+ }
+
+ /**
* Queries candidate for each mappingKey, and returns the first cursor that includes a
* candidate.
*
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index 50781bf..1823711 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -308,7 +308,7 @@
final Identifier parentIdentifier = mDatabase.getParentIdentifier(documentId);
mMtpManager.deleteDocument(identifier.mDeviceId, identifier.mObjectHandle);
mDatabase.deleteDocument(documentId);
- getDocumentLoader(parentIdentifier).clearTask(parentIdentifier);
+ getDocumentLoader(parentIdentifier).cancelTask(parentIdentifier);
notifyChildDocumentsChange(parentIdentifier.mDocumentId);
if (parentIdentifier.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE) {
// If the parent is storage, the object might be appeared as child of device because
@@ -402,7 +402,7 @@
final String documentId = mDatabase.putNewDocument(
parentId.mDeviceId, parentDocumentId, record.operationsSupported,
infoWithHandle, 0l);
- getDocumentLoader(parentId).clearTask(parentId);
+ getDocumentLoader(parentId).cancelTask(parentId);
notifyChildDocumentsChange(parentDocumentId);
return documentId;
} catch (FileNotFoundException | RuntimeException error) {
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
index 45f89e4..60dd7e1 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
@@ -21,6 +21,7 @@
import android.mtp.MtpObjectInfo;
import android.net.Uri;
import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.Document;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
@@ -28,6 +29,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeoutException;
@MediumTest
public class DocumentLoaderTest extends AndroidTestCase {
@@ -141,6 +143,33 @@
}
}
+ public void testCancelTask() throws IOException, InterruptedException {
+ setUpDocument(mManager,
+ DocumentLoader.NUM_INITIAL_ENTRIES + DocumentLoader.NUM_LOADING_ENTRIES + 1);
+
+ // Block the first iteration in the background thread.
+ mManager.blockDocument(
+ 0, DocumentLoader.NUM_INITIAL_ENTRIES + 1);
+ setUpLoader();
+ try (final Cursor cursor = mLoader.queryChildDocuments(
+ MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier)) {
+ assertTrue(cursor.getExtras().getBoolean(DocumentsContract.EXTRA_LOADING));
+ }
+ Thread.sleep(DocumentLoader.NOTIFY_PERIOD_MS);
+
+ // Clear task while the first iteration is being blocked.
+ mManager.unblockDocument(
+ 0, DocumentLoader.NUM_INITIAL_ENTRIES + 1);
+ mLoader.cancelTask(mParentIdentifier);
+
+ Thread.sleep(DocumentLoader.NOTIFY_PERIOD_MS * 2);
+
+ // Check if it's OK to query invalidated task.
+ try (final Cursor cursor = mLoader.queryChildDocuments(
+ MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier)) {
+ }
+ }
+
private void setUpLoader() {
mLoader = new DocumentLoader(
new MtpDeviceRecord(
diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml
index 1208298..b9d1902 100644
--- a/packages/PrintSpooler/res/values-ar/strings.xml
+++ b/packages/PrintSpooler/res/values-ar/strings.xml
@@ -30,7 +30,7 @@
<string name="destination_default_text" msgid="5422708056807065710">"اختر طابعة"</string>
<string name="template_all_pages" msgid="3322235982020148762">"جميع الصفحات وعددها <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
<string name="template_page_range" msgid="428638530038286328">"النطاق <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
- <string name="pages_range_example" msgid="8558694453556945172">"على سبيل المثال، 1—5،8،11—13"</string>
+ <string name="pages_range_example" msgid="8558694453556945172">"مثلاً، ۱—۵،۹،۷—۱۰"</string>
<string name="print_preview" msgid="8010217796057763343">"معاينة قبل الطباعة"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"تثبيت برنامج عرض PDF للمعاينة"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"تعطّل تطبيق الطباعة"</string>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index c44f0d0..f32cd13 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Hierdie kenmerk is eksperimenteel en kan werkverrigting beïnvloed."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Geneutraliseer deur <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Ongeveer <xliff:g id="TIME">%1$s</xliff:g> oor"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol op WS"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol oor USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot vol vanaf draadloos"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Laai"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laai tans op WS"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Laai tans"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laai tans oor USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Laai tans"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Laai tans draadloos"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Laai tans"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Groter"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Grootste"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Gepasmaak (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index cd05135..1bb27e2 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> ገደማ ቀርቷል"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> በኤሲ ላይ እስከሚሞላ ድረስ"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> በዩኤስቢ ላይ እስከሚሞላ ድረስ"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> በገመድ አልባ ላይ እስከሚሞላ ድረስ"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"ያልታወቀ"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ኃይል በመሙላት ላይ"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"በኤሲ ሃይል በመሙላት ላይ"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"ኃይል በመሙላት ላይ"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"በዩኤስቢ ሃይል በመሙላት ላይ"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"ኃይል በመሙላት ላይ"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"በገመድ አልባ ሃይል በመሙላት ላይ"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"ኃይል በመሙላት ላይ"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ተለቅ ያለ"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"በጣም ተለቅ ያለ"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ብጁ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index b3f55eb..0f6b315 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> تقريبًا"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"يتبقى <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال باستخدام التيار المتردد"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال عبر USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> حتى الاكتمال بالشحن اللاسلكي"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"غير معروف"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"شحن"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"جارٍ الشحن بتيار متردد"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"جارٍ الشحن"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"جارٍ الشحن عبر USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"جارٍ الشحن"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"جارٍ الشحن لاسلكيًا"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"جارٍ الشحن"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"أكبر"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"أكبر مستوى"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"مخصص (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index 9a099af..5b2214a 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> qalıb"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC üzərindən dolana qədər"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB üzərindən dolana qədər"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> naqilsiz üzərindən dolana qədər"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Naməlum"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Enerji doldurma"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Dəyişən cərəyanda qidalanır"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Qidalanır"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB üzərindən qidalanır"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Qidalanır"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Naqilsiz qidalanır"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Qidalanır"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Daha böyük"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Ən böyük"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Fərdi (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 85b6ac2..e361efd 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -296,35 +296,26 @@
<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>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Preostalo vreme: <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"Preostalo je <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> dok se ne napuni"</string>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni punjačem"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni preko USB-a"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> dok se ne napuni bežično"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Punjenje"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Punjenje preko punjača"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Puni se"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Punjenje preko USB-a"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Puni se"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bežično punjenje"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Puni se"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Veći"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Najveći"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Prilagođeni (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-be-rBY/strings.xml b/packages/SettingsLib/res/values-be-rBY/strings.xml
index c8098ec..05c6d9af 100644
--- a/packages/SettingsLib/res/values-be-rBY/strings.xml
+++ b/packages/SettingsLib/res/values-be-rBY/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Засталося <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі ад сеткі пер. току"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі па USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўн. зарадкі бесправадным шляхам"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Невядома"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Зарадка"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Зар. ад сеткі пер. току"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Зарадка"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Зарадка па USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Зарадка"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Бесправадная зарадка"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Зарадка"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Большы"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Найвялікшы"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Карыстальніцкі (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 35b24bf..f596b04 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Оставащо време: <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане при променлив ток"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане през USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно безжично зареждане"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Неизвестно"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Зарежда се"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Зареждане при AC"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Зарежда се"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Зареждане през USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Зарежда се"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Безжично зареждане"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Зарежда се"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"По-голямо"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Най-голямо"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Персонализирано (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index 14c2c95..f691278 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -331,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"খুব বড়"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"বৃহত্তম"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"কাস্টম (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml
index f9c7fcad..e4bd011 100644
--- a/packages/SettingsLib/res/values-bs-rBA/strings.xml
+++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml
@@ -296,35 +296,26 @@
<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>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Imate još <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - imate još <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do kraja punjenja na el. napajanju"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pune baterije preko USB-a"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pune baterije bežičnim punjenjem"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Nepoznato"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Puni se"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Puni se na punjaču"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Punjenje"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Punjenje preko USB-a"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Punjenje"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bežično punjenje"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Punjenje"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Veće"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Najveće"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Prilagodi (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index a070740..ba19e30 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -331,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Més gran"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Màxim"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalitzat (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 040c9f0..03208bf 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkce je experimentální a může mít vliv na výkon."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Přepsáno nastavením <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Zbývající čas: <xliff:g id="TIME">%1$s</xliff:g> (přibližně)"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Zbývající čas: <xliff:g id="TIME">%1$s</xliff:g>"</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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – zbývá <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití ze zásuvky"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití přes USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití bezdrátově"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Neznámé"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíjí se"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Nabíjení z adaptéru"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Nabíjení"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Nabíjení přes USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Nabíjení"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bezdrátové nabíjení"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Nabíjení"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Větší"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Největší"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Vlastní (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index ddad673..d58fe62d 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -331,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Større"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Størst"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tilpasset (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 514228f..dc38dae 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -296,35 +296,26 @@
<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>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Noch ca. <xliff:g id="TIME">%1$s</xliff:g> verbleibend"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Noch <xliff:g id="TIME">%1$s</xliff:g>"</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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – noch <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – bei Stromanschluss voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – über USB voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – bei kabellosem Laden voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Unbekannt"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Wird aufgeladen"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laden über Netzteil"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Ladevorgang"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laden über USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Ladevorgang"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Kabelloses Laden"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Ladevorgang"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Größer"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Am größten"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Benutzerdefiniert (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 8df693a..87d5a98 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Απομένει/ουν <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση με φορτιστή AC"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση μέσω USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για πλήρη ασύρματη φόρτιση"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Άγνωστο"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Φόρτιση"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Φόρτιση με AC"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Φόρτιση"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Φόρτιση μέσω USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Φόρτιση"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Ασύρματη φόρτιση"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Φόρτιση"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Πιο μεγάλα"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Μεγαλύτερα"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Προσαρμοσμένη (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 466291a..fe490a2 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> left"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full on AC"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full over USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full from wireless"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Charging on AC"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Charging"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Charging over USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Charging"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Charging wirelessly"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Charging"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Larger"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Largest"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 466291a..fe490a2 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> left"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full on AC"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full over USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full from wireless"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Charging on AC"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Charging"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Charging over USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Charging"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Charging wirelessly"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Charging"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Larger"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Largest"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 466291a..fe490a2 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> left"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full on AC"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full over USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until full from wireless"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Unknown"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Charging"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Charging on AC"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Charging"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Charging over USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Charging"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Charging wirelessly"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Charging"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Larger"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Largest"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 9bc2cf4..03d9a95 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función es experimental y puede afectar el rendimiento."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Falta <xliff:g id="TIME">%1$s</xliff:g> aproximadamente"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tiempo restante: <xliff:g id="TIME">%1$s</xliff:g>"</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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tiempo restante: <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 la carga"</string>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga por CA"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga por USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar la carga inalámbrica"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Desconocido"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Carga en CA"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Cargando"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Carga con USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Cargando"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Carga inalámbrica"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Cargando"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Más grande"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Máximo"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index ec0cafe..4aaad05 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -331,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Más grande"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Lo más grande posible"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index 29a1aea..85261129 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> on jäänud"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> on jäänud"</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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis (vahelduvvool)"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis (USB)"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, kuni aku on täis (juhtmeta laad.)"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Tundmatu"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Laadimine"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laad. vahelduvv.-v."</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Laadimine"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laadimine USB kaudu"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Laadimine"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Juhtmevaba laadimine"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Laadimine"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Suurem"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Suurim"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Kohandatud (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index 4f55e35..2cc73bb 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Eginbidea esperimentala da eta eragina izan dezake funtzionamenduan."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"<xliff:g id="TIME">%1$s</xliff:g> inguru guztiz kargatu arte"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> 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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> korrontearen bidez guztiz kargatu arte"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB bidez guztiz kargatu arte"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> haririk gabe guztiz kargatu arte"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Ezezaguna"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Kargatzea"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"KA bidez kargatzen"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Kargatzen"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB bidez kargatzen"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Kargatzen"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Hari gabe kargatzen"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Kargatzen"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Oso handia"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Handiena"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Pertsonalizatua (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index e9d63fd..3fdb474 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> باقی مانده است"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل با جریان متناوب"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل از طریق USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل بهطور بیسیم"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"ناشناس"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"در حال شارژ شدن"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"شارژ با جریان متناوب"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"درحال شارژ شدن"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"شارژ از طریق USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"درحال شارژ شدن"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"شارژ به صورت بیسیم"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"درحال شارژ شدن"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"بزرگتر"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"بزرگترین"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"سفارشی (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 5531d27..b70d6a0 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tämä ominaisuus on kokeellinen ja voi vaikuttaa suorituskykyyn."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Tämän ohittaa <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Noin <xliff:g id="TIME">%1$s</xliff:g> jäljellä"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä (laturilataus)"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä (USB-lataus)"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä (WiFi-lataus)"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Tuntematon"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Ladataan"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laturilataus"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Ladataan"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-lataus"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Ladataan"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Langaton lataus"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Ladataan"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Suurempi"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Suurin"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Muokattu (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index df6bdc6..cc8e7f6 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -296,35 +296,26 @@
<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>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Temps restant : <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – Temps restant : <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (charge complète sur c.a. dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (chargée à 100 %% par USB dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> %% (chargée à 100 %% avec chargeur sans fil dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Inconnu"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Batterie en charge"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"En charge (c.a.)"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Charge en cours..."</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"En charge par USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Charge en cours..."</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"En charge sans fil"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Charge en cours..."</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Plus grande"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"La plus grande"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personnalisée (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index ee40b2a..a1b85a0 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Cette fonctionnalité est expérimentale et peut affecter les performances."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Il reste environ <xliff:g id="TIME">%1$s</xliff:g>."</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Temps restant : <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – Temps restant : <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% sur secteur dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% via USB dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> (chargée à 100 %% sans fil dans <xliff:g id="TIME">%2$s</xliff:g>)"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Inconnu"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Batterie en charge"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"En charge sur secteur"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"En charge"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"En charge via USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"En charge"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"En charge sans fil"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"En charge"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Plus grand"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Le plus grand"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personnalisé (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index 4a0451e..1bdddd9 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Esta función é experimental e pode afectar ao rendemento."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Duración aproximada de <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tempo restante: <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> (tempo restante: <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g>)"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga con CA"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g>)"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga con USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g>)"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar a carga co modo sen fíos"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g>)"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Descoñecido"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Cargando"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Cargando con CA"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Cargando"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Cargando por USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Cargando"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Cargando sen fíos"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Cargando"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Máis grande"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"O máis grande"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml
index becda28..eafb8b1 100644
--- a/packages/SettingsLib/res/values-gu-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> બાકી"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g>, AC પર પૂર્ણ ચાર્જ થયાંને <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g>, USB પર પૂર્ણ ચાર્જ થયાંને <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> વાયરલેસ દ્વારા પૂર્ણ થાય ત્યાં સુધી"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"અજાણ્યું"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ચાર્જ થઈ રહ્યું છે"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC પર ચાર્જિંગ"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"ચાર્જ થઈ રહ્યું છે"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB થી ચાર્જિંગ"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"ચાર્જ થઈ રહ્યું છે"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"વાયરલેસથી ચાર્જિંગ"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"ચાર્જ થઈ રહ્યું છે"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"વધુ મોટું"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"સૌથી મોટું"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"કસ્ટમ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 6dffdd9..b008e1f 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> शेष"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC पर पूरी होने तक"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB पर पूरी होने तक"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> वायरलेस से पूरी होने तक"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज हो रही है"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC से चार्ज हो रही"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"चार्ज हो रहा है"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB पर चार्ज हो रही"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"चार्ज हो रहा है"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"वायरलेस रूप से चार्ज हो रही"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"चार्ज हो रहा है"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"अधिक बड़ा"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"सबसे बड़ा"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"कस्टम (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 1edb015..6ba366c 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -331,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Veće"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Najveće"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Prilagođeno (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 060599c..b10f5be 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -331,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Nagyobb"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Legnagyobb"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Egyéni (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 63c4336..2021520 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Մնացել է <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը հոսանքից"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը USB-ով"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը անլար ցանցից"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Անհայտ"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Լիցքավորում"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Լիցքավորում AC-ով"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Լիցքավորում"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Լիցքավորում USB-ով"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Լիցքավորում"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Անլար լիցքավորում"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Լիցքավորում"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Ավելի մեծ"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Ամենամեծ"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Հատուկ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index c86c768..c02e3fa 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Fitur ini bersifat eksperimental dan dapat memengaruhi kinerja."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Digantikan oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Kira-kira tersisa <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> tersisa"</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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tersisa"</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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh pada AC"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh melalui USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sampai penuh dari nirkabel"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Mengisi daya"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Mengisi daya pada AC"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Mengisi daya"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Isi daya lewat USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Mengisi daya"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Isi daya nirkabel"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Mengisi daya"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Lebih besar"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Terbesar"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"(<xliff:g id="DENSITYDPI">%d</xliff:g>) khusus"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index 1fc0dc0..bdf5a35 100644
--- a/packages/SettingsLib/res/values-is-rIS/strings.xml
+++ b/packages/SettingsLib/res/values-is-rIS/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Þessi eiginleiki er á tilraunastigi og getur haft áhrif á frammistöðu."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Hnekkt af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Um það bil <xliff:g id="TIME">%1$s</xliff:g> eftir"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu með hleðslutæki"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu í gegnum USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> í fulla hleðslu þráðlaust"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Óþekkt"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Í hleðslu"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Hleðslutæki tengt"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Í hleðslu"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Hleður um USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Í hleðslu"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Hleður þráðlaust"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Í hleðslu"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Stærra"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Stærst"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Sérsniðið (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 78cd29b..43c41d7 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Questa funzione è sperimentale e potrebbe influire sulle prestazioni."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Circa <xliff:g id="TIME">%1$s</xliff:g> rimanenti"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tempo rimanente: <xliff:g id="TIME">%1$s</xliff:g>"</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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tempo rimanente: <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> alla carica completa"</string>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa tramite CA"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa tramite USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lla carica completa con wireless"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Sconosciuta"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"In carica"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"In carica tramite CA"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"In carica"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"In carica tramite USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"In carica"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"In carica, wireless"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"In carica"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Più grande"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Massimo"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizzato (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 16e0f44d..e25d218 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> בערך"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"נותרו <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד למילוי בזרם חילופין"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד למילוי ב-USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד למילוי בטעינה אלחוטית"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"לא ידוע"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"טוען"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"טוען בזרם חילופין"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"בטעינה"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"טוען ב-USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"בטעינה"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"טוען באופן אלחוטי"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"בטעינה"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"יותר גדול"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"הכי גדול"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"מותאם אישית (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index ce405df..ac239fe 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>(AC)"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>(USB)"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - フル充電まで<xliff:g id="TIME">%2$s</xliff:g>(ワイヤレス)"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"不明"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ACで充電しています"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"充電しています"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USBで充電しています"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"充電しています"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"無線で充電しています"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"充電しています"</string>
<string name="battery_info_status_discharging" msgid="310932812698268588">"充電していません"</string>
<string name="battery_info_status_not_charging" msgid="2820070506621483576">"充電していません"</string>
<!-- String.format failed for translation -->
@@ -342,4 +333,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"特大"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"最大"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"カスタム(<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml
index 20a1d2a..883d637 100644
--- a/packages/SettingsLib/res/values-ka-rGE/strings.xml
+++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"დარჩენილია <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ელკვებით სრულ დატენვამდე"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB-თი სრულ დატენვამდე"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> უსადენოდან სრულ დატენვამდე"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"უცნობი"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"იტენება"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"დატენვა ელკვებაზე"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"იტენება"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"დატენვა USB-ზე"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"იტენება"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"დატენვა უსადენოდ"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"იტენება"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"უფრო დიდი"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"უდიდესი"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"მორგებული (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index e71c8d0..3270170 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> қалды"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - айнымалы токпен толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB арқылы толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - сымсыз толғанша <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Белгісіз"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Зарядталуда"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Айнымалы токпен зар."</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Зарядталуда"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB арқылы зарядтау"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Зарядталуда"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Сымсыз зарядтау"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Зарядталуда"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Үлкенірек"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Ең үлкен"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Арнаулы (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index 687b71b..9d6d3475 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"នៅសល់ <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូតដល់ពេញរចន្តឆ្លាស់"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូតដល់ពេញតាមយូអេសប៊ី"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> រហូតដល់ពេញពីឥតខ្សែ"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"មិនស្គាល់"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"កំពុងបញ្ចូលថ្ម"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"បញ្ចូលថ្មតាម AC"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"កំពុងសាកថ្ម"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"បញ្ចូលថ្មតាមយូអេសប៊ី"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"កំពុងសាកថ្ម"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"បញ្ចូលថ្មដោយឥតខ្សែ"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"កំពុងសាកថ្ម"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ធំជាង"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"ធំបំផុត"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ផ្ទាល់ខ្លួន (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index 713d9b3..dc35604 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> ಉಳಿದಿದೆ"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC ನಲ್ಲಿ ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB ಮೂಲಕ ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ವೈರ್ಲೆಸ್ನಿಂದ ಪೂರ್ಣವಾಗುವವರೆಗೆ"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"ಅಜ್ಞಾತ"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC ನಲ್ಲಿ ಚಾರ್ಜ್"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ಮೂಲಕ ಚಾರ್ಜ್"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ನಿಸ್ತಂತುವಾಗಿ ಚಾರ್ಜ್"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ಸ್ವಲ್ಪ ದೊಡ್ಡ"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"ದೊಡ್ಡ"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ಕಸ್ಟಮ್ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 348141e..fc8f478 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> 남음"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료(AC 전원)"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료(USB)"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료(무선)"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"알 수 없음"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"충전 중"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"충전 중(AC 전원)"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"충전 중"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"충전 중(USB)"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"충전 중"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"충전 중(무선)"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"충전 중"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"더 크게"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"가장 크게"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"맞춤(<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index 2016f04..8b0119e 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> калды"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC аркылуу толгончо"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB аркылуу толгончо"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> зымсыз кубаттоо аркылуу толгончо"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Белгисиз"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Кубатталууда"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ӨА кубатталууда"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Кубатталууда"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB\'ден кубатталууда"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Кубатталууда"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Зымсыз кубатталууда"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Кубатталууда"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Чоңураак"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Эң чоң"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Ыңгайлаштырылган (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index 7e6db5e..3532137 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"ຍັງເຫຼືອ <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະເຕັມໂດຍສາກດ້ວຍໄຟ AC"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະເຕັມໂດຍສາກດ້ວຍ USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະເຕັມໂດຍສາກແບບໄຮ້ສາຍ"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"ບໍ່ຮູ້ຈັກ"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ກຳລັງສາກໄຟ"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ກຳລັງສາກຜ່ານໝໍ້ໄຟ"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"ກຳລັງສາກໄຟ"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"ກຳລັງສາກຜ່ານ USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"ກຳລັງສາກໄຟ"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ກຳລັງສາກໄຮ້ສາຍ"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"ກຳລັງສາກໄຟ"</string>
<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>
@@ -340,4 +331,5 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ໃຫຍ່ກວ່າ"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"ໃຫຍ່ທີ່ສຸດ"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ປັບແຕ່ງເອງ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <string name="help_feedback_label" msgid="6815040660801785649">"ຊ່ວຍເຫຼືອ & ຄຳຕິຊົມ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index d49876e..02739f3 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ši funkcija yra eksperimentinė ir ji gali turėti įtakos našumui."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nepaisyta naudojant nuostatą „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Liko maždaug <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Liko <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo naud. kint. sr."</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo naudojant USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> iki visiško įkrovimo belaid. ryš."</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Nežinomas"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Kraunasi..."</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Įkr. naud. kint. sr."</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Įkraunama"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Įkraunama naud. USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Įkraunama"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Įkraunama be laidų"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Įkraunama"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Didesnis"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Didžiausias"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tinkintas (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 6cd9cfd5..54c75ff 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Šī funkcija ir eksperimentāla un var ietekmēt veiktspēju."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Jaunā preference: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Atlikušais laiks: aptuveni <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Atlicis: <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> — atlicis: <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai maiņstrāvas uzlādei"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai USB uzlādei"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai bezvadu uzlādei"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Nezināms"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Uzlāde"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Maiņstrāvas uzlāde"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Notiek uzlāde"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB uzlāde"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Notiek uzlāde"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bezvadu uzlāde"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Notiek uzlāde"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Lielāks"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Vislielākais"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Pielāgots (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml
index f8f65ec..8f11118 100644
--- a/packages/SettingsLib/res/values-mk-rMK/strings.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"уште <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна на AC"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна преку USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до целосно полна, безжично"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Непознато"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Се полни"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Полнење на струја"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Се полни"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Полнење преку УСБ"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Се полни"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Безжично полнење"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Се полни"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Поголем"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Најголем"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Приспособен (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index 7350b7f..f39b109 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - AC-യിൽ പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB വഴി പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - വയർലെസ് വഴി പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"അജ്ഞാതം"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ചാർജ്ജുചെയ്യുന്നു"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC-യിൽ ചാർജ്ജുചെയ്യുന്നു"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"ചാർജ്ജുചെയ്യുന്നു"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-യിലൂടെ ചാർജ്ജുചെയ്യുന്നു"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"ചാർജ്ജുചെയ്യുന്നു"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"വയർലെസ്സ് കണക്ഷനിലൂടെ ചാർജ്ജുചെയ്യുന്നു"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"ചാർജ്ജുചെയ്യുന്നു"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"കൂടുതൽ വലുത്"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"ഏറ്റവും വലുത്"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ഇഷ്ടാനുസൃതം ( <xliff:g id="DENSITYDPI">%d</xliff:g> )"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index 7eeae06..8b005d1 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> үлдсэн"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"АС-р дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"USB-р дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"утасгүй цэнэглэгчээр дүүртэл <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Тодорхойгүй"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Цэнэглэж байна"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC-р цэнэглэж байна"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Цэнэглэж байна"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB-р цэнэглэж байна"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Цэнэглэж байна"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Кабльгүйгээр цэнэглэж байна"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Цэнэглэж байна"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Илүү том"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Хамгийн том"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Тогтмол утга (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml
index 0521ba1..9296a32 100644
--- a/packages/SettingsLib/res/values-mr-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> शिल्लक"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC वरून पूर्ण होण्यात"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB वरून पूर्ण होण्यात"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> वायरलेसवरून पूर्ण होण्यात"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज होत आहे"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC वर चार्ज करीत आहे"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"चार्ज होत आहे"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB वरून चार्ज करीत आहे"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"चार्ज होत आहे"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"वायरलेस वरून चार्ज करीत आहे"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"चार्ज होत आहे"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"आणखी मोठा"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"सर्वात मोठा"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"सानुकूल करा (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index a8be0e5..60a5298 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ciri ini adalah percubaan dan boleh menjejaskan prestasi."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Diatasi oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Kira-kira <xliff:g id="TIME">%1$s</xliff:g> lagi"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi"</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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh di AC"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh melalui USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga penuh dari wayarles"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Tidak diketahui"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Mengecas"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Mengecas pada AC"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Mengecas"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Mengecas melalui USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Mengecas"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Mengecas tanpa wayar"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Mengecas"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Lebih besar"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Terbesar"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tersuai (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index 220deff..e512aac 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> ကျန်ပါသည်"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> လျှပ်စစ်ဖြင့် အပြည့်အထိ"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB ဖြင့် အပြည့်အထိ"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ကြိုးမဲ့ဖြင့် အပြည့်အထိ"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"အကြောင်းအရာ မသိရှိ"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"အားသွင်းနေပါသည်"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"လျှပ်စစ်ဖြင့် အားသွင်းနေ"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"အားသွင်းနေသည်"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USBဖြင့် အားသွင်းနေ"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"အားသွင်းနေသည်"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ကြိုးမဲ့ အားသွင်းနေ"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"အားသွင်းနေသည်"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ပိုကြီး"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"အကြီးဆုံး"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"စိတ်ကြိုက် (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index a1407ac..3d01254 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -296,35 +296,26 @@
<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>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> gjenstår"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> gjenstår"</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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g> med vekselstrøm"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g> via USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – fulladet om <xliff:g id="TIME">%2$s</xliff:g> via trådløs lading"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Ukjent"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Lader"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Lader via strømuttak"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Lader"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Lader via USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Lader"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Lader trådløst"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Lader"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Større"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Størst"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Egendefinert (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index 83e2e74..f2e6ea4 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> बाँकी छ"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC मा पूर्ण नभए सम्म"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB मा पूर्ण नभए सम्म"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> वायरलेसबाट पूर्ण नभए सम्म"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज हुँदै"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC मा चार्ज गर्दै"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"चार्ज हुँदै"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB मा चार्ज गर्दै"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"चार्ज हुँदै"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"बिना तार चार्ज गर्दै"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"चार्ज हुँदै"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"अझ ठूलो"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"सबैभन्दा ठूलो"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"अनुकूलन (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 55017d8..4ae1fb0b 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Deze functie is experimenteel en kan invloed hebben op de prestaties."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca. <xliff:g id="TIME">%1$s</xliff:g> resterend"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol via wisselstroom"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol via USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot vol via draadloos"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Onbekend"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Opladen"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Opladen via netvoeding"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Opladen"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Opladen via USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Opladen"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Draadloos opladen"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Opladen"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Groter"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Grootst"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Aangepast (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index eb1eaac..5596cbc 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> ਬਾਕੀ"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC ਤੇ ਪੂਰਾ ਹੋਣ ਤੱਕ"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB ਤੇ ਪੂਰਾ ਹੋਣ ਤੱਕ"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਵਾਇਰਲੈਸ ਤੋਂ ਪੂਰਾ ਹੋਣ ਤੱਕ"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"ਅਗਿਆਤ"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ਚਾਰਜਿੰਗ"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC ਤੇ ਚਾਰਜਿੰਗ"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"ਚਾਰਜ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ਤੇ ਚਾਰਜਿੰਗ"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"ਚਾਰਜ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"ਵਾਇਰਲੈਸ ਤੌਰ ਤੇ ਚਾਰਜਿੰਗ"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"ਚਾਰਜ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ਥੋੜ੍ਹਾ ਵੱਡਾ"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"ਸਭ ਤੋਂ ਵੱਡਾ"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 1e56cfd..81ebed8 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"To jest funkcja eksperymentalna i może wpływać na działanie urządzenia."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Nadpisana przez <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Pozostało około <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Został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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostało <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania z gniazdka"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania przez USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania bezprzewodowo"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Nieznane"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Ładowanie"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Ładowanie zasilaczem"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Ładowanie"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Ładowanie przez USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Ładowanie"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Ład. bezprzewodowe"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Ładowanie"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Większe"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Największe"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Niestandardowe (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 93f333a..5bfbc2d 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -115,7 +115,7 @@
<string name="tts_engine_network_required" msgid="1190837151485314743">"Este idioma requer uma conexão de rede ativa para a conversão de texto em voz."</string>
<string name="tts_default_sample_string" msgid="4040835213373086322">"Este é um exemplo de sintetização de voz."</string>
<string name="tts_status_title" msgid="7268566550242584413">"Status de idioma padrão"</string>
- <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> é totalmente suportada"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> é totalmente suportado"</string>
<string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> requer conexão de rede"</string>
<string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> não é suportado"</string>
<string name="tts_status_checking" msgid="5339150797940483592">"Verificando..."</string>
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Aproximadamente <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> restante(s)"</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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir em CA"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir via USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir sem fio"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Carregamento CA"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Carregando"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Carregamento via USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Carregando"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Carregamento sem fio"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Carregando"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Muito grande"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Maior"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizada (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index dda00fe..244e27d 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Resta(m) <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – resta(m) <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar completa através de CA"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar completa através de USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até ficar compl. por rede s/ fios"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"A carregar"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"A carregar por CA"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"A carregar"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"A carregar por USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"A carregar"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"A carregar sem fios"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"A carregar"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Maior"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"O maior"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 93f333a..5bfbc2d 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -115,7 +115,7 @@
<string name="tts_engine_network_required" msgid="1190837151485314743">"Este idioma requer uma conexão de rede ativa para a conversão de texto em voz."</string>
<string name="tts_default_sample_string" msgid="4040835213373086322">"Este é um exemplo de sintetização de voz."</string>
<string name="tts_status_title" msgid="7268566550242584413">"Status de idioma padrão"</string>
- <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> é totalmente suportada"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> é totalmente suportado"</string>
<string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> requer conexão de rede"</string>
<string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> não é suportado"</string>
<string name="tts_status_checking" msgid="5339150797940483592">"Verificando..."</string>
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Este recurso é experimental e pode afetar o desempenho."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Aproximadamente <xliff:g id="TIME">%1$s</xliff:g> restante(s)"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> restante(s)"</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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir em CA"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir via USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> até concluir sem fio"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Desconhecido"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Carregando"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Carregamento CA"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Carregando"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Carregamento via USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Carregando"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Carregamento sem fio"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Carregando"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Muito grande"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Maior"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizada (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 3c46d41..668d19c 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Această funcție este experimentală și poate afecta performanțele."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valoare înlocuită de <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Timp rămas: aproximativ <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Timp rămas: <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – timp rămas: <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă la c.a."</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă prin USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> până la încărcare completă wireless"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Necunoscut"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Încarcă"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Se încarcă la C.A."</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Se încarcă"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Se încarcă prin USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Se încarcă"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Se încarcă fără fir"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Se încarcă"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Mai mare"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Cel mai mare"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizat (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index f4929de..a9d4abc 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Осталось: <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки (от сети)"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки (через USB)"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки (беспроводная)"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Неизвестно"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Идет зарядка"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Зарядка от сети"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Зарядка"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Зарядка через USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Зарядка"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Беспроводная зарядка"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Зарядка"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Очень крупный"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Максимальный"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Другой (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index 99f018b..90b82f1 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>ක් ඉතිරිය"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"ඉතිරි <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"AC හි <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පුර්ණ වන තෙක්"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"USB හරහ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පුර්ණ වන තෙක්"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"රේඩියෝව වෙතින් <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> සම්පූර්ණ වන තෙක්"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"නොදනී"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ආරෝපණය වෙමින්"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC හි ආරෝපණය වෙමින්"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"ආරෝපණය වෙමින්"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB හරහා ආරෝපණය වෙමින්"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"ආරෝපණය වෙමින්"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"රැහැන් රහිතව ආරෝපණය වෙමින්"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"ආරෝපණය වෙමින්"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"වඩා විශාල"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"විශාලතම"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"අභිරුචි (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 4dffdef..dbb4dde 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Funkcia je experimentálna a môže mať vplyv na výkonnosť."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Prekonané predvoľbou <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Zostáva cca. <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Zostávajúci čas: <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – zostávajúci čas: <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia zo zásuvky"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia cez USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia bezdrôtovo"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Neznáme"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Nabíjanie"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Nabíjanie zo zásuvky"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Nabíjanie"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Nabíjanie cez USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Nabíjanie"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Bezdrôtové nabíjanie"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Nabíjanie"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Väčšie"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Najväčšie"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Vlastné (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 676a3ab..54e8636 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Še <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – še <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti prek napajalnika"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti prek USB-ja"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti prek brezž. pol."</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Neznano"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Polnjenje"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Polnj. prek iz. toka"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Polnjenje"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Polnj. prek USB-ja"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Polnjenje"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Brezžično polnjenje"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Polnjenje"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Večje"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Največje"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Po meri (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index c18e639..ecc10f4 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> të mbetura"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> deri sa të mbushet në AC"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> deri sa të mbushet me USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> deri sa të mbushet nga lidhja pa tel"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"I panjohur"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Po ngarkohet"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Po ngarkohet në AC"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Po ngarkohet"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Po ngarkohet me USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Po ngarkohet"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Po ngarkohet me valë"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Po ngarkohet"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Më i madh"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Më i madhi"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"I personalizuar (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index c0791fc..5330893 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Преостало време: <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"Преостало је <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни пуњачем"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни преко USB-а"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> док се не напуни бежично"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Непознато"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Пуњење"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Пуњење преко пуњача"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Пуни се"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Пуњење преко USB-а"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Пуни се"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Бежично пуњење"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Пуни се"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Већи"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Највећи"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Прилагођени (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 60c42a5..0a054578 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Den här funktionen är experimentell och kan påverka prestandan."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Har åsidosatts av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Ca <xliff:g id="TIME">%1$s</xliff:g> kvar"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat via laddare"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat via USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till fulladdat via trådlös laddning"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Okänd"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Laddar"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Laddas via adapter"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Laddar"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Laddas via USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Laddar"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Laddas trådlöst"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Laddar"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Större"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Störst"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Anpassad (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 5de7686..20d3cc8 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -296,35 +296,26 @@
<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>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Zimesalia takribani <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Zimesalia <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"Imechaji <xliff:g id="LEVEL">%1$s</xliff:g> - Zimesalia <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae kwa kutumia AC"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g>%% - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae kwa kutumia USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia <xliff:g id="TIME">%2$s</xliff:g> hadi ijae kwa isiyotumia waya"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Haijulikani"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Inachaji"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Inachaji kupitia AC"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Inachaji"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Inachaji kupitia USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Inachaji"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Inachaji bila kutumia waya"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Inachaji"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Kubwa kiasi"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Kubwa zaidi"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Kiwango maalum (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index a5f04d0..304680b 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> உள்ளது"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"முழு AC சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"முழு USB சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"முழு வயர்லெஸ் சார்ஜிற்கு: <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"அறியப்படாத"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"சார்ஜ் ஏற்றப்படுகிறது"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC மூலம் சார்ஜாகிறது"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"சார்ஜ் ஏறுகிறது"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB மூலம் சார்ஜாகிறது"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"சார்ஜ் ஏறுகிறது"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"வயர்லெஸில் சார்ஜாகிறது"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"சார்ஜ் ஏறுகிறது"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"கொஞ்சம் பெரியது"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"மிகப் பெரியது"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"தனிப்பயன் (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index fe40766..b6457c7 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> మిగిలి ఉంది"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - ACలో పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB ద్వారా పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - వైర్లెస్ నుండి పూర్తిగా నిండటానికి <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"తెలియదు"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ఛార్జ్ అవుతోంది"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"ACలో ఛార్జ్ అవుతోంది"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"ఛార్జ్ అవుతోంది"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ద్వారా ఛార్జ్ అవుతోంది"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"ఛార్జ్ అవుతోంది"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"వైర్లెస్ ద్వారా ఛార్జ్ అవుతోంది"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"ఛార్జ్ అవుతోంది"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"చాలా పెద్దగా"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"అతి పెద్దగా"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"అనుకూలం (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index c58692f..345da0f 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"เหลือเวลา <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็มเมื่อชาร์จผ่าน AC"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็มเมื่อชาร์จผ่าน USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะเต็มเมื่อชาร์จผ่านระบบไร้สาย"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"ไม่ทราบ"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"กำลังชาร์จ"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"กำลังชาร์จไฟ AC"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"กำลังชาร์จ"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"กำลังชาร์จผ่าน USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"กำลังชาร์จ"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"กำลังชาร์จแบบไร้สาย"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"กำลังชาร์จ"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ใหญ่ขึ้น"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"ใหญ่ที่สุด"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"กำหนดเอง (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 093256c..f820ab8 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -296,35 +296,26 @@
<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>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> na lang ang natitira"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> pa"</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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> pa"</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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno sa AC"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno sa USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> bago mapuno mula sa wireless"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Hindi Kilala"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Nagcha-charge"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Nagcha-charge sa AC"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Nagcha-charge"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Nagcha-charge sa USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Nagcha-charge"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Wireless nag-charge"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Nagcha-charge"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Mas malaki"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Pinakamalaki"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 1947d39..9766dea 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu özellik deneyseldir ve performansı etkileyebilir."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> tarafından geçersiz kılındı"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Yaklaşık <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - prize takılı, tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - USB üzerinden şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - kablosuzdan tam şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> var"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Bilinmiyor"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Şarj oluyor"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC ile şarj oluyor"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Şarj oluyor"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB ile şarj oluyor"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Şarj oluyor"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Kablosuz şarj oluyor"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Şarj oluyor"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Daha büyük"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"En büyük"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Özel (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 0ed6cc0..831484f 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Залишилося <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного зарядження з розетки"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного зарядження через USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного з бездротового зарядження"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Невідомо"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Зарядж-ся"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Заряджання з розетки"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Заряджається"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Заряджання через USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Заряджається"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Заряджання без дроту"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Заряджається"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Більші елементи"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Найбільші елементи"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Спеціальний масштаб (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index 99a0f2b..15277ae 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g> باقی ہیں"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> AC پر پورا ہونے تک"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> USB پر پورا ہونے تک"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> وائرلیس سے پورا ہونے تک"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"نامعلوم"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"چارج ہو رہا ہے"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"AC پر چارج ہو رہی ہے"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"چارجنگ ہو رہی ہے"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"USB پر چارج ہورہی ہے"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"چارجنگ ہو رہی ہے"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"وائرلیس چارجنگ"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"چارجنگ ہو رہی ہے"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"قدرے بڑا"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"سب سے بڑا"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"حسب ضرورت (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index b9c0243..374e7fc 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Bu funksiya tajribaviy bo‘lib, u qurilma unumdorligiga ta’sir qilishi mumkin."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> bilan almashtirildi"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> – <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, o‘zgaruvchan tok orqali to‘lguncha"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, USB orqali to‘lguncha"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>, simsiz quvvatlash orqali to‘lguncha"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Noma’lum"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Quvvat olmoqda"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Quvvat olmoqda (AC)"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Quvvat olmoqda"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Quvvat olmoqda (USB)"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Quvvat olmoqda"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Simsiz quvvat olmoqda"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Quvvat olmoqda"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Kattaroq"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Eng katta"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Moslashtirilgan (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 0c3dc89..1c86175 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Tính năng này là tính năng thử nghiệm và có thể ảnh hưởng đến hoạt động."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Bị ghi đè bởi <xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Còn khoảng <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Còn lại <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - còn lại <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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy khi cắm vào nguồn AC"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy qua USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> cho đến khi đầy từ không dây"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Không xác định"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Đang sạc"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Sạc trên AC"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Đang sạc"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Sạc qua USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Đang sạc"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Sạc không dây"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Đang sạc"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Lớn hơn"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Lớn nhất"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tùy chỉnh (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 2b8ce65..d0dc925 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"还可用 <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满(交流电充电)"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满(USB充电)"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满(无线充电)"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"未知"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"正在充电"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"正在通过交流电源充电"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"正在充电"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"正在通过USB充电"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"正在充电"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"正在无线充电"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"正在充电"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"较大"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"最大"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"自定义 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 8dd0417..9bb0a4c 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"尚餘 <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電 (透過插頭充電)"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電 (透過 USB 充電)"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> 後完成充電 (無線充電)"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"未知"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"正在透過 AC 充電"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"正在充電"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"正在透過 USB 充電"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"正在充電"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"正在透過無線方式充電"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"正在充電"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"較大"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"最大"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"自訂 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index dd59954..bf3880b 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -296,35 +296,26 @@
<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">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"還剩 <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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽 (AC)"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽 (USB)"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽 (無線充電)"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"不明"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"充電中"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"正在透過 AC 變壓器充電"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"充電中"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"正在透過 USB 充電"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"充電中"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"正在透過無線方式充電"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"充電中"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"較大"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"最大"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"自訂 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 610cac4..7953372 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -296,35 +296,26 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Lesi sici esesilingo futhi singathinta ukusebenza."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Igitshezwe ngaphezulu yi-<xliff:g id="TITLE">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only" msgid="4400068916452346544">"Cishe ngu-<xliff:g id="TIME">%1$s</xliff:g> osele"</string>
- <!-- no translation found for power_remaining_duration_only_short (5329694252258605547) -->
- <skip />
+ <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> esisele"</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>
- <!-- no translation found for power_discharging_duration_short (4192244429001842403) -->
- <skip />
+ <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> okusele"</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>
- <!-- no translation found for power_charging_duration_short (1098603958472207920) -->
- <skip />
+ <string name="power_charging_duration_short" msgid="1098603958472207920">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_ac" msgid="3969186192576594254">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale ku-AC"</string>
- <!-- no translation found for power_charging_duration_ac_short (7895864687218765582) -->
- <skip />
+ <string name="power_charging_duration_ac_short" msgid="7895864687218765582">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_usb" msgid="182405645340976546">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale ngaphezulu kwe-USB"</string>
- <!-- no translation found for power_charging_duration_usb_short (941854728040426399) -->
- <skip />
+ <string name="power_charging_duration_usb_short" msgid="941854728040426399">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_duration_wireless" msgid="1829295708243159464">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> kuze igcwale kusukela kokungenantambo"</string>
- <!-- no translation found for power_charging_duration_wireless_short (1642664799869599476) -->
- <skip />
+ <string name="power_charging_duration_wireless_short" msgid="1642664799869599476">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="196130600938058547">"Akwaziwa"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Iyashaja"</string>
<string name="battery_info_status_charging_ac" msgid="2909861890674399949">"Iyashaja ku-AC"</string>
- <!-- no translation found for battery_info_status_charging_ac_short (7431401092096415502) -->
- <skip />
+ <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Iyashaja"</string>
<string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Iyashaja ngaphezulu kwe-USB"</string>
- <!-- no translation found for battery_info_status_charging_usb_short (6733371990319101366) -->
- <skip />
+ <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Iyashaja"</string>
<string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Iyashaja ngaphandle kwentambo"</string>
- <!-- no translation found for battery_info_status_charging_wireless_short (752569941028903610) -->
- <skip />
+ <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Iyashaja"</string>
<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>
@@ -340,4 +331,6 @@
<string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Okukhulu kakhulu"</string>
<string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Okukhulu kakhulu"</string>
<string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Ngokwezifiso (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+ <!-- no translation found for help_feedback_label (6815040660801785649) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index a560e3c..084acac 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -850,5 +850,7 @@
<!-- Description for a custom screen zoom level. This shows the requested display
density in raw pixels per inch rather than using a relative description. [CHAR LIMIT=24] -->
<string name="screen_zoom_summary_custom">Custom (<xliff:g id="densityDpi" example="160">%d</xliff:g>)</string>
+ <!-- Label for Help and feedback menu item -->
+ <string name="help_feedback_label">Help & feedback</string>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
new file mode 100644
index 0000000..320cd58
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
@@ -0,0 +1,205 @@
+/*
+ * 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 com.android.settingslib;
+
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources.Theme;
+import android.net.Uri;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MenuItem.OnMenuItemClickListener;
+
+import java.net.URISyntaxException;
+import java.util.Locale;
+
+/**
+ * Functions to easily prepare contextual help menu option items with an intent that opens up the
+ * browser to a particular URL, while taking into account the preferred language and app version.
+ */
+public class HelpUtils {
+ private final static String TAG = HelpUtils.class.getSimpleName();
+
+ private static final int MENU_HELP = Menu.FIRST + 100;
+
+ /**
+ * Help URL query parameter key for the preferred language.
+ */
+ private final static String PARAM_LANGUAGE_CODE = "hl";
+
+ /**
+ * Help URL query parameter key for the app version.
+ */
+ private final static String PARAM_VERSION = "version";
+
+ // Constants for help intents.
+ private static final String EXTRA_CONTEXT = "EXTRA_CONTEXT";
+ private static final String EXTRA_THEME = "EXTRA_THEME";
+ private static final String EXTRA_PRIMARY_COLOR = "EXTRA_PRIMARY_COLOR";
+ private static final String EXTRA_BACKUP_URI = "EXTRA_BACKUP_URI";
+
+ /**
+ * Cached version code to prevent repeated calls to the package manager.
+ */
+ private static String sCachedVersionCode = null;
+
+ /** Static helper that is not instantiable*/
+ private HelpUtils() { }
+
+ public static boolean prepareHelpMenuItem(Activity activity, Menu menu, String helpUri,
+ String backupContext) {
+ MenuItem helpItem = menu.add(0, MENU_HELP, 0, R.string.help_feedback_label);
+ return prepareHelpMenuItem(activity, helpItem, helpUri, backupContext);
+ }
+
+ public static boolean prepareHelpMenuItem(Activity activity, Menu menu, int helpUriResource,
+ String backupContext) {
+ MenuItem helpItem = menu.add(0, MENU_HELP, 0, R.string.help_feedback_label);
+ return prepareHelpMenuItem(activity, helpItem, activity.getString(helpUriResource),
+ backupContext);
+ }
+
+ /**
+ * Prepares the help menu item by doing the following.
+ * - If the helpUrlString is empty or null, the help menu item is made invisible.
+ * - Otherwise, this makes the help menu item visible and sets the intent for the help menu
+ * item to view the URL.
+ *
+ * @return returns whether the help menu item has been made visible.
+ */
+ public static boolean prepareHelpMenuItem(final Activity activity, MenuItem helpMenuItem,
+ String helpUriString, String backupContext) {
+ if (TextUtils.isEmpty(helpUriString)) {
+ // The help url string is empty or null, so set the help menu item to be invisible.
+ helpMenuItem.setVisible(false);
+
+ // return that the help menu item is not visible (i.e. false)
+ return false;
+ } else {
+ final Intent intent = getHelpIntent(activity, helpUriString, backupContext);
+
+ // Set the intent to the help menu item, show the help menu item in the overflow
+ // menu, and make it visible.
+ if (intent != null) {
+ helpMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ try {
+ activity.startActivityForResult(intent, 0);
+ } catch (ActivityNotFoundException exc) {
+ Log.e(TAG, "No activity found for intent: " + intent);
+ }
+ return true;
+ }
+ });
+ helpMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+ helpMenuItem.setVisible(true);
+ } else {
+ helpMenuItem.setVisible(false);
+ return false;
+ }
+
+ // return that the help menu item is visible (i.e., true)
+ return true;
+ }
+ }
+
+ public static Intent getHelpIntent(Context context, String helpUriString,
+ String backupContext) {
+ // Try to handle as Intent Uri, otherwise just treat as Uri.
+ try {
+ Intent intent = Intent.parseUri(helpUriString,
+ Intent.URI_ANDROID_APP_SCHEME | Intent.URI_INTENT_SCHEME);
+ addIntentParameters(context, intent, backupContext);
+ ComponentName component = intent.resolveActivity(context.getPackageManager());
+ if (component != null) {
+ return intent;
+ } else if (intent.hasExtra(EXTRA_BACKUP_URI)) {
+ // This extra contains a backup URI for when the intent isn't available.
+ return getHelpIntent(context, intent.getStringExtra(EXTRA_BACKUP_URI),
+ backupContext);
+ } else {
+ return null;
+ }
+ } catch (URISyntaxException e) {
+ }
+ // The help url string exists, so first add in some extra query parameters.
+ final Uri fullUri = uriWithAddedParameters(context, Uri.parse(helpUriString));
+
+ // Then, create an intent that will be fired when the user
+ // selects this help menu item.
+ Intent intent = new Intent(Intent.ACTION_VIEW, fullUri);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ return intent;
+ }
+
+ private static void addIntentParameters(Context context, Intent intent, String backupContext) {
+ if (!intent.hasExtra(EXTRA_CONTEXT)) {
+ // Insert some context if none exists.
+ intent.putExtra(EXTRA_CONTEXT, backupContext);
+ }
+ intent.putExtra(EXTRA_THEME, 1 /* Light, dark action bar */);
+ Theme theme = context.getTheme();
+ TypedValue typedValue = new TypedValue();
+ theme.resolveAttribute(android.R.attr.colorPrimary, typedValue, true);
+ intent.putExtra(EXTRA_PRIMARY_COLOR, context.getColor(typedValue.resourceId));
+ }
+
+ /**
+ * Adds two query parameters into the Uri, namely the language code and the version code
+ * of the app's package as gotten via the context.
+ * @return the uri with added query parameters
+ */
+ public static Uri uriWithAddedParameters(Context context, Uri baseUri) {
+ Uri.Builder builder = baseUri.buildUpon();
+
+ // Add in the preferred language
+ builder.appendQueryParameter(PARAM_LANGUAGE_CODE, Locale.getDefault().toString());
+
+ // Add in the package version code
+ if (sCachedVersionCode == null) {
+ // There is no cached version code, so try to get it from the package manager.
+ try {
+ // cache the version code
+ PackageInfo info = context.getPackageManager().getPackageInfo(
+ context.getPackageName(), 0);
+ sCachedVersionCode = Integer.toString(info.versionCode);
+
+ // append the version code to the uri
+ builder.appendQueryParameter(PARAM_VERSION, sCachedVersionCode);
+ } catch (NameNotFoundException e) {
+ // Cannot find the package name, so don't add in the version parameter
+ // This shouldn't happen.
+ Log.wtf(TAG, "Invalid package name for context", e);
+ }
+ } else {
+ builder.appendQueryParameter(PARAM_VERSION, sCachedVersionCode);
+ }
+
+ // Build the full uri and return it
+ return builder.build();
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index e86ca82..59637be 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -459,58 +459,40 @@
LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
EnforcedAdmin enforcedAdmin = null;
final int userId = UserHandle.myUserId();
- if (lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
- // userId is managed profile and has a separate challenge, only consider
- // the admins in that user.
- final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId);
+ final UserManager um = UserManager.get(context);
+ final List<UserInfo> profiles = um.getProfiles(userId);
+ final int profilesSize = profiles.size();
+ // As we do not have a separate screen lock timeout settings for work challenge,
+ // we need to combine all profiles maximum time to lock even work challenge is
+ // enabled.
+ for (int i = 0; i < profilesSize; i++) {
+ final UserInfo userInfo = profiles.get(i);
+ final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
if (admins == null) {
- return null;
+ continue;
}
for (ComponentName admin : admins) {
- if (dpm.getMaximumTimeToLock(admin, userId) > 0) {
+ if (dpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
if (enforcedAdmin == null) {
- enforcedAdmin = new EnforcedAdmin(admin, userId);
+ enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
} else {
return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
}
- }
- }
- } else {
- // Return all admins for this user and the profiles that are visible from this
- // user that do not use a separate work challenge.
- final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
- for (UserInfo userInfo : um.getProfiles(userId)) {
- final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
- if (admins == null) {
+ // This same admins could have set policies both on the managed profile
+ // and on the parent. So, if the admin has set the policy on the
+ // managed profile here, we don't need to further check if that admin
+ // has set policy on the parent admin.
continue;
}
- final boolean isSeparateProfileChallengeEnabled =
- lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
- for (ComponentName admin : admins) {
- if (!isSeparateProfileChallengeEnabled) {
- if (dpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
- if (enforcedAdmin == null) {
- enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
- } else {
- return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
- }
- // This same admins could have set policies both on the managed profile
- // and on the parent. So, if the admin has set the policy on the
- // managed profile here, we don't need to further check if that admin
- // has set policy on the parent admin.
- continue;
- }
- }
- if (userInfo.isManagedProfile()) {
- // If userInfo.id is a managed profile, we also need to look at
- // the policies set on the parent.
- DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
- if (parentDpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
- if (enforcedAdmin == null) {
- enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
- } else {
- return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
- }
+ if (userInfo.isManagedProfile()) {
+ // If userInfo.id is a managed profile, we also need to look at
+ // the policies set on the parent.
+ final DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
+ if (parentDpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
+ if (enforcedAdmin == null) {
+ enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
+ } else {
+ return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
}
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 586f269..ca0b86a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -15,7 +15,7 @@
import android.os.BatteryManager;
import android.os.UserManager;
import com.android.internal.util.UserIcons;
-import com.android.settingslib.drawable.CircleFramedDrawable;
+import com.android.settingslib.drawable.UserIconDrawable;
import java.text.NumberFormat;
@@ -73,21 +73,22 @@
/**
* Returns a circular icon for a user.
*/
- public static Drawable getUserIcon(Context context, UserManager um, UserInfo user) {
+ public static UserIconDrawable getUserIcon(Context context, UserManager um, UserInfo user) {
+ final int iconSize = UserIconDrawable.getSizeForList(context);
if (user.isManagedProfile()) {
// We use predefined values for managed profiles
Bitmap b = BitmapFactory.decodeResource(context.getResources(),
com.android.internal.R.drawable.ic_corp_icon);
- return CircleFramedDrawable.getInstance(context, b);
+ return new UserIconDrawable(iconSize).setIcon(b).bake();
}
if (user.iconPath != null) {
Bitmap icon = um.getUserIcon(user.id);
if (icon != null) {
- return CircleFramedDrawable.getInstance(context, icon);
+ return new UserIconDrawable(iconSize).setIcon(icon).bake();
}
}
- return CircleFramedDrawable.getInstance(context, UserIcons.convertToBitmap(
- UserIcons.getDefaultUserIcon(user.id, /* light= */ false)));
+ return new UserIconDrawable(iconSize).setIconDrawable(
+ UserIcons.getDefaultUserIcon(user.id, /* light= */ false)).bake();
}
/** Formats the ratio of amount/total as a percentage. */
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 6052ccd..7f0e27a 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -399,6 +399,9 @@
// Copy previous profile list into removedProfiles
removedProfiles.clear();
removedProfiles.addAll(profiles);
+ if (DEBUG) {
+ Log.d(TAG,"Current Profiles" + profiles.toString());
+ }
profiles.clear();
if (uuids == null) {
@@ -415,6 +418,13 @@
}
}
+ if ((mHfpClientProfile != null) &&
+ BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree_AG) &&
+ BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.Handsfree)) {
+ profiles.add(mHfpClientProfile);
+ removedProfiles.remove(mHfpClientProfile);
+ }
+
if (BluetoothUuid.containsAnyUuid(uuids, A2dpProfile.SINK_UUIDS) &&
mA2dpProfile != null) {
profiles.add(mA2dpProfile);
@@ -425,7 +435,7 @@
mA2dpSinkProfile != null) {
profiles.add(mA2dpSinkProfile);
removedProfiles.remove(mA2dpSinkProfile);
- }
+ }
if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush) &&
mOppProfile != null) {
@@ -461,5 +471,9 @@
profiles.remove(mPbapProfile);
removedProfiles.add(mPbapProfile);
}
+
+ if (DEBUG) {
+ Log.d(TAG,"New Profiles" + profiles.toString());
+ }
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
new file mode 100644
index 0000000..32478a7
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
@@ -0,0 +1,428 @@
+/*
+ * 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.settingslib.drawable;
+
+import android.annotation.NonNull;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.graphics.drawable.Drawable;
+
+import com.android.settingslib.R;
+
+/**
+ * Converts the user avatar icon to a circularly clipped one with an optional badge and frame
+ */
+public class UserIconDrawable extends Drawable implements Drawable.Callback {
+
+ private Drawable mUserDrawable;
+ private Bitmap mUserIcon;
+ private Bitmap mBitmap; // baked representation. Required for transparent border around badge
+ private final Paint mIconPaint = new Paint();
+ private final Paint mPaint = new Paint();
+ private final Matrix mIconMatrix = new Matrix();
+ private float mIntrinsicRadius;
+ private float mDisplayRadius;
+ private float mPadding = 0;
+ private int mSize = 0; // custom "intrinsic" size for this drawable if non-zero
+ private boolean mInvalidated = true;
+ private ColorStateList mTintColor = null;
+ private PorterDuff.Mode mTintMode = PorterDuff.Mode.SRC_ATOP;
+
+ private float mFrameWidth;
+ private float mFramePadding;
+ private ColorStateList mFrameColor = null;
+ private Paint mFramePaint;
+
+ private Drawable mBadge;
+ private Paint mClearPaint;
+ private float mBadgeRadius;
+ private float mBadgeMargin;
+
+ /**
+ * Gets the system default managed-user badge as a drawable
+ * @param context
+ * @return drawable containing just the badge
+ */
+ public static Drawable getManagedUserBadgeDrawable(Context context) {
+ int displayDensity = context.getResources().getDisplayMetrics().densityDpi;
+ return context.getResources().getDrawableForDensity(
+ com.android.internal.R.drawable.ic_corp_user_badge,
+ displayDensity, context.getTheme());
+ }
+
+ /**
+ * Gets the preferred list-item size of this drawable.
+ * @param context
+ * @return size in pixels
+ */
+ public static int getSizeForList(Context context) {
+ return (int) context.getResources().getDimension(R.dimen.circle_avatar_size);
+ }
+
+ public UserIconDrawable() {
+ this(0);
+ }
+
+ /**
+ * Use this constructor if the drawable is intended to be placed in listviews
+ * @param intrinsicSize if 0, the intrinsic size will come from the icon itself
+ */
+ public UserIconDrawable(int intrinsicSize) {
+ super();
+ mIconPaint.setAntiAlias(true);
+ mIconPaint.setFilterBitmap(true);
+ mPaint.setFilterBitmap(true);
+ mPaint.setAntiAlias(true);
+ if (intrinsicSize > 0) {
+ setBounds(0, 0, intrinsicSize, intrinsicSize);
+ setIntrinsicSize(intrinsicSize);
+ }
+ setIcon(null);
+ }
+
+ public UserIconDrawable setIcon(Bitmap icon) {
+ if (mUserDrawable != null) {
+ mUserDrawable.setCallback(null);
+ mUserDrawable = null;
+ }
+ mUserIcon = icon;
+ if (mUserIcon == null) {
+ mIconPaint.setShader(null);
+ mBitmap = null;
+ } else {
+ mIconPaint.setShader(new BitmapShader(icon, Shader.TileMode.CLAMP,
+ Shader.TileMode.CLAMP));
+ }
+ onBoundsChange(getBounds());
+ return this;
+ }
+
+ public UserIconDrawable setIconDrawable(Drawable icon) {
+ if (mUserDrawable != null) {
+ mUserDrawable.setCallback(null);
+ }
+ mUserIcon = null;
+ mUserDrawable = icon;
+ if (mUserDrawable == null) {
+ mBitmap = null;
+ } else {
+ mUserDrawable.setCallback(this);
+ }
+ onBoundsChange(getBounds());
+ return this;
+ }
+
+ public UserIconDrawable setBadge(Drawable badge) {
+ mBadge = badge;
+ if (mBadge != null) {
+ if (mClearPaint == null) {
+ mClearPaint = new Paint();
+ mClearPaint.setAntiAlias(true);
+ mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+ mClearPaint.setStyle(Paint.Style.FILL);
+ }
+ // update metrics
+ onBoundsChange(getBounds());
+ } else {
+ invalidateSelf();
+ }
+ return this;
+ }
+
+ public UserIconDrawable setBadgeIfManagedUser(Context context, int userId) {
+ Drawable badge = null;
+ boolean isManaged = context.getSystemService(DevicePolicyManager.class)
+ .getProfileOwnerAsUser(userId) != null;
+ if (isManaged) {
+ badge = getManagedUserBadgeDrawable(context);
+ }
+ return setBadge(badge);
+ }
+
+ public void setBadgeRadius(float radius) {
+ mBadgeRadius = radius;
+ onBoundsChange(getBounds());
+ }
+
+ public void setBadgeMargin(float margin) {
+ mBadgeMargin = margin;
+ onBoundsChange(getBounds());
+ }
+
+ /**
+ * Sets global padding of icon/frame. Doesn't effect the badge.
+ * @param padding
+ */
+ public void setPadding(float padding) {
+ mPadding = padding;
+ onBoundsChange(getBounds());
+ }
+
+ private void initFramePaint() {
+ if (mFramePaint == null) {
+ mFramePaint = new Paint();
+ mFramePaint.setStyle(Paint.Style.STROKE);
+ mFramePaint.setAntiAlias(true);
+ }
+ }
+
+ public void setFrameWidth(float width) {
+ initFramePaint();
+ mFrameWidth = width;
+ mFramePaint.setStrokeWidth(width);
+ onBoundsChange(getBounds());
+ }
+
+ public void setFramePadding(float padding) {
+ initFramePaint();
+ mFramePadding = padding;
+ onBoundsChange(getBounds());
+ }
+
+ public void setFrameColor(int color) {
+ initFramePaint();
+ mFramePaint.setColor(color);
+ invalidateSelf();
+ }
+
+ public void setFrameColor(ColorStateList colorList) {
+ initFramePaint();
+ mFrameColor = colorList;
+ invalidateSelf();
+ }
+
+ /**
+ * This sets the "intrinsic" size of this drawable. Useful for views which use the drawable's
+ * intrinsic size for layout. It is independent of the bounds.
+ * @param size if 0, the intrinsic size will be set to the displayed icon's size
+ */
+ public void setIntrinsicSize(int size) {
+ mSize = size;
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ if (mInvalidated) {
+ rebake();
+ }
+ if (mBitmap != null) {
+ if (mTintColor == null) {
+ mPaint.setColorFilter(null);
+ } else {
+ int color = mTintColor.getColorForState(getState(), mTintColor.getDefaultColor());
+ if (mPaint.getColorFilter() == null) {
+ mPaint.setColorFilter(new PorterDuffColorFilter(color, mTintMode));
+ } else {
+ ((PorterDuffColorFilter) mPaint.getColorFilter()).setMode(mTintMode);
+ ((PorterDuffColorFilter) mPaint.getColorFilter()).setColor(color);
+ }
+ }
+
+ canvas.drawBitmap(mBitmap, 0, 0, mPaint);
+ }
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ mPaint.setAlpha(alpha);
+ super.invalidateSelf();
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ }
+
+ @Override
+ public void setTintList(ColorStateList tintList) {
+ mTintColor = tintList;
+ super.invalidateSelf();
+ }
+
+ @Override
+ public void setTintMode(@NonNull PorterDuff.Mode mode) {
+ mTintMode = mode;
+ super.invalidateSelf();
+ }
+
+ /**
+ * This 'bakes' the current state of this icon into a bitmap and removes/recycles the source
+ * bitmap/drawable. Use this when no more changes will be made and an intrinsic size is set.
+ * This effectively turns this into a static drawable.
+ */
+ public UserIconDrawable bake() {
+ if (mSize <= 0) {
+ throw new IllegalStateException("Baking requires an explicit intrinsic size");
+ }
+ onBoundsChange(new Rect(0, 0, mSize, mSize));
+ rebake();
+ mFrameColor = null;
+ mFramePaint = null;
+ mClearPaint = null;
+ if (mUserDrawable != null) {
+ mUserDrawable.setCallback(null);
+ mUserDrawable = null;
+ } else if (mUserIcon != null) {
+ mUserIcon.recycle();
+ mUserIcon = null;
+ }
+ return this;
+ }
+
+ private void rebake() {
+ mInvalidated = false;
+
+ if (mBitmap == null || (mUserDrawable == null && mUserIcon == null)) {
+ return;
+ }
+
+ final Canvas canvas = new Canvas(mBitmap);
+ canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+
+ if(mUserDrawable != null) {
+ mUserDrawable.draw(canvas);
+ } else if (mUserIcon != null) {
+ int saveId = canvas.save();
+ canvas.concat(mIconMatrix);
+ canvas.drawCircle(mUserIcon.getWidth() * 0.5f, mUserIcon.getHeight() * 0.5f,
+ mIntrinsicRadius, mIconPaint);
+ canvas.restoreToCount(saveId);
+ }
+
+ if (mFrameColor != null) {
+ mFramePaint.setColor(mFrameColor.getColorForState(getState(), Color.TRANSPARENT));
+ }
+ if ((mFrameWidth + mFramePadding) > 0.001f) {
+ float radius = mDisplayRadius - mPadding - mFrameWidth * 0.5f;
+ canvas.drawCircle(getBounds().exactCenterX(), getBounds().exactCenterY(),
+ radius, mFramePaint);
+ }
+
+ if ((mBadge != null) && (mBadgeRadius > 0.001f)) {
+ final float badgeDiameter = mBadgeRadius * 2f;
+ final float badgeTop = mBitmap.getHeight() - badgeDiameter;
+ float badgeLeft = mBitmap.getWidth() - badgeDiameter;
+
+ mBadge.setBounds((int) badgeLeft, (int) badgeTop,
+ (int) (badgeLeft + badgeDiameter), (int) (badgeTop + badgeDiameter));
+
+ final float borderRadius = mBadge.getBounds().width() * 0.5f + mBadgeMargin;
+ canvas.drawCircle(badgeLeft + mBadgeRadius, badgeTop + mBadgeRadius,
+ borderRadius, mClearPaint);
+
+ mBadge.draw(canvas);
+ }
+ }
+
+ @Override
+ protected void onBoundsChange(Rect bounds) {
+ if (bounds.isEmpty() || (mUserIcon == null && mUserDrawable == null)) {
+ return;
+ }
+
+ // re-create bitmap if applicable
+ float newDisplayRadius = Math.min(bounds.width(), bounds.height()) * 0.5f;
+ int size = (int) (newDisplayRadius * 2);
+ if (mBitmap == null || size != ((int) (mDisplayRadius * 2))) {
+ mDisplayRadius = newDisplayRadius;
+ if (mBitmap != null) {
+ mBitmap.recycle();
+ }
+ mBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+ }
+
+ // update metrics
+ mDisplayRadius = Math.min(bounds.width(), bounds.height()) * 0.5f;
+ final float iconRadius = mDisplayRadius - mFrameWidth - mFramePadding - mPadding;
+ RectF dstRect = new RectF(bounds.exactCenterX() - iconRadius,
+ bounds.exactCenterY() - iconRadius,
+ bounds.exactCenterX() + iconRadius,
+ bounds.exactCenterY() + iconRadius);
+ if (mUserDrawable != null) {
+ Rect rounded = new Rect();
+ dstRect.round(rounded);
+ mIntrinsicRadius = Math.min(mUserDrawable.getIntrinsicWidth(),
+ mUserDrawable.getIntrinsicHeight()) * 0.5f;
+ mUserDrawable.setBounds(rounded);
+ } else if (mUserIcon != null) {
+ // Build square-to-square transformation matrix
+ final float iconCX = mUserIcon.getWidth() * 0.5f;
+ final float iconCY = mUserIcon.getHeight() * 0.5f;
+ mIntrinsicRadius = Math.min(iconCX, iconCY);
+ RectF srcRect = new RectF(iconCX - mIntrinsicRadius, iconCY - mIntrinsicRadius,
+ iconCX + mIntrinsicRadius, iconCY + mIntrinsicRadius);
+ mIconMatrix.setRectToRect(srcRect, dstRect, Matrix.ScaleToFit.FILL);
+ }
+
+ invalidateSelf();
+ }
+
+ @Override
+ public void invalidateSelf() {
+ super.invalidateSelf();
+ mInvalidated = true;
+ }
+
+ @Override
+ public boolean isStateful() {
+ return mFrameColor != null && mFrameColor.isStateful();
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return (mSize <= 0 ? (int) mIntrinsicRadius * 2 : mSize);
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return getIntrinsicWidth();
+ }
+
+ @Override
+ public void invalidateDrawable(@NonNull Drawable who) {
+ invalidateSelf();
+ }
+
+ @Override
+ public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
+ scheduleSelf(what, when);
+ }
+
+ @Override
+ public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
+ unscheduleSelf(what);
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/UserAdapter.java b/packages/SettingsLib/src/com/android/settingslib/drawer/UserAdapter.java
index f9fa805f..750601d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/UserAdapter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/UserAdapter.java
@@ -33,7 +33,7 @@
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import com.android.internal.util.UserIcons;
-import com.android.settingslib.drawable.CircleFramedDrawable;
+import com.android.settingslib.drawable.UserIconDrawable;
import com.android.settingslib.R;
@@ -71,7 +71,8 @@
}
private static Drawable encircle(Context context, Drawable icon) {
- return CircleFramedDrawable.getInstance(context, UserIcons.convertToBitmap(icon));
+ return new UserIconDrawable(UserIconDrawable.getSizeForList(context))
+ .setIconDrawable(icon).bake();
}
}
private ArrayList<UserDetails> data;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 61c9f2b..640399f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1831,14 +1831,11 @@
private void maybeNotifyProfiles(int userId, Uri uri, String name,
Set<String> keysCloned) {
if (keysCloned.contains(name)) {
- List<UserInfo> profiles = mUserManager.getProfiles(userId);
- int size = profiles.size();
- for (int i = 0; i < size; i++) {
- UserInfo profile = profiles.get(i);
+ for (int profileId : mUserManager.getProfileIdsWithDisabled(userId)) {
// the notification for userId has already been sent.
- if (profile.id != userId) {
+ if (profileId != userId) {
mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
- profile.id, 0, uri).sendToTarget();
+ profileId, 0, uri).sendToTarget();
}
}
}
@@ -1942,7 +1939,7 @@
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 126;
+ private static final int SETTINGS_VERSION = 127;
private final int mUserId;
@@ -2167,6 +2164,36 @@
currentVersion = 126;
}
+ if (currentVersion == 126) {
+ // Version 126: copy the primary values of LOCK_SCREEN_SHOW_NOTIFICATIONS and
+ // LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS into managed profile.
+ if (mUserManager.isManagedProfile(userId)) {
+ final SettingsState systemSecureSettings =
+ getSecureSettingsLocked(UserHandle.USER_SYSTEM);
+
+ final Setting showNotifications = systemSecureSettings.getSettingLocked(
+ Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS);
+ if (showNotifications != null) {
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+ secureSettings.insertSettingLocked(
+ Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
+ showNotifications.getValue(),
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+
+ final Setting allowPrivate = systemSecureSettings.getSettingLocked(
+ Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+ if (allowPrivate != null) {
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+ secureSettings.insertSettingLocked(
+ Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
+ allowPrivate.getValue(),
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+ }
+ currentVersion = 127;
+ }
+
// vXXX: Add new settings above this point.
// Return the current version.
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 9e2442c..f5854f5 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -488,5 +488,12 @@
<action android:name="com.android.systemui.action.CLEAR_TUNER" />
</intent-filter>
</receiver>
+
+ <receiver
+ android:name=".statusbar.KeyboardShortcutsReceiver">
+ <intent-filter>
+ <action android:name="android.intent.action.SHOW_KEYBOARD_SHORTCUTS" />
+ </intent-filter>
+ </receiver>
</application>
</manifest>
diff --git a/packages/SystemUI/res/values-h560dp/config.xml b/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml
similarity index 68%
copy from packages/SystemUI/res/values-h560dp/config.xml
copy to packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml
index 8b576b9..20251c2 100644
--- a/packages/SystemUI/res/values-h560dp/config.xml
+++ b/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml
@@ -1,7 +1,7 @@
<?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.
@@ -16,8 +16,7 @@
~ limitations under the License
-->
-<resources>
- <!-- The maximum number of items to be displayed in quick settings -->
- <integer name="quick_settings_detail_max_item_count">6</integer>
-</resources>
-
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_activated="true" android:color="@color/current_user_border_color" />
+ <item android:color="@android:color/transparent" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-h560dp/config.xml b/packages/SystemUI/res/color/qs_user_detail_avatar_tint.xml
similarity index 68%
copy from packages/SystemUI/res/values-h560dp/config.xml
copy to packages/SystemUI/res/color/qs_user_detail_avatar_tint.xml
index 8b576b9..2b75c36 100644
--- a/packages/SystemUI/res/values-h560dp/config.xml
+++ b/packages/SystemUI/res/color/qs_user_detail_avatar_tint.xml
@@ -1,7 +1,7 @@
<?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.
@@ -16,8 +16,7 @@
~ limitations under the License
-->
-<resources>
- <!-- The maximum number of items to be displayed in quick settings -->
- <integer name="quick_settings_detail_max_item_count">6</integer>
-</resources>
-
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:color="@color/qs_tile_disabled_color" />
+ <item android:color="@android:color/transparent" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml b/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml
new file mode 100644
index 0000000..6519673
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_backspace.xml
@@ -0,0 +1,27 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:pathData="M0 0h24v24H0z" />
+ <path android:fillColor="@color/ksh_key_item_color"
+ android:pathData="M22 3H7c-.69 0-1.23 .35 -1.59 .88 L0 12l5.41 8.11c.36 .53 .9 .89
+1.59 .89 h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-3 12.59L17.59 17 14 13.41 10.41 17 9 15.59
+12.59 12 9 8.41 10.41 7 14 10.59 17.59 7 19 8.41 15.41 12 19 15.59z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_down.xml b/packages/SystemUI/res/drawable/ic_ksh_key_down.xml
new file mode 100644
index 0000000..25a2560
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_down.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
+ -->
+<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="@color/ksh_key_item_color"
+ android:pathData="M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z" />
+ <path android:pathData="M0-.75h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_enter.xml b/packages/SystemUI/res/drawable/ic_ksh_key_enter.xml
new file mode 100644
index 0000000..599f350
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_enter.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
+ -->
+<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="@color/ksh_key_item_color"
+ android:pathData="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_left.xml b/packages/SystemUI/res/drawable/ic_ksh_key_left.xml
new file mode 100644
index 0000000..038187e8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_left.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
+ -->
+<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="@color/ksh_key_item_color"
+ android:pathData="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" />
+ <path android:pathData="M0 0h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_meta.xml b/packages/SystemUI/res/drawable/ic_ksh_key_meta.xml
new file mode 100644
index 0000000..1e2195e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_meta.xml
@@ -0,0 +1,28 @@
+<?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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="@color/ksh_key_item_color"
+ android:pathData="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91
+3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27 .28 v.79l5 4.99L20.49
+19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5
+14z" />
+ <path android:pathData="M0 0h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_right.xml b/packages/SystemUI/res/drawable/ic_ksh_key_right.xml
new file mode 100644
index 0000000..f2d7315
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_right.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
+ -->
+<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="@color/ksh_key_item_color"
+ android:pathData="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" />
+ <path android:pathData="M0 0h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_ksh_key_up.xml b/packages/SystemUI/res/drawable/ic_ksh_key_up.xml
new file mode 100644
index 0000000..36a83b1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_ksh_key_up.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
+ -->
+<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="@color/ksh_key_item_color"
+ android:pathData="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" />
+ <path android:pathData="M0 0h24v24H0z" />
+</vector>
diff --git a/packages/SystemUI/res/values-h560dp/config.xml b/packages/SystemUI/res/drawable/ksh_key_item_background.xml
similarity index 69%
rename from packages/SystemUI/res/values-h560dp/config.xml
rename to packages/SystemUI/res/drawable/ksh_key_item_background.xml
index 8b576b9..75ff30d 100644
--- a/packages/SystemUI/res/values-h560dp/config.xml
+++ b/packages/SystemUI/res/drawable/ksh_key_item_background.xml
@@ -1,7 +1,6 @@
<?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.
@@ -15,9 +14,8 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<resources>
- <!-- The maximum number of items to be displayed in quick settings -->
- <integer name="quick_settings_detail_max_item_count">6</integer>
-</resources>
-
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@color/ksh_key_item_background" />
+ <corners android:radius="2dp" />
+</shape>
diff --git a/packages/SystemUI/res/layout/battery_detail.xml b/packages/SystemUI/res/layout/battery_detail.xml
index af3e379..1f24ab0 100644
--- a/packages/SystemUI/res/layout/battery_detail.xml
+++ b/packages/SystemUI/res/layout/battery_detail.xml
@@ -26,10 +26,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="72dp"
- android:paddingBottom="@dimen/battery_detail_graph_space_top"
- android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/colorAccent" />
+ <com.android.systemui.ResizingSpace
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/battery_detail_graph_space_top" />
+
<com.android.settingslib.graph.UsageView
android:id="@+id/battery_usage"
android:layout_width="match_parent"
@@ -40,11 +43,14 @@
android:colorAccent="?android:attr/colorAccent"
systemui:textColor="#66FFFFFF" />
+ <com.android.systemui.ResizingSpace
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/battery_detail_graph_space_bottom" />
+
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider"
- android:layout_marginTop="@dimen/battery_detail_graph_space_bottom"
android:layout_marginBottom="8dp" />
<RelativeLayout
diff --git a/packages/SystemUI/res/layout/forced_resizable_activity.xml b/packages/SystemUI/res/layout/forced_resizable_activity.xml
index df245bc..3c778c4 100644
--- a/packages/SystemUI/res/layout/forced_resizable_activity.xml
+++ b/packages/SystemUI/res/layout/forced_resizable_activity.xml
@@ -18,10 +18,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <TextView
+ <include
+ layout="@*android:layout/transient_notification"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:text="@string/forced_resizable_info_text"
- android:textColor="#ffffff"/>
+ android:layout_gravity="center"/>
</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
index 9c2c0ab..63b759b 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
@@ -15,15 +15,25 @@
~ limitations under the License
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/keyboard_shortcuts_keyword_wrapper"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:minHeight="48dp"
android:paddingStart="24dp"
android:paddingEnd="24dp"
android:paddingBottom="8dp">
+ <ImageView
+ android:id="@+id/keyboard_shortcuts_icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_marginEnd="32dp"
+ android:layout_gravity="center_vertical"
+ android:visibility="gone"
+ android:layout_alignParentStart="true"
+ android:layout_centerVertical="true"/>
<TextView
android:id="@+id/keyboard_shortcuts_keyword"
+ android:layout_toEndOf="@+id/keyboard_shortcuts_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingEnd="12dp"
@@ -32,7 +42,8 @@
android:maxLines="5"
android:singleLine="false"
android:scrollHorizontally="false"
- android:layout_alignParentStart="true"/>
+ android:layout_alignParentStart="true"
+ android:layout_centerVertical="true"/>
<com.android.systemui.statusbar.KeyboardShortcutKeysLayout
android:id="@+id/keyboard_shortcuts_item_container"
android:layout_toEndOf="@+id/keyboard_shortcuts_keyword"
@@ -41,5 +52,6 @@
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:textSize="14sp"
- android:scrollHorizontally="false"/>
+ android:scrollHorizontally="false"
+ android:layout_centerVertical="true"/>
</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml
new file mode 100644
index 0000000..5db6789
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml
@@ -0,0 +1,24 @@
+<?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
+ -->
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/ksh_item_padding"
+ android:layout_marginStart="@dimen/ksh_item_margin_start"
+ android:scaleType="fitXY"
+ android:background="@drawable/ksh_key_item_background"/>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
index 5002c12..31a8773 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
@@ -17,9 +17,10 @@
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginStart="4dp"
- android:padding="4dp"
- android:background="#EEEEEE"
- android:textColor="#8C000000"
+ android:padding="@dimen/ksh_item_padding"
+ android:layout_marginStart="@dimen/ksh_item_margin_start"
+ android:background="@drawable/ksh_key_item_background"
+ android:textColor="@color/ksh_key_item_color"
android:singleLine="true"
- android:textSize="14sp"/>
+ android:gravity="center"
+ android:textSize="@dimen/ksh_item_text_size"/>
diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml b/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
index c6e453a..d685528 100644
--- a/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
+++ b/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
@@ -33,14 +33,18 @@
<TextView android:id="@+id/user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginEnd="16dp"
+ android:layout_marginEnd="13dp"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher.UserName"
/>
<com.android.systemui.statusbar.phone.UserAvatarView android:id="@+id/user_picture"
- android:layout_width="@dimen/max_avatar_size"
- android:layout_height="@dimen/max_avatar_size"
+ android:layout_width="@dimen/framed_avatar_size"
+ android:layout_height="@dimen/framed_avatar_size"
android:contentDescription="@null"
+ android:backgroundTint="@color/qs_user_detail_avatar_tint"
+ android:backgroundTintMode="src_atop"
sysui:frameWidth="@dimen/keyguard_user_switcher_border_thickness"
- sysui:framePadding="6dp"
- sysui:activeFrameColor="@color/current_user_border_color" />
+ sysui:framePadding="2.5dp"
+ sysui:badgeDiameter="18dp"
+ sysui:badgeMargin="1dp"
+ sysui:frameColor="@color/qs_user_detail_avatar_frame" />
</com.android.systemui.qs.tiles.UserDetailItemView>
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index 3358a18..af2a285 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -25,13 +25,15 @@
android:visibility="invisible"
android:orientation="vertical">
+ <com.android.systemui.ResizingSpace
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/qs_detail_margin_top" />
+
<include
android:id="@+id/qs_detail_header"
layout="@layout/qs_detail_header"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="28dp"
- />
+ android:layout_height="wrap_content" />
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:id="@+id/qs_detail_header_progress"
diff --git a/packages/SystemUI/res/layout/qs_detail_items.xml b/packages/SystemUI/res/layout/qs_detail_items.xml
index c22e42c..f1a8d63 100644
--- a/packages/SystemUI/res/layout/qs_detail_items.xml
+++ b/packages/SystemUI/res/layout/qs_detail_items.xml
@@ -16,17 +16,19 @@
-->
<!-- extends FrameLayout -->
<com.android.systemui.qs.QSDetailItems xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:sysui="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingTop="16dp"
+ android:paddingTop="@dimen/qs_detail_items_padding_top"
android:paddingStart="16dp"
android:paddingEnd="16dp">
- <LinearLayout
+ <com.android.systemui.qs.AutoSizingList
android:id="@android:id/list"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" />
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ sysui:itemHeight="@dimen/qs_detail_item_height" />
<LinearLayout
android:id="@android:id/empty"
@@ -48,9 +50,4 @@
android:layout_marginTop="20dp"
android:textAppearance="@style/TextAppearance.QS.DetailEmpty" />
</LinearLayout>
-
- <View
- android:id="@+id/min_height_spacer"
- android:layout_width="match_parent"
- android:layout_height="0dp"/>
-</com.android.systemui.qs.QSDetailItems>
\ No newline at end of file
+</com.android.systemui.qs.QSDetailItems>
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index b0dca9a..cce9c0f 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -26,9 +26,7 @@
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:textAppearance="@style/TextAppearance.QS.TileLabel"
android:clickable="false" />
<ImageView android:id="@+id/restricted_padlock"
android:layout_width="@dimen/qs_tile_text_size"
diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml
index 661d74a..58fc069 100644
--- a/packages/SystemUI/res/layout/qs_user_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml
@@ -33,12 +33,16 @@
<com.android.systemui.statusbar.phone.UserAvatarView
android:id="@+id/user_picture"
- android:layout_width="@dimen/max_avatar_size"
- android:layout_height="@dimen/max_avatar_size"
- android:layout_marginBottom="10dp"
+ android:layout_width="@dimen/framed_avatar_size"
+ android:layout_height="@dimen/framed_avatar_size"
+ android:layout_marginBottom="7dp"
+ android:backgroundTint="@color/qs_user_detail_avatar_tint"
+ android:backgroundTintMode="src_atop"
systemui:frameWidth="2dp"
- systemui:framePadding="6dp"
- systemui:activeFrameColor="@color/current_user_border_color"/>
+ systemui:framePadding="2.5dp"
+ systemui:badgeDiameter="18dp"
+ systemui:badgeMargin="1dp"
+ systemui:frameColor="@color/qs_user_detail_avatar_frame"/>
<LinearLayout
android:layout_width="wrap_content"
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 b88846b..5d3b5ff 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -84,6 +84,7 @@
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:contentDescription="@string/accessibility_quick_settings_expand"
android:padding="12dp" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 3dca77d..7c4ce15 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -55,6 +55,7 @@
android:layout_width="match_parent"
android:layout_height="@dimen/heads_up_scrim_height"
android:background="@drawable/heads_up_scrim"
+ sysui:ignoreRightInset="true"
android:importantForAccessibility="no"/>
<include layout="@layout/status_bar"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 3fa6245..8dff1c7 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Maak <xliff:g id="APP">%s</xliff:g> toe."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> verwerp."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle onlangse programme is toegemaak."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Maak <xliff:g id="APP">%s</xliff:g>-programinligting oop."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Begin tans <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Kennisgewing is toegemaak."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is die volumedialoog"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Raak om die oorspronklike terug te stel."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Jy gebruik tans jou werkprofiel"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Stelsel-UI-ontvanger"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Wys persentasie van ingebedde battery"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Wys batteryvlakpersentasie binne die statusbalkikoon wanneer dit nie laai nie"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Program sal dalk nie met multivenster werk nie"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posisie <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dubbeltik om te wysig."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dubbeltik om by te voeg."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posisie <xliff:g id="POSITION">%1$d</xliff:g>. Dubbeltik om te kies."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is verwyder"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is na posisie <xliff:g id="POSITION">%2$d</xliff:g> geskuif"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Kitsinstellingswysiger."</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>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index eb5d256..7f6c6b2 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> አስወግድ።"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ተሰናብቷል::"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ሁሉም የቅርብ ጊዜ ማመልከቻዎች ተሰናብተዋል።"</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"የ<xliff:g id="APP">%s</xliff:g> መተግበሪያ መረጃውን ይክፈቱ።"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> በመጀመር ላይ።"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"ማሳወቂያ ተወግዷል።"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> የድምጽ መጠን መገናኛው ነው"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"የመጀመሪያውን ወደነበረበት ለመመለስ ይንኩ።"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"የስራ መገለጫዎን እየተጠቀሙ ነው"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"የስርዓት በይነገጽ መቃኛ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"የተቀላቀለ የባትሪ አጠቃቀም መቶኛ አሳይ"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ኃይል በማይሞላበት ጊዜ በሁነታ አሞሌ አዶ ውስጥ የባትሪ ደረጃ መቶኛን አሳይ"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"መተግበሪያ ከብዝሃ-መስኮት ጋር ላይሠራ ይችላል"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ቦታ <xliff:g id="POSITION">%1$d</xliff:g>፣ <xliff:g id="TILE_NAME">%2$s</xliff:g>። ለማርትዕ ሁለቴ መታ ያድርጉ።"</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>። ለማከል ሁለቴ መታ ያድርጉ።"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ቦታ <xliff:g id="POSITION">%1$d</xliff:g>። ለመምረጥ ሁለቴ መታ ያድርጉ።"</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ተወግዷል"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ወደ ቦታ <xliff:g id="POSITION">%2$d</xliff:g> ተወስዷል"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"የፈጣን ቅንብሮች አርታዒ።"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"መተግበሪያ ከተከፈለ ማያ ገጽ ጋር ላይሠራ ይችላል"</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"መተግበሪያው የተከፈለ ማያ ገጽን አይደግፍም።"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 82a772c..1b1d280 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -172,8 +172,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"إزالة <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"تمت إزالة <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"تم تجاهل كل التطبيقات المستخدمة مؤخرًا."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"فتح معلومات تطبيق <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"جارٍ بدء <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"تم تجاهل الإشعار."</string>
@@ -425,6 +424,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> هو مربع حوار مستوى الصوت"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"المس لاستعادة الإعداد الأصلي."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"أنت تستخدم ملفك الشخصي للعمل"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"أداة ضبط واجهة مستخدم النظام"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"عرض نسبة البطارية المدمجة"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"عرض نسبة مستوى البطارية داخل رمز شريط الحالة أثناء عدم الشحن"</string>
@@ -499,7 +504,7 @@
<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>
+ <string name="color_revert_message" msgid="9116001069397996691">"يمكن أن تتسبب بعض إعدادات الألوان في تعطيل إمكانية استخدام الجهاز. يمكنك النقر على \"موافق\" لتأكيد إعدادات الألوان هذه، وإلا فستتم إعادة تعيين هذه الإعدادات بعد ۱۰ ثوانٍ."</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>
@@ -600,7 +605,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"يمكن ألا يعمل التطبيق مع وضع النوافذ المتعددة."</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"الموضع <xliff:g id="POSITION">%1$d</xliff:g>، <xliff:g id="TILE_NAME">%2$s</xliff:g>. انقر نقرًا مزدوجًا للتعديل."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. انقر نقرًا مزدوجًا للإضافة."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"الموضع <xliff:g id="POSITION">%1$d</xliff:g>. انقر نقرًا مزدوجًا للتحديد."</string>
@@ -610,4 +614,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"تمت إزالة <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"تم نقل <xliff:g id="TILE_NAME">%1$s</xliff:g> إلى الموضع <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"برنامج تعديل الإعدادات السريعة."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"يمكن ألا يعمل التطبيق مع وضع تقسيم الشاشة."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"التطبيق لا يتيح تقسيم الشاشة."</string>
</resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 59b3141..4fee4ec 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> kənarlaşdırın."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> çıxarıldı."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Bütün son tətbiqlər kənarlaşdırıldı."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> tətbiqi haqqında məlumatı açın."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> başlanır."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Bildiriş uzaqlaşdırıldı."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> proqramı səs səviyyəsi dialoqudur"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Orijinalı bərpa etmək üçün toxun."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"İş profilinizi istifadə edirsiniz"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Daxil batareya faizini göstərin"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Elektrik şəbəsinə qoşulu olmayan zaman batareya səviyyəsini status paneli ikonası daxilində göstərin"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Tətbiq çoxsaylı pəncərə ilə işləməyə bilər."</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g> mövqeyi, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Redaktə etmək üçün iki dəfə tıklayın."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Əlavə etmək üçün iki dəfə tıklayın."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g> mövqeyi. Seçmək üçün iki dəfə tıklayın."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> silindi"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> mövqeyinə köçürüldü"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Sürətli ayarlar redaktoru."</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>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 0945885..4d22d2e 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -169,8 +169,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Odbacite <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> je odbačena."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Sve nedavno korišćene aplikacije su odbačene."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Otvorite informacije o aplikaciji <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Pokrećemo <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obaveštenje je odbačeno."</string>
@@ -422,6 +421,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je dijalog za jačinu zvuka"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Dodirnite da biste vratili original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Koristite profil za Work"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Tjuner za korisnički interfejs sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Prikazuj ugrađeni procenat baterije"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Prikazivanje nivoa napunjenosti baterije u procentima unutar ikone na statusnoj traci kada se baterija ne puni"</string>
@@ -597,7 +602,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Aplikacija možda neće funkcionisati sa više prozora"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>. pozicija, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dvaput dodirnite da biste izmenili."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dvaput dodirnite da biste dodali."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g>. pozicija. Dvaput dodirnite da biste izabrali."</string>
@@ -607,4 +611,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Pločica <xliff:g id="TILE_NAME">%1$s</xliff:g> je uklonjena"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Pločica <xliff:g id="TILE_NAME">%1$s</xliff:g> je premeštena na <xliff:g id="POSITION">%2$d</xliff:g>. poziciju"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Uređivač za Brza podešavanja."</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>
</resources>
diff --git a/packages/SystemUI/res/values-be-rBY/strings.xml b/packages/SystemUI/res/values-be-rBY/strings.xml
index 726a0e7..5f3aa55 100644
--- a/packages/SystemUI/res/values-be-rBY/strings.xml
+++ b/packages/SystemUI/res/values-be-rBY/strings.xml
@@ -172,8 +172,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Выдаліць <xliff:g id="APP">%s</xliff:g> са спіса апошніх."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> выдалены."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Усе апошнія праграмы адхілены."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Адкрыць інфармацыю пра праграму <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Запускаецца <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Апавяшчэнне прапушчана."</string>
@@ -425,6 +424,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> з\'яўляецца дыялогам гучнасці"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Націсніце, каб аднавіць арыгінал."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Вы выкарыстоўваеце свой працоўны профіль"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Наладка сістэмнага інтэрфейсу карыстальніка"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Паказваць працэнт зараду акумулятара"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Паказваць працэнт узроўню акумулятара ўнутры значка панэлі стану, калі ён не зараджаецца"</string>
@@ -535,7 +540,7 @@
<string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"Апошнія"</string>
<string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"Назад"</string>
<string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Апавяшчэнні"</string>
- <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Спалучэнні клавіш для хуткага доступу"</string>
+ <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Спалучэнні клавіш"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Пераключэнне рэжыму ўводу"</string>
<string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Праграмы"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Памочнік"</string>
@@ -600,7 +605,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Праграма можа не працаваць у рэжыме некалькіх вокнаў"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Месца: <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Краніце двойчы, каб рэдагаваць."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Краніце двойчы, каб дадаць."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Месца: <xliff:g id="POSITION">%1$d</xliff:g>. Краніце двойчы, каб выбраць."</string>
@@ -610,4 +614,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Плітка <xliff:g id="TILE_NAME">%1$s</xliff:g> выдалена"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> перамешчана ў наступнае месца: <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Рэдактар хуткіх налад."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Праграма можа не працаваць у рэжыме дзялення экрана."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Праграма не падтрымлівае функцыю дзялення экрана."</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 479087a..7aa52fe 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Отхвърляне на <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложението <xliff:g id="APP">%s</xliff:g> е отхвърлено."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Всички скорошни приложения са отхвърлени."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Отворете информацията за приложението <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> се стартира."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Известието е отхвърлено."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> изпълнява ролята на диалоговия прозорец за силата на звука"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Докоснете, за да възстановите оригинала."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Използвате служебния си потребителски профил"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Тунер на системния потребителски интерфейс"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Показване на процента на вградената батерия"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Показване на процента на нивото на батерията в иконата на лентата на състоянието, когато не се зарежда"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Приложението може да не работи в режим за няколко прозореца"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>, „<xliff:g id="TILE_NAME">%2$s</xliff:g>“. Докоснете двукратно, за да редактирате."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"„<xliff:g id="TILE_NAME">%1$s</xliff:g>“. Докоснете двукратно, за да добавите."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>. Докоснете двукратно, за да изберете."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Премахнахте „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Преместихте „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ на позиция <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Редактор за бързи настройки."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Приложението може да не работи в режим на разделен екран."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Приложението не поддържа разделен екран."</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index ccbcb6e..6bf0cae 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> খারিজ করুন।"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> খারিজ করা হয়েছে৷"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"সমস্ত সাম্প্রতিক অ্যাপ্লিকেশন খারিজ করা হয়েছে।"</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> অ্যাপ্লিকেশানের তথ্য খুলবে৷"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> তারাঙ্কিত করা হচ্ছে।"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"বিজ্ঞপ্তি খারিজ করা হয়েছে৷"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> হল ভলিউম ডায়লগ"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"আসলটি পুনঃস্থাপন করতে স্পর্শ করুন৷"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"আপনি আপনার কাজের প্রোফাইল ব্যবহার করছেন"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"সিস্টেম UI টিউনার"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"এম্বেড করা ব্যাটারির শতকরা হার দেখায়"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"যখন চার্জ করা হবে না তখন স্থিতি দন্ডের আইকনের ভিতরে ব্যাটারি স্তরের শতকার হার দেখায়"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"একাধিক-উইন্ডো দিয়ে অ্যাপ কাজ নাও করতে পারে"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g> অবস্থান, <xliff:g id="TILE_NAME">%2$s</xliff:g>৷ সম্পাদনা করতে দুবার আলতো চাপুন৷"</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>৷ যোগ করতে দুবার আলতো চাপুন৷"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g> অবস্থান৷ নির্বাচন করতে দুবার আলতো চাপুন৷"</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> মোছা হয়েছে"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> এ সরানো হয়েছে"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"দ্রুত সেটিংস সম্পাদক৷"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"অ্যাপ্লিকেশানটি বিভক্ত স্ক্রীনে কাজ নাও করতে পারে৷"</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"অ্যাপ্লিকেশান বিভক্ত-স্ক্রীন সমর্থন করে না৷"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
index c5398a2..3b438d6 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -169,8 +169,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Odbaci aplikaciju <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> uklonjena."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Sve nedavno korištene aplikacije su odbačene."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Otvaranje informacija o aplikaciji <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Pokrećem aplikaciju <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obavještenje je uklonjeno."</string>
@@ -422,6 +421,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je dijaloški okvir za jačinu zvuka"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Dodirnite da vratite original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Koristite svoj profil za posao"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Podešavač za korisničko sučelje sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Prikaži ugrađeni postotak baterije"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Prikazuje postotak nivoa baterije unutar ikone na statusnoj traci kada se baterija ne puni"</string>
@@ -597,7 +602,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Aplikacija možda neće raditi s višestrukim prozorom"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Pozicija <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dvaput dodirnite za uređivanje."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g> Dvaput dodirnite za dodavanje."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Pozicija <xliff:g id="POSITION">%1$d</xliff:g>. Dvaput dodirnite za odabir."</string>
@@ -607,4 +611,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> je uklonjen"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> je premješten na poziciju <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Uređivanje brzih postavki"</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>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index b7fffb7..99cc5a9 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ignora <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"S\'ha omès <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"S\'han descartat totes les aplicacions recents."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Obre la informació sobre l\'aplicació <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"S\'està iniciant <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificació omesa."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> és el diàleg de volum"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Toca per restaurar l\'original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Estàs utilitzant el perfil professional"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Personalitzador d\'interfície d\'usuari"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostra el percentatge de la bateria inserit"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostra el percentatge del nivell de bateria dins de la icona de la barra d\'estat quan no s\'estigui carregant"</string>
@@ -539,7 +544,7 @@
<string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactes"</string>
<string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Correu electrònic"</string>
<string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
- <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Music"</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
<string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendari"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Mostra amb els controls de volum"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"És possible que l\'aplicació no funcioni amb el Mode multifinestra"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posició <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Fes doble toc per editar-la."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Fes doble toc per afegir-ho."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posició <xliff:g id="POSITION">%1$d</xliff:g>. Fes doble toc per seleccionar-la."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha suprimit"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> s\'ha mogut a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de la configuració ràpida."</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>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index b707ece..3bc73f6 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -170,8 +170,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Zavřít aplikaci <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikace <xliff:g id="APP">%s</xliff:g> byla odebrána."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Všechny naposledy použité aplikace byly odstraněny."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Otevře informace o aplikaci <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Spouštění aplikace <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Oznámení je zavřeno."</string>
@@ -423,6 +422,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je dialog hlasitosti"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Klepnutím obnovíte originál."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Používáte pracovní profil"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Nástroj na ladění uživatelského rozhraní systému"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Zobrazovat vložené procento nabití baterie"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Když neprobíhá nabíjení, zobrazit v ikoně na stavovém řádku procento nabití baterie"</string>
@@ -598,7 +603,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Aplikace nemusí v režimu několika oken fungovat."</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Pozice <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dvojitým klepnutím ji upravíte."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dlaždici přidáte dvojitým klepnutím."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Pozice <xliff:g id="POSITION">%1$d</xliff:g>. Dvojitým klepnutím ji vyberete."</string>
@@ -608,4 +612,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Dlaždice <xliff:g id="TILE_NAME">%1$s</xliff:g> byla odstraněna"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Dlaždice <xliff:g id="TILE_NAME">%1$s</xliff:g> byla přesunuta na pozici <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor rychlého nastavení"</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>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 7a25141..3b47e24 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Afvis <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> er annulleret."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle de seneste applikationer er lukket."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Åbn appoplysningerne for <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> startes."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Underretningen er annulleret."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er dialogboksen for lydstyrke"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Tryk for at gendanne originalen."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Du bruger din arbejdsprofil"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Vis procent for det indbyggede batteri"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Vis procenttallet for batteriniveauet i ikonet for statusbjælken, når der ikke oplades"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Appen fungerer muligvis ikke i Multivindue"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Tryk to gange for at redigere."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Tryk to gange for at tilføje."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position <xliff:g id="POSITION">%1$d</xliff:g>. Tryk to gange for at vælge."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> fjernes"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> blev flyttet til position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Redigeringsværktøj for Hurtige indstillinger."</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>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index e10eb64..436e7c4 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> beenden"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> entfernt"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle kürzlich verwendeten Apps wurden entfernt."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Infos zur App \"<xliff:g id="APP">%s</xliff:g>\" öffnen."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> wird gestartet."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Benachrichtigung geschlossen"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> regelt die Lautstärke."</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Zum Wiederherstellen des Originals hier tippen"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Du verwendest dein Arbeitsprofil."</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Eingebettete Akku-Prozentzahl anzeigen"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Prozentzahl für Akkustand in Statusleistensymbol anzeigen, wenn das Gerät nicht geladen wird"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"App funktioniert im Mehrfenstermodus möglicherweise nicht"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Zum Bearbeiten doppeltippen."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Zum Hinzufügen doppeltippen."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position <xliff:g id="POSITION">%1$d</xliff:g>. Zum Auswählen doppeltippen."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> wurde entfernt"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> an Position <xliff:g id="POSITION">%2$d</xliff:g> verschoben"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor für Schnelleinstellungen."</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>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 5ec3133..8809cdf 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Παράβλεψη <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Απορρίφθηκαν <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Έγινε παράβλεψη όλων των πρόσφατων εφαρμογών."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Άνοιγμα πληροφοριών εφαρμογής <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Έναρξη <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Η ειδοποίηση έχει απορριφθεί."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> αποτελεί το παράθυρο διαλόγου ελέγχου έντασης"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Αγγίξτε για επαναφορά αρχικού."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Χρησιμοποιείτε το προφίλ εργασίας σας"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Εμφάνιση ποσοστού ενσωματωμένης μπαταρίας"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Εμφάνιση ποσοστού επιπέδου μπαταρίας μέσα στο εικονίδιο της γραμμής κατάστασης όταν δεν γίνεται φόρτιση"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Η εφαρμογή ενδέχεται να μη λειτουργεί με τη λειτουργία πολλαπλών παραθύρων"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Θέση <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Πατήστε δύο φορές για επεξεργασία."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Πατήστε δύο φορές για προσθήκη."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Θέση <xliff:g id="POSITION">%1$d</xliff:g>. Πατήστε δύο φορές για επιλογή."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Το <xliff:g id="TILE_NAME">%1$s</xliff:g> καταργείται"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Το <xliff:g id="TILE_NAME">%1$s</xliff:g> μετακινήθηκε στη θέση <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Επεξεργασία γρήγορων ρυθμίσεων."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Δεν είναι δυνατή η λειτουργία της εφαρμογής με διαχωρισμό οθόνης."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Η εφαρμογή δεν υποστηρίζει διαχωρισμό οθόνης."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index f08894f..218cbbd 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Dismiss <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"All recent applications dismissed."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Open <xliff:g id="APP">%s</xliff:g> application info."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Starting <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification dismissed."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"You\'re using your work profile"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Show embedded battery percentage"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Show battery level percentage inside the status bar icon when not charging"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"App may not work with multi-window"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position <xliff:g id="POSITION">%1$d</xliff:g>. Double tap to select."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is removed"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> moved to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Quick settings editor."</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>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index f08894f..218cbbd 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Dismiss <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"All recent applications dismissed."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Open <xliff:g id="APP">%s</xliff:g> application info."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Starting <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification dismissed."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"You\'re using your work profile"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Show embedded battery percentage"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Show battery level percentage inside the status bar icon when not charging"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"App may not work with multi-window"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position <xliff:g id="POSITION">%1$d</xliff:g>. Double tap to select."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is removed"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> moved to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Quick settings editor."</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>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index f08894f..218cbbd 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Dismiss <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"All recent applications dismissed."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Open <xliff:g id="APP">%s</xliff:g> application info."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Starting <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification dismissed."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"You\'re using your work profile"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Show embedded battery percentage"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Show battery level percentage inside the status bar icon when not charging"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"App may not work with multi-window"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position <xliff:g id="POSITION">%1$d</xliff:g>. Double tap to select."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is removed"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> moved to position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Quick settings editor."</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>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index b5a10e1..c612431 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rechazar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartada."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Se descartaron todas las aplicaciones recientes."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Abre la información de la aplicación de <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación ignorada"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> es el cuadro de diálogo de volumen."</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar el original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Estás usando tu perfil de trabajo"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Sintonizador de IU del sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentaje de la batería integrada"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostrar porcentaje del nivel de batería en el ícono de la barra de estado cuando no se está cargando"</string>
@@ -538,7 +543,7 @@
<string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Navegador"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Contactos"</string>
<string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Correo electrónico"</string>
- <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"MI"</string>
+ <string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"IM"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Música"</string>
<string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendario"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Es posible que la app no se ejecute con la función Multiventana"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posición <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Presiona dos veces para editarla."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Presiona dos veces para agregarlo."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posición <xliff:g id="POSITION">%1$d</xliff:g>. Presiona dos veces para seleccionarla."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Se quitó <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Se movió <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de Configuración rápida"</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>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index d8affc9..c6ef4cc 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ignorar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Se ha eliminado <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Se han ignorado todas las aplicaciones recientes."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Abre la información de la aplicación <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación ignorada"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> es el cuadro de diálogo de volumen"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar la versión original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Estás usando tu perfil de trabajo"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Configurador de IU del sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentaje de batería insertado"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostrar el porcentaje del nivel de batería en el icono de la barra de estado cuando no se esté cargando"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Es posible que la aplicación no funcione con el modo multiventana"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posición <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toca dos veces para cambiarla."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toca dos veces para añadirlo."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posición <xliff:g id="POSITION">%1$d</xliff:g>. Toca dos veces para seleccionarla."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> se ha quitado"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> se ha movido a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de ajustes rápidos."</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>
</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index f18bf05..664748b 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rakendusest <xliff:g id="APP">%s</xliff:g> loobumine."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Loobusite rakendusest <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Kõikidest hiljutistest rakendustest on loobutud"</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Rakenduse <xliff:g id="APP">%s</xliff:g> teabe avamine."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Rakenduse <xliff:g id="APP">%s</xliff:g> käivitamine."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g>, <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Märguandest on loobutud."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> on helitugevuse dialoog"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Originaali taastamiseks puudutage."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Kasutate oma tööprofiili"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Süsteemi kasutajaliidese tuuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Kuva lisatud akutaseme protsent"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Akutaseme protsendi kuvamine olekuriba ikoonil, kui akut ei laeta"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Rakendus ei pruugi mitme akna režiimis töötada"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Asend <xliff:g id="POSITION">%1$d</xliff:g>, paan <xliff:g id="TILE_NAME">%2$s</xliff:g>. Topeltpuudutage muutmiseks."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Topeltpuudutage lisamiseks."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Asend <xliff:g id="POSITION">%1$d</xliff:g>. Topeltpuudutage valimiseks."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Paan <xliff:g id="TILE_NAME">%1$s</xliff:g> eemaldati"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Paan <xliff:g id="TILE_NAME">%1$s</xliff:g> teisaldati asendisse <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Kiirseadete redigeerija."</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>
</resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 575f8749..287f73f 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Baztertu <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> baztertu da."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Azken aplikazio guztiak baztertu da."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Ireki <xliff:g id="APP">%s</xliff:g> aplikazioari buruzko informazioa."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> hasten."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Jakinarazpena baztertu da."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> da bolumenaren leihoa"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Ukitu jatorrizkora leheneratzeko"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Work profila erabiltzen ari zara"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Sistemako erabiltzaile-interfazearen konfiguratzailea"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Erakutsi txertatutako bateriaren ehunekoa"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Erakutsi bateria-mailaren ehunekoa egoera-barraren ikonoan, kargatzen ari ez denean"</string>
@@ -537,11 +542,11 @@
<string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Laguntzailea"</string>
<string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Arakatzailea"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Kontaktuak"</string>
- <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Helbide elektronikoa"</string>
+ <string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Posta"</string>
<string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Istanteko mezularitza"</string>
<string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Musika"</string>
<string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
- <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Egutegia"</string>
+ <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Calendar"</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>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Baliteke aplikazioak ez funtzionatzea leiho anitzetan."</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>. posizioa, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Editatzeko, sakatu birritan."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Gehitzeko, sakatu birritan."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g>. posizioa. Hautatzeko, sakatu birritan."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Kendu da <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>. posiziora eraman da"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Ezarpen bizkorren editorea."</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>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 322197e..5020bd8 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"رد کردن <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> نادیده گرفته شد."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"همه برنامههای اخیر رد شدند."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"باز کردن اطلاعات برنامه <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> در حال شروع به کار است."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"اعلان ردشد."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> کنترلکننده صدا است"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"برای بازیابی کنترلکننده اصلی، لمس کنید."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"درحال استفاده از نمایه کاریتان هستید"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"تنظیمکننده واسط کاربری سیستم"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"نمایش درصد شارژ باتری جاسازی شده"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"نمایش درصد سطح باتری در نماد نوار وضعیت، هنگامی که باتری شارژ نمیشود"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"برنامه ممکن است با چندپنجره کار نکند"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"موقعیت <xliff:g id="POSITION">%1$d</xliff:g>، <xliff:g id="TILE_NAME">%2$s</xliff:g>. برای ویرایش دو ضربه سریع بزنید."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. برای افزودن دو ضربه سریع بزنید."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"موقعیت <xliff:g id="POSITION">%1$d</xliff:g>. برای انتخاب دو ضربه سریع بزنید."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> حذف میشود"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> به موقعیت <xliff:g id="POSITION">%2$d</xliff:g> منتقل شد"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ویرایشگر تنظیمات سریع."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"ممکن است برنامه با تقسیم صفحه کار نکند."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"برنامه از تقسیم صفحه پشتیبانی نمیکند."</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 6db0a3e..dca5b12 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Hylätään <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> hylättiin."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Kaikki viimeisimmät sovellukset on hylätty."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Avaa sovelluksen <xliff:g id="APP">%s</xliff:g> tiedot."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Käynnistetään <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ilmoitus hylätty."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> on äänenvoimakkuusvalinta."</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Palauta alkuperäinen koskettamalla."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Käytät työprofiilia."</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Näytä akun varaus kuvakkeessa"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Näyttää akun varausprosentin tilapalkin kuvakkeessa, kun laitetta ei ladata."</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Sovellus ei ehkä toimi usean ikkunan tilassa."</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Paikka <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Muokkaa kaksoisnapauttamalla."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Lisää kaksoisnapauttamalla."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Paikka <xliff:g id="POSITION">%1$d</xliff:g>. Valitse kaksoisnapauttamalla."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> poistettiin."</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> siirrettiin paikkaan <xliff:g id="POSITION">%2$d</xliff:g>."</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Pika-asetusten muokkausnäkymä"</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>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 89c6826..76a3438 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Supprimer <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Application \"<xliff:g id="APP">%s</xliff:g>\" ignorée."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toutes les applications récentes ont été supprimées."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Ouvre les détails de l\'application <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Lancement de <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification masquée"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Touchez pour restaurer l\'original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Vous utilisez votre profil professionnel."</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Afficher le pourcentage intégré de charge"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Afficher le pourcentage correspondant au niveau de la pile dans l\'icône de la barre d\'état lorsque l\'appareil n\'est pas en charge."</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Il est possible que l\'application ne fonctionne pas en mode Multi-fenêtre."</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Touchez deux fois pour modifier."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Touchez deux fois pour ajouter."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position : <xliff:g id="POSITION">%1$d</xliff:g>. Touchez deux fois pour sélectionner."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> a été supprimé"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> a été déplacé à la position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Éditeur de paramètres rapides."</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>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 2f99b94..d1ba9e3 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Supprimer <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Application \"<xliff:g id="APP">%s</xliff:g>\" ignorée."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toutes les applications récentes ont été supprimées."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Ouvre les informations sur l\'application <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Lancement de <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> : <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification masquée"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Appuyez pour restaurer l\'interface d\'origine."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Vous utilisez votre profil professionnel."</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Afficher le pourcentage intégré de la batterie"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Affichez le pourcentage correspondant au niveau de la batterie dans l\'icône de la barre d\'état lorsque l\'appareil n\'est pas en charge."</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Il est possible que l\'application ne fonctionne pas en mode multifenêtre."</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, \"<xliff:g id="TILE_NAME">%2$s</xliff:g>\". Appuyer deux fois pour modifier."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Appuyer deux fois pour ajouter."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position <xliff:g id="POSITION">%1$d</xliff:g>. Appuyer deux fois pour sélectionner."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Le bloc \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" a bien été supprimé."</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Le bloc \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" a bien été déplacé à la position <xliff:g id="POSITION">%2$d</xliff:g>."</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Éditeur de configuration rapide."</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>
</resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 45c3626..0f6bedc 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rexeitar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Rexeitouse <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Rexeitáronse todas as aplicacións recentes."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Abre a información da aplicación <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación rexeitada"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é o cadro de diálogo de volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar o orixinal."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Estás usando o perfil de traballo"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Configurador da IU do sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentaxe de batería inserida"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostrar porcentaxe do nivel de batería na icona da barra de estado cando non está en carga"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Pode que a aplicación non funcione con varias ventás."</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posición <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toca dúas veces o elemento para editalo."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toca dúas veces o elemento para engadilo"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posición <xliff:g id="POSITION">%1$d</xliff:g>. Toca dúas veces o elemento para seleccionalo."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Eliminouse <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> moveuse á posición <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de configuración rápida."</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>
</resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index ef6a49c..f937362 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> કાઢી નાખો."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> કાઢી નાખી."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"તમામ તાજેતરની એપ્લિકેશનો કાઢી નાખી."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> ઍપ્લિકેશન માહિતી ખોલો."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> પ્રારંભ કરી રહ્યું છે."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"સૂચના કાઢી નાખી."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> એ વૉલ્યૂમ સંવાદ છે"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"મૂળને પુનઃસ્થાપિત કરવા માટે ટચ કરો."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"તમે તમારી કાર્ય પ્રોફાઇલનો ઉપયોગ કરી રહ્યાં છો"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"સિસ્ટમ UI ટ્યૂનર"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"એમ્બેડ કરેલ બૅટરી ટકા બતાવો"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"જ્યારે ચાર્જ ન થઈ રહ્યું હોય ત્યારે સ્થિતિ બાર આયકનની અંદર બૅટરી સ્તર ટકા બતાવો"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"બહુ-વિંડો સાથે અૅપ્લિકેશન કદાચ કામ ન કરે"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"સ્થિતિ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. સંપાદિત કરવા માટે બે વાર ટૅપ કરો."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ઉમેરવા માટે બે વાર ટૅપ કરો."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"સ્થિતિ <xliff:g id="POSITION">%1$d</xliff:g>. પસંદ કરવા માટે બે વાર ટૅપ કરો."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> દૂર કરવામાં આવ્યું છે"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ને <xliff:g id="POSITION">%2$d</xliff:g> સ્થિતિ પર ખસેડ્યું"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ઝડપી સેટિંગ્સ સંપાદક."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"વિભાજિત-સ્ક્રીન સાથે ઍપ્લિકેશન કદાચ કામ ન કરે."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ઍપ્લિકેશન સ્ક્રીન-વિભાજનનું સમર્થન કરતી નથી."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 1ba0caf..b30d7a6 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> को ख़ारिज करें."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> खा़रिज कर दिया गया."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"हाल ही के सभी ऐप्लिकेशन ख़ारिज कर दिए गए."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> ऐप्लिकेशन जानकारी खोलें."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> प्रारंभ हो रहा है."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"नोटिफिकेशन खारिज की गई."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> वॉल्यूम संवाद है"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"मूल वॉल्यूम को फिर से लाने के लिए स्पर्श करें."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"आप अपनी कार्य प्रोफ़ाइल का उपयोग कर रहे हैं"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"सिस्टम UI ट्यूनर"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"एम्बेड किया गया बैटरी प्रतिशत दिखाएं"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"जब चार्ज नहीं किया जा रहा हो तब स्थिति बार आइकन में बैटरी स्तर का प्रतिशत दिखाएं"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"हो सकता है कि ऐप्लिकेशन एकाधिक विंडो के साथ काम ना करे"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. संपादित करने के लिए डबल टैप करें."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. जोड़ने के लिए डबल टैप करें."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>. चुनने के लिए डबल टैप करें."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> निकाल दिया गया है"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> को <xliff:g id="POSITION">%2$d</xliff:g> स्थिति में ले जाया गया"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"त्वरित सेटिंग संपादक."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"हो सकता है कि ऐप्लिकेशन विभाजित स्क्रीन के साथ काम ना करे."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ऐप विभाजित स्क्रीन का समर्थन नहीं करता है."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 81c6276..24e8f8d 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -169,8 +169,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Odbacivanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> odbačena je."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Odbačene su sve nedavne aplikacije."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Otvaranje informacija o aplikaciji <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Pokretanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obavijest je odbačena."</string>
@@ -422,6 +421,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> predstavlja dijaloški okvir za upravljanje glasnoćom"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Dodirnite da biste vratili izvorno."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Upotrebljavate radni profil"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Ugađanje korisničkog sučelja sustava"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Prikaži ugrađeni postotak baterije"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Prikazivanje postotka razine baterije na ikoni trake statusa kada se ne puni"</string>
@@ -597,7 +602,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Aplikacija možda neće funkcionirati uz više prozora"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dodirnite dvaput da biste uredili."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dodirnite dvaput da biste dodali."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>. Dodirnite dvaput da biste odabrali."</string>
@@ -607,4 +611,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Pločica <xliff:g id="TILE_NAME">%1$s</xliff:g> uklonjena"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Pločica <xliff:g id="TILE_NAME">%1$s</xliff:g> premještena je na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Uređivač brzih postavki."</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>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index b7ac8a4..cf69932 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"A(z) <xliff:g id="APP">%s</xliff:g> elvetése."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> eltávolítva."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Az összes alkalmazás eltávolítva a nemrég használtak közül."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"A(z) <xliff:g id="APP">%s</xliff:g> alkalmazás adatainak megnyitása."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"A(z) <xliff:g id="APP">%s</xliff:g> indítása."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Értesítés elvetve."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás kezeli a hangerőt"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Érintse meg az eredeti érték visszaállításához."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"A munkaprofilt használja"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Kezelőfelület-hangoló"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"A beépített akkumulátor töltöttségi szintjének megjelenítése"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Az akkumulátor töltöttségi szintjének megjelenítése az állapotsori ikonban, amikor az eszköz nem töltődik"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Lehet, hogy az alkalmazás nem működik többablakos nézetben"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>. pozíció: <xliff:g id="TILE_NAME">%2$s</xliff:g>. Koppintson duplán a szerkesztéshez."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Koppintson duplán a hozzáadáshoz."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g>. pozíció. Koppintson duplán a kiválasztáshoz."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"A(z) <xliff:g id="TILE_NAME">%1$s</xliff:g> eltávolítva"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"A(z) <xliff:g id="TILE_NAME">%1$s</xliff:g> áthelyezve a(z) <xliff:g id="POSITION">%2$d</xliff:g>. pozícióba"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Gyorsbeállítások szerkesztője"</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>
</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 7e4e01a..d58b63e 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Անտեսել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>-ը անտեսված է:"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Բոլոր վերջին հավելվածները հեռացվել են ցուցակից:"</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Բացել <xliff:g id="APP">%s</xliff:g> հավելվածի մասին տեղեկությունները"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Մեկնարկել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ծանուցումը անտեսվեց:"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ը ձայնի ուժգնության երկխոսության հավելված է"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Դիպչեք՝ սկզբնօրինակը վերականգնելու համար:"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Դուք օգտագործում եք ձեր աշխատանքային պրոֆիլը"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Համակարգի ՕՄ-ի կարգավորիչ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Ցուցադրել ներկառուցված մարտկոցի տոկոսայնությունը"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Ցուցադրել մարտկոցի լիցքավորման տոկոսայնությունը կարգավիճակի գոտու պատկերակի վրա, երբ այն չի լիցքավորվում"</string>
@@ -533,7 +538,7 @@
<string name="keyboard_shortcut_group_system_notifications" msgid="8366964080041773224">"Ծանուցումներ"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4892255911160332762">"Ստեղնային դյուրանցումներ"</string>
<string name="keyboard_shortcut_group_system_switch_input" msgid="2334164096341310324">"Փոխարկել մուտքագրման եղանակը"</string>
- <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Գործադիրներ"</string>
+ <string name="keyboard_shortcut_group_applications" msgid="9129465955073449206">"Հավելվածներ"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="9095441910537146013">"Օգնություն"</string>
<string name="keyboard_shortcut_group_applications_browser" msgid="6465985474000766533">"Դիտարկիչ"</string>
<string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Կոնտակտներ"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Հավելվածը չի կարող աշխատել բազմապատուհան ռեժիմում"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Դիրք <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>: Կրկնակի հպեք՝ փոխելու համար:"</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>: Կրկնակի հպեք՝ ավելացնելու համար:"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Դիրք <xliff:g id="POSITION">%1$d</xliff:g>: Կրկնակի հպեք՝ ընտրելու համար:"</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> սալիկը հեռացվել է"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> սալիկը տեղափոխվել է դեպի <xliff:g id="POSITION">%2$d</xliff:g> դիրք"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Արագ կարգավորումների խմբագրիչ:"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Հավելվածը չի կարող աշխատել տրոհված էկրանի ռեժիմում:"</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Հավելվածը չի աջակցում էկրանի տրոհումը:"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 2b51426..cab43c1 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Menyingkirkan <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> disingkirkan."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Semua aplikasi terbaru telah ditutup."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Buka info aplikasi <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Memulai <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notifikasi disingkirkan."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> adalah dialog volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Sentuh untuk memulihkan aslinya."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Anda menggunakan profil kerja"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Penyetel Antarmuka Pengguna Sistem"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Tampilkan persentase baterai yang tersemat"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Tampilkan persentase tingkat baterai dalam ikon bilah status saat tidak mengisi daya"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Aplikasi mungkin tidak berfungsi dengan multi-jendela"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posisi <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Ketuk dua kali untuk mengedit."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Ketuk dua kali untuk menambahkan."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posisi <xliff:g id="POSITION">%1$d</xliff:g>. Ketuk dua kali untuk memilih."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> dihapus"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> dpindahkan ke posisi <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor setelan cepat."</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>
</resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 1dc37df..f67f4c1 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Hunsa <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> vísað frá."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Öll nýleg forrit fjarlægð."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Opna forritsupplýsingar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Ræsir <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Tilkynningu lokað."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er hljóðstyrksvalmyndin"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Snertu til að færa í upprunalegt horf."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Þú ert að nota vinnusniðið"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Fínstillingar kerfisviðmóts"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Sýna innfellda rafhlöðustöðu"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Sýna rafhlöðustöðuna í stöðustikunni þegar tækið er ekki í hleðslu"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Hugsanlegt er að forritið virki ekki í mörgum gluggum"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Staða <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Ýttu tvisvar til að breyta."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Ýttu tvisvar til að bæta við."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Staða <xliff:g id="POSITION">%1$d</xliff:g>. Ýttu tvisvar til að velja."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> var fjarlægð"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> færð í stöðu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Flýtistillingaritill."</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>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 4a8ba99..ea1bb00 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Elimina <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> eliminata."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Tutte le applicazioni recenti sono state rimosse."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Mostra informazioni sull\'applicazione <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Avvio di <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notifica eliminata."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> rappresenta la finestra di dialogo relativa al volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Tocca per ripristinare l\'originale."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Stai utilizzando il profilo di lavoro"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Sintetizzatore interfaccia utente di sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostra percentuale batteria incorporata"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostra la percentuale di carica della batteria nell\'icona della barra di stato quando non è in carica"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"L\'app potrebbe non funzionare con la modalità multi-finestra"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posizione <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Tocca due volte per modificare."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Tocca due volte per aggiungere."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posizione <xliff:g id="POSITION">%1$d</xliff:g>. Tocca due volte per selezionare."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Il riquadro <xliff:g id="TILE_NAME">%1$s</xliff:g> è stato rimosso"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Il riquadro <xliff:g id="TILE_NAME">%1$s</xliff:g> è stato spostato nella posizione <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor di impostazioni rapide."</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>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index d41d50d..88bfafc 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -170,8 +170,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"סגור את <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> נדחה."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"כל האפליקציות האחרונות נסגרו."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"פתח מידע על האפליקציה <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"מפעיל את <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"הודעה נדחתה."</string>
@@ -423,6 +422,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> הוא תיבת הדו-שיח של עוצמת הקול"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"גע כדי לשחזר את עוצמת הקול המקורית."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"אתה משתמש בפרופיל העבודה שלך"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"הצג בשורת הסטטוס את אחוז עוצמת הסוללה"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"הצג את אחוז עוצמת הסוללה בתוך הסמל שבשורת הסטטוס כשהמכשיר אינו בטעינה"</string>
@@ -598,7 +603,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"ייתכן שהאפליקציה לא תפעל עם ריבוי חלונות"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"מיקום <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. הקש פעמיים כדי לערוך."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. הקש פעמיים כדי להוסיף."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"מיקום <xliff:g id="POSITION">%1$d</xliff:g>. הקש פעמיים כדי לבחור."</string>
@@ -608,4 +612,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> הוסר"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> הועבר למיקום <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"עורך הגדרות מהירות."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"ייתכן שהיישום לא יפעל עם מסך מפוצל."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"האפליקציה אינה תומכת במסך מפוצל."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 83a9888..04a392c 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>を削除します。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>は削除されました。"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"最近のアプリケーションをすべて消去しました。"</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"「<xliff:g id="APP">%s</xliff:g>」のアプリ情報を開きます。"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>を開始しています。"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"通知が削除されました。"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>を音量ダイアログとして使用"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"タップすると元の音量ダイアログが復元されます。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"仕事用プロファイルを使用しています"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"システムUI調整ツール"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"内蔵電池の残量の割合を表示する"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"充電していないときには電池残量の割合をステータスバーアイコンに表示する"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"アプリはマルチウィンドウでは動作しないことがあります"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ポジション <xliff:g id="POSITION">%1$d</xliff:g> の <xliff:g id="TILE_NAME">%2$s</xliff:g> を編集するにはダブルタップします。"</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g> を追加するにはダブルタップします。"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ポジション <xliff:g id="POSITION">%1$d</xliff:g> に配置します。選択するにはダブルタップします。"</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> を削除しました"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> をポジション <xliff:g id="POSITION">%2$d</xliff:g> に移動しました"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"クイック設定エディタ"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"アプリは分割画面では動作しないことがあります。"</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"アプリで分割画面がサポートされていません。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 5008fe0..fbd97f0 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>-ის უგულებელყოფა."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ამოშლილია სიიდან."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ყველა ბოლო აპლიკაცია გაუქმდა."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> აპლიკაციის ინფორმაციის გახსნა."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> იწყება."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"შეტყობინება წაიშალა."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ხმოვან დიალოგშია"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"ორიგინალის აღდგენისათვის, შეეხეთ."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"თქვენ სამსახურის პროფილს იყენებთ"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"სისტემის UI ტუნერი"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"ჩამაგრებული ბატარეის პროცენტის ჩვენება"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ბატარეის დონის პროცენტის ჩვენება სტატუსის ზოლის ხატულას შიგნით, როდესაც არ იტენება"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"აპმა შეიძლება არ იმუშაოს მრავალი ფანჯრის რეჟიმში"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"პოზიცია <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. რედაქტირებისთვის, შეეხეთ ორმაგად."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. დასამატებლად, შეეხეთ ორმაგად."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"პოზიცია <xliff:g id="POSITION">%1$d</xliff:g>. ასარჩევად, შეეხეთ ორმაგად."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ამოიშალა"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> გადატანილია პოზიციაზე <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"სწრაფი პარამეტრების რედაქტორი."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"აპმა შეიძლება არ იმუშაოს გაყოფილი ეკრანის რეჟიმში."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ეკრანის გაყოფა არ არის მხარდაჭერილი აპის მიერ."</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index ff33f05..4bc585a 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> қолданбасынан бас тарту."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> алынып тасталған."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Барлық жақындағы қабылданбаған қолданбалар."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> қолданбасы туралы ақпаратты ашады."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> іске қосылуда."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Хабар алынып тасталды."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> — көлем диалогтық терезесі"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Түпнұсқаны қалпына келтіру үшін түртіңіз."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Сіз жұмыс профиліңізді пайдаланып жатырсыз"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Жүйелік пайдаланушылық интерфейс тюнері"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Ендірілген батарея пайыздық шамасын көрсету"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Зарядталмай тұрғанда, күй жолағы белгішесінің ішінде батарея деңгейінің пайыздық шамасын көрсетеді"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Қолданба көп тереземен жұмыс істемеуі мүмкін"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g> орны, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Өңдеу үшін екі рет түртіңіз."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Қосу үшін екі рет түртіңіз."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g> орны. Таңдау үшін екі рет түртіңіз."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> жойылды"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> орнына жылжытылды"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Жылдам параметрлер өңдегіші."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Қолданба бөлінген экранда жұмыс істемеуі мүмкін."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Қодланба бөлінген экранды қолдамайды."</string>
</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index b69f893..9f66f3b 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"បោះបង់ <xliff:g id="APP">%s</xliff:g> ។"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> បដិសេធ។"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"កម្មវិធីថ្មីៗទាំងអស់ត្រូវបានបោះបង់។"</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"បើកព័ត៌មានកម្មវិធី <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"ចាប់ផ្ដើម <xliff:g id="APP">%s</xliff:g> ។"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"បានបដិសេធការជូនដំណឹង"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> គឺជាប្រអប់សម្លេង"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"ប៉ះដើម្បីស្តារច្បាប់ដើម។"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"អ្នកកំពុងប្រើប្រវត្តិរូបការងាររបស់អ្នក"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"កម្មវិធីសម្រួល UI ប្រព័ន្ធ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"បង្ហាញភាគរយថាមពលថ្មដែលបានបង្កប់"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"បង្ហាញភាគរយនៃកម្រិតថាមពលថ្មនៅក្នុងរូបតំណាងរបារស្ថានភាពនៅពេលមិនសាកថ្ម"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"កម្មវិធីអាចនឹងមិនដំណើរការជាមួយពហុវិនដូទេ"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ទីតាំង <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>, ប៉ះពីរដងដើម្បីកែ"</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>, ប៉ះពីរដងដើម្បីបន្ថែម"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ទីតាំង <xliff:g id="POSITION">%1$d</xliff:g>, ប៉ះពីរដងដើម្បីជ្រើស"</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ត្រូវបានយកចេញ"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> បានផ្លាស់ទីទៅទីតាំង <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"កម្មវិធីកែការកំណត់រហ័ស"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"កម្មវិធីអាចនឹងមិនដំណើរការនៅលើអេក្រង់បំបែកទេ"</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"កម្មវិធីមិនគាំទ្រអេក្រង់បំបែកជាពីរទេ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 1ce14dd5..41537a39 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ವಜಾಗೊಳಿಸು."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ವಜಾಗೊಳಿಸಲಾಗಿದೆ."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ಇತ್ತೀಚಿನ ಎಲ್ಲಾ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ವಜಾಗೊಳಿಸಲಾಗಿದೆ."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ ತೆರೆಯಿರಿ."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"ಅಧಿಸೂಚನೆ ವಜಾಗೊಂಡಿದೆ."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ವಾಲ್ಯೂಮ್ ಸಂವಾದವಾಗಿದೆ"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"ಮೂಲ ಮರುಸ್ಥಾಪಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಅನ್ನು ನೀವು ಬಳಸುತ್ತಿರುವಿರಿ"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"ಸಿಸ್ಟಮ್ UI ಟ್ಯೂನರ್"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"ಎಂಬೆಡ್ ಮಾಡಲಾದ ಬ್ಯಾಟರಿ ಶೇಕಡಾ ತೋರಿಸಿ"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ಚಾರ್ಜ್ ಮಾಡದಿರುವಾಗ ಸ್ಥಿತಿ ಪಟ್ಟಿ ಐಕಾನ್ ಒಳಗೆ ಬ್ಯಾಟರಿ ಮಟ್ಟದ ಶೇಕಡಾವನ್ನು ತೋರಿಸಿ"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"ಬಹು ವಿಂಡೋದಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ಕೆಲಸ ಮಾಡದೇ ಇರಬಹುದು"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ಸ್ಥಾನ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. ಸಂಪಾದಿಸಲು ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ಸೇರಿಸಲು ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ಸ್ಥಾನ <xliff:g id="POSITION">%1$d</xliff:g>. ಆಯ್ಕೆಮಾಡಲು ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="POSITION">%2$d</xliff:g> ಸ್ಥಾನಕ್ಕೆ <xliff:g id="TILE_NAME">%1$s</xliff:g> ಸೇರಿಸಲಾಗಿದೆ"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳ ಸಂಪಾದಕ."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"ವಿಭಜಿಸಿದ ಪರದೆಯಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ಕೆಲಸ ಮಾಡದೇ ಇರಬಹುದು."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ಅಪ್ಲಿಕೇಶನ್ ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index a8a2a0a..702c489 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>을(를) 숨깁니다."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>이(가) 제거되었습니다."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"최근 사용한 애플리케이션을 모두 닫았습니다."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> 애플리케이션 정보를 엽니다."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>을(를) 시작하는 중입니다."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"알림이 제거되었습니다."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>은(는) 볼륨 대화입니다."</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"원본을 복원하려면 터치하세요."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"직장 프로필을 사용하고 있습니다."</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"시스템 UI 튜너"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"내장형 배터리 잔량 비율 표시"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"충전 중이 아닌 경우 상태 표시줄 아이콘 내에 배터리 잔량 비율 표시"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"앱이 멀티 윈도우에서 작동하지 않을 수 있습니다."</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"위치 <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. 수정하려면 두 번 탭하세요."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. 추가하려면 두 번 탭하세요."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"위치 <xliff:g id="POSITION">%1$d</xliff:g>. 선택하려면 두 번 탭하세요."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 타일이 삭제되었습니다."</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 타일을 위치 <xliff:g id="POSITION">%2$d</xliff:g>(으)로 이동함"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"빠른 설정 편집기"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"앱이 분할 화면에서 작동하지 않을 수 있습니다."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"앱이 화면 분할을 지원하지 않습니다."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 6a2d77f..23349eb 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> этибарга албоо."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> жок болду."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Акыркы колдонмолордун баары көз жаздымда калтырылды."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> колдонмосу жөнүндө маалыматты ачыңыз."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> иштеп баштоодо."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Эскертме жок кылынды."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> үндү катуулатуу диалогу"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Түпнусканы калыбына келтирүү үчүн тийип коюңуз."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Жумуш профилиңизди колдонуп жатасыз"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Батарянын кубатнын деңгээли пайыз менен көрсөтлсүн"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Түзмөк кубаттанбай турганда, батареянын деңгээли статус тилкесинде көрүнүп турат"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Бир нече терезе режиминде колдонмо иштебей калышы мүмкүн"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Орду - <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Түзөтүү үчүн эки жолу таптаңыз."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Кошуу үчүн эки жолу таптаңыз."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Орду - <xliff:g id="POSITION">%1$d</xliff:g>. Тандоо үчүн эки жолу таптаңыз."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> алынып салынды"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> деген <xliff:g id="POSITION">%2$d</xliff:g>-орунга жылдырылды"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Ыкчам жөндөөлөр түзөткүчү."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Колдонмодо экран бөлүнбөшү мүмкүн."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Колдонмодо экран бөлүнбөйт."</string>
</resources>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index 26a81c8..c40797c 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -24,4 +24,14 @@
<dimen name="docked_divider_handle_width">2dp</dimen>
<dimen name="docked_divider_handle_height">16dp</dimen>
+
+ <dimen name="qs_tile_margin_top">2dp</dimen>
+ <dimen name="qs_brightness_padding_top">0dp</dimen>
+
+ <dimen name="battery_detail_graph_space_top">9dp</dimen>
+ <dimen name="battery_detail_graph_space_bottom">9dp</dimen>
+
+ <integer name="quick_settings_num_columns">4</integer>
+ <bool name="quick_settings_wide">true</bool>
+ <dimen name="qs_detail_margin_top">0dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 601cc2a..22acd02 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"ປິດ <xliff:g id="APP">%s</xliff:g> ໄວ້."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"ປິດ <xliff:g id="APP">%s</xliff:g> ແລ້ວ."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ທຸກແອັບພລິເຄຊັນບໍ່ດົນມານີ້ຖືກປ່ອຍໄປ."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"ເປີດຂໍ້ມູນແອັບພລິເຄຊັນ <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"ກຳລັງເປີດ <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"ປິດການແຈ້ງເຕືອນແລ້ວ."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ແມ່ນໜ້າຕ່າງລະດັບສຽງ"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"ສໍາຜັດເພື່ອກູ້ຄືນຕົ້ນສະບັບ."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ທ່ານກຳລັງໃຊ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຂອງທ່ານ"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"ສະແດງເປີເຊັນແບັດເຕີຣີທີ່ຕິດມາ"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ສະແດງເປີເຊັນລະດັບແບັດເຕີຣີຢູ່ດ້ານໃນໄອຄອນແຖບສະຖານະ ເມື່ອບໍ່ສາກຢູ່"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"ແອັບອາດບໍ່ສາມາດໃຊ້ໄດ້ກັບຫຼາຍໜ້າຈໍ"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ຕຳແໜ່ງ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. ແຕະສອງເທື່ອເພື່ອແກ້ໄຂ."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ແຕະສອງເທື່ອເພື່ອເພີ່ມ."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ຕຳແໜ່ງ <xliff:g id="POSITION">%1$d</xliff:g>. ແຕະສອງເທື່ອເພື່ອເລືອກ."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"ລຶບ <xliff:g id="TILE_NAME">%1$s</xliff:g> ອອກແລ້ວ"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ຍ້າຍໄປຕຳແໜ່ງ <xliff:g id="POSITION">%2$d</xliff:g> ແລ້ວ"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ຕົວແກ້ໄຂການຕັ້ງຄ່າດ່ວນ"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"ແອັບອາດໃຊ້ບໍ່ໄດ້ກັບການແບ່ງໜ້າຈໍ."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ແອັບບໍ່ຮອງຮັບໜ້າຈໍແບບແຍກກັນ."</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 866abf3..ac32b30 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -170,8 +170,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Atsisakyti <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Atsisakyta programos „<xliff:g id="APP">%s</xliff:g>“."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Atsisakyta visų naujausių programų."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Atidaryti programos „<xliff:g id="APP">%s</xliff:g>“ informaciją."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Paleidžiama <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"„<xliff:g id="APP">%1$s</xliff:g>“ <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pranešimo atsisakyta."</string>
@@ -423,6 +422,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ yra garsumo valdymo dialogo langas"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Palieskite, kad atkurtumėte originalą."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Naudojate darbo profilį"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Sistemos naudotojo sąsajos derinimo priemonė"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Rodyti įterptą akumuliat. įkrovos procentinę vertę"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Rodyti akumuliatoriaus įkrovos lygio procentinę vertę būsenos juostos piktogramoje, kai įrenginys nėra įkraunamas"</string>
@@ -598,7 +603,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Naudojant kelių langų funkciją programa gali neveikti"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g> padėtis, išklotinės elementas „<xliff:g id="TILE_NAME">%2$s</xliff:g>“. Dukart palieskite, kad redaguotumėte."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“. Dukart palieskite, kad pridėtumėte."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g> padėtis. Dukart palieskite, kad pasirinktumėte."</string>
@@ -608,4 +612,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ pašalintas"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ perkeltas į <xliff:g id="POSITION">%2$d</xliff:g> padėtį"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Sparčiųjų nustatymų redagavimo priemonė."</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>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 9c32b31..218178a 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -169,8 +169,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Nerādīt lietotni <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Lietotne <xliff:g id="APP">%s</xliff:g> vairs netiek rādīta."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Visas nesen izmantotās lietojumprogrammas tika noņemtas."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Atveriet lietojumprogrammas <xliff:g id="APP">%s</xliff:g> informāciju."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Notiek lietotnes <xliff:g id="APP">%s</xliff:g> palaišana."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Paziņojums netiek rādīts."</string>
@@ -422,6 +421,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ir skaļuma dialoglodziņš"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Pieskarieties, lai atjaunotu sākotnējo."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Jūs izmantojat darba profilu."</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Sistēmas saskarnes regulators"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Rādīt akumulatora uzlādes līmeni procentos"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Rādīt akumulatora uzlādes līmeni procentos statusa joslas ikonā, kad netiek veikta uzlāde"</string>
@@ -597,7 +602,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Iespējams, lietotnē nedarbosies vairāku logu režīms."</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>. pozīcija, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Lai rediģētu, veiciet dubultskārienu."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Lai pievienotu, veiciet dubultskārienu."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g>. pozīcija. Lai atlasītu, veiciet dubultskārienu."</string>
@@ -607,4 +611,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Elements <xliff:g id="TILE_NAME">%1$s</xliff:g> ir noņemts"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Elements <xliff:g id="TILE_NAME">%1$s</xliff:g> ir pārvietots uz <xliff:g id="POSITION">%2$d</xliff:g>. pozīciju"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Ātro iestatījumu redaktors."</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>
</resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 7f2fc15..8d25796 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Отфрли <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> е отфрлена."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Сите неодамнешни апликации се отфрлени."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Отвори информации за апликацијата <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Се стартува <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Известувањето е отфрлено."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> е дијалог за јачина на звук"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Допрете за да го вратите оригиналот."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Го користите работниот профил"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Адаптер на УИ на системот"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Прикажи вграден процент на батеријата"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Прикажи процент на ниво на батеријата во внатрешноста на иконата со статусна лента кога не се полни"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Апликацијата може да не работи со повеќе прозорци"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Место <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Допрете двапати за уредување."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Допрете двапати за додавање."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Место <xliff:g id="POSITION">%1$d</xliff:g>. Допрете двапати за избирање."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> е отстранета"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> е преместена на место <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Уредник за брзи поставки."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Апликацијата можеби нема да работи во поделен екран."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Апликацијата не поддржува поделен екран."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index dfe992c..e44642d2 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> നിരസിക്കുക."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> നിരസിച്ചു."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"അടുത്തിടെയുള്ള എല്ലാ അപ്ലിക്കേഷനും നിരസിച്ചു."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> ആപ്പ് വിവരങ്ങൾ തുറക്കുക."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ആരംഭിക്കുന്നു."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"അറിയിപ്പ് നിരസിച്ചു."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>, വോളിയം ഡയലോഗാണ്"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"ആദ്യത്തേത് പുനഃസ്ഥാപിക്കാൻ സ്പർശിക്കുക."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"നിങ്ങൾ ഉപയോഗിക്കുന്നത് ഔദ്യോഗിക പ്രൊഫൈലാണ്"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"സിസ്റ്റം UI ട്യൂണർ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"എംബഡ് ചെയ്ത ബാറ്ററി ശതമാനം കാണിക്കുക"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ചാർജ്ജുചെയ്യാതിരിക്കുമ്പോൾ സ്റ്റാറ്റസ് ബാർ ഐക്കണിൽ ബാറ്ററി ലെവൽ ശതമാനം കാണിക്കുക"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"മൾട്ടി-വിൻഡോയിൽ ആപ്പ് പ്രവർത്തിച്ചേക്കില്ല"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"സ്ഥാനം <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. എഡിറ്റുചെയ്യുന്നതിന് രണ്ടുതവണ ടാപ്പുചെയ്യുക."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ചേർക്കാൻ രണ്ടുതവണ ടാപ്പുചെയ്യുക."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"സ്ഥാനം <xliff:g id="POSITION">%1$d</xliff:g>. തിരഞ്ഞെടുക്കാൻ രണ്ടുതവണ ടാപ്പുചെയ്യുക."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> നീക്കംചെയ്യുന്നു"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"സ്ഥാനം <xliff:g id="POSITION">%2$d</xliff:g>-ലേക്ക് <xliff:g id="TILE_NAME">%1$s</xliff:g> നീക്കി"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ദ്രുത ക്രമീകരണ എഡിറ്റർ."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"സ്പ്ലിറ്റ്-സ്ക്രീനിനൊപ്പം ആപ്പ് പ്രവർത്തിച്ചേക്കില്ല."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"സ്പ്ലിറ്റ്-സ്ക്രീനിനെ ആപ്പ് പിന്തുണയ്ക്കുന്നില്ല."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 80cb8f2..e3fd349 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -166,8 +166,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>-г хаах."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> байхгүй."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Хамгийн сүүлийн бүх програмыг арилгасан байна."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> апп-н мэдээллийг нээнэ үү."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>-г эхлүүлж байна."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Мэдэгдэл хаагдсан."</string>
@@ -419,6 +418,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь дууны диалог юм."</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Анхны хувилбарыг эргүүлэн хадгалахыг хүсвэл хүрнэ үү."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Та өөрийн ажлын профайлыг ашиглаж байна"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Системийн UI Тохируулагч"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Залгаатай тэжээлийн хувийг харуулах"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Тэжээлийн хувийг цэнэглээгүй байх үед статусын хэсэгт харуулна уу"</string>
@@ -594,7 +599,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Олон цонхтой үед апп ажиллахгүй байж болзошгүй"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Байршил <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Засахын тулд 2 удаа дарна уу."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Нэмэхийн тулд 2 удаа дарна уу."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Албан тушаал <xliff:g id="POSITION">%1$d</xliff:g>. Сонгохын тулд 2 удаа дарна уу."</string>
@@ -604,4 +608,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-г устгасан"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-г <xliff:g id="POSITION">%2$d</xliff:g> байршилд зөөсөн"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Түргэн тохиргоо засварлагч."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Апп хуваагдсан дэлгэцэд ажиллахгүй."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Энэ апп нь дэлгэц хуваах тохиргоог дэмждэггүй."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 76dfcd5..2cd5ed8 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> डिसमिस करा."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> डिसमिस केला."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"अलीकडील सर्व अनुप्रयोग डिसमिस झाले."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> अनुप्रयोग माहिती उघडा."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> प्रारंभ करीत आहे."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना डिसमिस केल्या."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> हा व्हॉल्यूम संवाद आहे"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"मूळ पुनर्संचयित करण्यासाठी स्पर्श करा."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"आपण आपले कार्य प्रोफाईल वापरत आहात"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"सिस्टीम UI ट्यूनर"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"एम्बेडेड बॅटरी टक्केवारी दर्शवा"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"चार्ज होत नसताना स्टेटस बार चिन्हामध्ये बॅटरी पातळी टक्केवारी दर्शवा"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"एकाधिक-विंडो सह अॅप कार्य करू शकत नाही"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"स्थिती <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. संपादित करण्यासाठी दोनदा टॅप करा."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g> . जोडण्यासाठी दोनदा टॅप करा."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"स्थिती <xliff:g id="POSITION">%1$d</xliff:g>. निवडण्यासाठी दोनदा टॅप करा."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ला काढले आहे"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ला <xliff:g id="POSITION">%2$d</xliff:g> स्थितीवर हलविले"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"द्रुत सेटिंग्ज संपादक."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"अॅप कदाचित विभाजित-स्क्रीनसह कार्य करू शकत नाही."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"अॅप स्क्रीन-विभाजनास समर्थन देत नाही."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 9401198..e11f7ff 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ketepikan <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ditolak."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Semua aplikasi terbaharu diketepikan."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Buka maklumat aplikasi <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Memulakan <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pemberitahuan diketepikan."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ialah dialog kelantangan"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Sentuh untuk memulihkan yang asal."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Anda sedang menggunakan profil kerja"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Penala UI Sistem"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Tunjukkan peratusan bateri terbenam"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Tunjukkan peratusan aras bateri dalam ikon bar status semasa tidak mengecas"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Apl mungkin tidak berfungsi dengan berbilang tetingkap"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Kedudukan <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dwiketik untuk mengedit."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dwiketik untuk menambah."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Kedudukan <xliff:g id="POSITION">%1$d</xliff:g>. Dwiketik untuk memilih."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> dialih keluar"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> dialihkan ke kedudukan <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor tetapan pantas."</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>
</resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 6964750..67ce1fc 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>ကို ပယ်လိုက်ရန်"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ထုတ်ထားသည်။"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"မကြာသေးမီက အပလီကေးရှင်းများအားလုံး ဖယ်ထုတ်ပြီးပါပြီ။"</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> အက်ပ်အချက်အလက်ကို ဖွင့်ပါ။"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>ကို စတင်နေသည်။"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g><xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"အကြောင်းကြားချက်ကိုဖယ်ရှားပြီး"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် အသံဒိုင်ယာလော့ခ်ဖြစ်သည်"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"မူရင်းအားပြန်လည်သိမ်းဆည်းရန် ထိပါ။"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"သင်သည် အလုပ်ပရိုဖိုင်းအား သုံးနေသည်"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"စနစ် UI ဖမ်းစက်"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"မြုတ်ထားသည့် ဘတ်ထရီ ရာခိုင်နှုန်းကို ပြပါ"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"အားမသွင်းနေစဉ်တွင် ဘတ်ထရီအဆင့် ရာခိုင်နှုန်းကို အခြေနေပြဘား အိုင်ကွန်တွင် ပြပါ"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"အက်ပ်သည် ဝင်းဒိုးများတပြိုင်နက်ဖွင့်ခြင်းကို မပံ့ပိုးပါ"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>၊ <xliff:g id="TILE_NAME">%2$s</xliff:g> နေရာ။ တည်းဖြတ်ရန် နှစ်ချက်တို့ပါ။"</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>။ ပေါင်းထည့်ရန် နှစ်ချက်တို့ပါ။"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g> နေရာ။ ရွေးချယ်ရန် နှစ်ချက်တို့ပါ။"</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ကိုဖယ်ရှားလိုက်ပါပြီ"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ကို <xliff:g id="POSITION">%2$d</xliff:g> နေရာသို့ ရွှေ့လိုက်ပါပြီ"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"မြန်ဆန်သည့် ဆက်တင်တည်းဖြတ်စနစ်"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"မျက်နှာပြင် ခွဲခြမ်းပြသမှုဖြင့် အက်ပ်သည် အလုပ်လုပ်မည် မဟုတ်ပါ။"</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"အက်ပ်သည် မျက်နှာပြင်ခွဲပြရန် ပံ့ပိုးထားခြင်းမရှိပါ။"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index eed5f36..6d68342 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Avvis <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> avvist."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle nylig brukte apper er avvist."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Åpne appinformasjonen for <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Starter <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Varselet ble skjult."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er volumdialogen"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Trykk for å gå tilbake til den opprinnelige volumdialogen."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Du bruker jobbprofilen din"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Vis prosent for det innebygde batteriet"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Vis batterinivåprosenten inni statusfeltikonet når du ikke lader"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Appen fungerer kanskje ikke i Flervindusmodus"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Plassering <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dobbelttrykk for å endre."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dobbelttrykk for å legge til."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Plassering <xliff:g id="POSITION">%1$d</xliff:g>. Dobbelttrykk for å velge."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> er fjernet"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> er flyttet til plassering <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Redigeringsvindu for hurtiginnstillinger."</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>
</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 836dc4b..231a28a 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> खारेज गर्नुहोस्।"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> खारेज गरिएको छ।"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"सबै हालका अनुप्रयोगहरू खारेज गरियो।"</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> अनुप्रयोग सम्बन्धी जानकारी खोल्नुहोस्।"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>सुरु गर्दै।"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना खारेज।"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> भोल्यूम संवाद हो"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"मूल पुनर्स्थापना गर्न छुनुहोस्।"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"तपाईँले कार्य प्रोफाइल प्रयोग गर्दै हुनुहुन्छ"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"प्रणाली UI ट्युनर"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"इम्बेड गरिएको ब्याट्री प्रतिशत देखाउनुहोस्"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"चार्ज नगरेको बेला वस्तुस्थिति पट्टी आइकन भित्र ब्याट्री प्रतिशत स्तर देखाउनुहोस्"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"अनुप्रयोग बहु-विन्डोमा काम नगर्न सक्छ"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। सम्पादन गर्नका लागि डबल ट्याप गर्नुहोस्।"</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। थप्नका लागि डबल ट्याप गर्नुहोस्।"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>। चयन गर्नका लागि डबल ट्याप गर्नुहोस्।"</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> लाई हटाइयो"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> लाई स्थिति <xliff:g id="POSITION">%2$d</xliff:g> मा सारियो"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"द्रुत सेटिङ सम्पादक।"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"अनुप्रयोगले विभाजित-स्क्रिनमा काम नगर्न सक्छ।"</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"अनुप्रयोगले विभाजित-स्क्रिनलाई समर्थन गर्दैन।"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 41075e39..700fd88 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> sluiten."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> verwijderd."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle recente apps gesloten."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"App-gegevens voor <xliff:g id="APP">%s</xliff:g> openen."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> starten."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Melding verwijderd."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is het volumedialoogvenster"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Tik hierop om het origineel te herstellen."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"U gebruikt je werkprofiel"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Systeem-UI-tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Percentage ingebouwde accu weergeven"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Accupercentage weergeven in het pictogram op de statusbalk wanneer er niet wordt opgeladen"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"De app werkt mogelijk niet met meerdere vensters"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Positie <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dubbeltik om te bewerken."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dubbeltik om toe te voegen."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Positie <xliff:g id="POSITION">%1$d</xliff:g>. Dubbeltik om te selecteren."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is verwijderd"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> is verplaatst naar positie <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor voor \'Snelle instellingen\'."</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>
</resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 1703a2f..d2166a4a 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ਨੂੰ ਰੱਦ ਕਰੋ।"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ਰੱਦ ਕੀਤਾ।"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ਸਾਰੀਆਂ ਹਾਲੀਆ ਐਪਲੀਕੇਸ਼ਨਾਂ ਰੱਦ ਕੀਤੀਆਂ।"</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> ਐਪਲੀਕੇਸ਼ਨਾਂ ਜਾਣਕਾਰੀ ਖੋਲ੍ਹੋ।"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ।"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"ਸੂਚਨਾ ਰੱਦ ਕੀਤੀ।"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਵੋਲਯੂਮ ਡਾਇਲੌਗ ਹੈ"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"ਅਸਲੀ ਨੂੰ ਰੀਸਟੋਰ ਕਰਨ ਲਈ ਛੋਹਵੋ।"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ਤੁਸੀਂ ਆਪਣੀ ਕੰਮ ਪ੍ਰੋਫਾਈਲ ਵਰਤ ਰਹੇ ਹੋ"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI ਟਿਊਨਰ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"ਜੋਡ਼ੀ ਗਈ ਬੈਟਰੀ ਪ੍ਰਤਿਸ਼ਤਤਾ ਦਿਖਾਓ"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ਜਦੋਂ ਚਾਰਜ ਨਾ ਹੋ ਰਹੀ ਹੋਵੇ ਤਾਂ ਸਥਿਤੀ ਬਾਰ ਦੇ ਅੰਦਰ ਬੈਟਰੀ ਪੱਧਰ ਪ੍ਰਤਿਸ਼ਤਤਾ ਦਿਖਾਓ"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਐਪ ਮਲਟੀ-ਵਿੰਡੋ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ਸਥਿਤੀ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। ਸੰਪਾਦਨ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ।"</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ।"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ਸਥਿਤੀ <xliff:g id="POSITION">%1$d</xliff:g>। ਚੁਣਨ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ।"</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਨੂੰ ਹਟਾਇਆ ਗਿਆ"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਨੂੰ <xliff:g id="POSITION">%2$d</xliff:g> ਸਥਿਤੀ \'ਤੇ ਤਬਦੀਲ ਕੀਤਾ ਗਿਆ"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਸੰਪਾਦਕ।"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਐਪ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ।"</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ਐਪ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਨੂੰ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ।"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 297b849..2f1f889 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -170,8 +170,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Usuń stąd <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>: zamknięto."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Wszystkie ostatnie aplikacje zostały zamknięte."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Otwórz informacje o aplikacji <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Uruchamiam <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Zamknięto powiadomienie."</string>
@@ -423,6 +422,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> steruje głośnością"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Dotknij, by przywrócić pierwotną."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Używasz profilu do pracy"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Kalibrator System UI"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Pokaż procent naładowania baterii"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Pokaż procent naładowania baterii w ikonie na pasku stanu, gdy telefon się nie ładuje"</string>
@@ -598,7 +603,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Aplikacja może nie działać w trybie wielu okien"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Położenie <xliff:g id="POSITION">%1$d</xliff:g>, kafelek <xliff:g id="TILE_NAME">%2$s</xliff:g>. Kliknij dwukrotnie, by edytować."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"Kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g>. Kliknij dwukrotnie, by dodać."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Położenie <xliff:g id="POSITION">%1$d</xliff:g>. Kliknij dwukrotnie, by wybrać."</string>
@@ -608,4 +612,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g> został usunięty"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g> przeniesiony w położenie <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Edytor szybkich ustawień."</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>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index eb08d99..9b778cc 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Descartar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartado."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todos os apps recentes foram dispensados."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Abre informações do app <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação dispensada."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é a caixa de diálogo referente ao volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Toque para restaurar o original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Você está usando seu perfil de trabalho"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Sintonizador System UI"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentagem de bateria incorporada"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostrar porcentagem de nível de bateria dentro do ícone da barra de status quando não estiver carregando"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"É possível que o app não funcione com várias janelas"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posição <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toque duas vezes para editar."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toque duas vezes para adicionar."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posição <xliff:g id="POSITION">%1$d</xliff:g>. Toque duas vezes para selecionar."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> é removido"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> movido para a posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de configurações rápidas."</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>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index bba2f3e..69a4dad 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ignorar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ignorado."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todas as aplicações recentes foram ignoradas."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Abrir as informações da aplicação <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"A iniciar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação ignorada."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é a caixa de diálogo do volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Toque para restaurar o original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Está a utilizar o seu perfil de trabalho"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Sintonizador da interface do sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar percentagem da bateria incorporada"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostrar a percentagem do nível da bateria no ícone da barra de estado quando não estiver a carregar"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"A aplicação pode não funcionar com multijanelas"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posição <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toque duas vezes para editar."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toque duas vezes para adicionar."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posição <xliff:g id="POSITION">%1$d</xliff:g>. Toque duas vezes para selecionar."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> removido"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> movido para a posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de definições rápidas."</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>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index eb08d99..9b778cc 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Descartar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartado."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todos os apps recentes foram dispensados."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Abre informações do app <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação dispensada."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é a caixa de diálogo referente ao volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Toque para restaurar o original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Você está usando seu perfil de trabalho"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Sintonizador System UI"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentagem de bateria incorporada"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Mostrar porcentagem de nível de bateria dentro do ícone da barra de status quando não estiver carregando"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"É possível que o app não funcione com várias janelas"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posição <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toque duas vezes para editar."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toque duas vezes para adicionar."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posição <xliff:g id="POSITION">%1$d</xliff:g>. Toque duas vezes para selecionar."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> é removido"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> movido para a posição <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor de configurações rápidas."</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>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 81d0456..50289f3 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -169,8 +169,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Închideți <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> a fost eliminată."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toate aplicațiile recente au fost închise."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Deschideți informațiile despre aplicația <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Se inițiază <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificarea a fost închisă."</string>
@@ -422,6 +421,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> afișează caseta de dialog pentru volum"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Atingeți pentru a reveni la setarea inițială."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Acum folosiți profilul de serviciu"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Afișați procentajul bateriei încorporat"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Afișați procentajul cu nivelul bateriei în interiorul pictogramei din bara de stare, atunci când nu se încarcă"</string>
@@ -597,7 +602,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Este posibil ca aplicația să nu funcționeze cu ferestre multiple"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Poziția <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Atingeți de două ori pentru a edita."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Atingeți de două ori pentru a adăuga."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Poziția <xliff:g id="POSITION">%1$d</xliff:g>. Atingeți de două ori pentru a selecta."</string>
@@ -607,4 +611,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Caseta <xliff:g id="TILE_NAME">%1$s</xliff:g> este eliminată"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Caseta <xliff:g id="TILE_NAME">%1$s</xliff:g> a fost mutată pe poziția <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editorul pentru setări rapide."</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>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 86f0ec4..0347b03 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -170,8 +170,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Удаление приложения <xliff:g id="APP">%s</xliff:g> из списка."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" удалено из списка."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Все недавние приложения закрыты."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Открыть информацию о приложении \"<xliff:g id="APP">%s</xliff:g>\""</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Запуск приложения <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Уведомление закрыто"</string>
@@ -423,6 +422,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"Приложение <xliff:g id="APP_NAME">%1$s</xliff:g> назначено регулятором громкости"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Нажмите, чтобы восстановить приложение по умолчанию."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Вы перешли в рабочий профиль"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Показывать уровень заряда батареи в процентах"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Когда устройство работает в автономном режиме, процент заряда батареи показан в строке состояния"</string>
@@ -541,7 +546,7 @@
<string name="keyboard_shortcut_group_applications_contacts" msgid="2064197111278436375">"Контакты"</string>
<string name="keyboard_shortcut_group_applications_email" msgid="6257036897441939004">"Эл. почта"</string>
<string name="keyboard_shortcut_group_applications_im" msgid="1892749399083161405">"Чат"</string>
- <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музыка."</string>
+ <string name="keyboard_shortcut_group_applications_music" msgid="4775559515850922780">"Музыка"</string>
<string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
<string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Календарь"</string>
<string name="tuner_full_zen_title" msgid="4540823317772234308">"Показывать при нажатии кнопок регулировки громкости"</string>
@@ -598,7 +603,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Приложение не поддерживает многооконный режим"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>, кнопка \"<xliff:g id="TILE_NAME">%2$s</xliff:g>\". Чтобы изменить, нажмите дважды."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"Кнопка \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\". Чтобы добавить, нажмите дважды."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>. Чтобы выбрать, нажмите дважды."</string>
@@ -608,4 +612,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Кнопка \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" удалена"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Кнопка \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" теперь занимает позицию <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Редактор быстрых настроек."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Приложение не поддерживает разделение экрана."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Приложение не поддерживает разделение экрана."</string>
</resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 5a2f849..d92b0e8 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ඉවතලන්න."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> අස් කර ඇත."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"සියලුම මෑත යෙඳුම් අස් කරන ලදි."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> යෙදුම් තොරතුරු විවෘත කරයි."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කරමින්."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"දැනුම්දීම නිෂ්ප්රභා කරඇත."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ධාරිතා සංවාදයයි"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"මුල් තත්ත්වය නැවත ප්රතිසාධනය කිරීමට ස්පර්ශ කරන්න."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ඔබ ඔබේ කාර්යාල පැතිකඩ භාවිත කරමින් සිටී"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"පද්ධති UI සුසරකය"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"කාවද්දන ලද බැටරි ප්රතිශතය පෙන්වන්න"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ආරෝපණය නොවන විට තත්ත්ව තීරු නිරූපකය ඇතුළත බැටරි මට්ටම් ප්රතිශතය පෙන්වන්න"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"යෙදුම බහු-කවුළුව සමඟ ක්රියා නොකළ හැකිය."</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ස්ථානය <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. වෙනස් කිරීමට දෙවරක් තට්ටු කරන්න."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. එක් කිරීමට දෙවරක් තට්ටු කරන්න."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ස්ථානය <xliff:g id="POSITION">%1$d</xliff:g>. තෝරා ගැනීමට දෙවරක් තට්ටු කරන්න."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ඉවත් කරන ලදි"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> වන ස්ථානයට ගෙන යන ලදි"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ඉක්මන් සැකසුම් සංස්කාරකය."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"යෙදුම බෙදුම්-තිරය සමග ක්රියා නොකළ හැකිය."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"යෙදුම බෙදුණු-තිරය සඳහා සහාය නොදක්වයි."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 9468fcf..b606d01 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -170,8 +170,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Zrušiť aplikáciu <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikácia <xliff:g id="APP">%s</xliff:g> bola zrušená."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Všetky nedávne aplikácie boli odmietnuté."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Otvoriť informácie o aplikácii <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Spúšťa sa aplikácia <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Upozornenie bolo zrušené."</string>
@@ -423,6 +422,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je dialóg hlasitosti"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Klepnutím obnovíte originál."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Používate svoj pracovný profil."</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Tuner používateľského rozhrania systému"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Zobraziť percentá vloženej batérie"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Percentuálne zobrazenie nabitia batérie vnútri ikony v stavovom riadku, keď neprebieha nabíjanie"</string>
@@ -598,7 +603,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Aplikácia nemusí fungovať v režime viacerých okien"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Pozícia <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Upravíte ju dvojitým klepnutím."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Pridáte ju dvojitým klepnutím."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Pozícia <xliff:g id="POSITION">%1$d</xliff:g>. Vyberiete ju dvojitým klepnutím."</string>
@@ -608,4 +612,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Dlaždica <xliff:g id="TILE_NAME">%1$s</xliff:g> bola odstránená"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Dlaždica <xliff:g id="TILE_NAME">%1$s</xliff:g> bola presunutá na pozíciu <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor rýchlych nastavení"</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>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index c5a43f9..3c71c09 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -170,8 +170,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Opusti aplikacijo <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> je bila odstranjena."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Vse nedavne aplikacije so bile opuščene."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Odpiranje podatkov o aplikaciji <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Zaganjanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obvestilo je bilo odstranjeno."</string>
@@ -423,6 +422,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je pogovorno okno glede prostornine"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Dotaknite se, če želite obnoviti izvirnik."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Uporabljate delovni profil"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Uglaševalnik uporabniškega vmesnika sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Prikaži odstotek napolnjenosti vgraj. akumulatorja"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Prikaz odstotka napolnjenosti akumulatorja znotraj ikone v vrstici stanja, ko se ne polni"</string>
@@ -598,7 +603,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Aplikacija morda ne deluje v načinu z več okni"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Če želite urediti, se dvakrat dotaknite."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Če želite dodati, se dvakrat dotaknite."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Položaj: <xliff:g id="POSITION">%1$d</xliff:g>. Če želite izbrati, se dvakrat dotaknite."</string>
@@ -608,4 +612,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> je odstranjeno"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> premaknjeno na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Urejevalnik hitrih nastavitev."</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>
</resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 0188e5b..fe79425 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Largo <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> është hequr."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Të gjitha aplikacionet e fundit u larguan."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Hap informacionin e aplikacionit <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Po nis <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Njoftimi është hequr."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> është dialogu i volumit"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Prek për të restauruar origjinalin."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Po përdor profilin tënd të punës"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Sintonizuesi i Sistemit të Ndërfaqes së Përdoruesit"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Shfaq përqindjen e baterisë së integruar"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Shfaq përqindjen e nivelit të baterisë brenda ikonës së shiritit të statusit kur nuk është duke u ngarkuar."</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Aplikacioni mund të mos punojë me funksionin me shumë dritare."</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Pozicioni <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Trokit dy herë për ta redaktuar."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Trokit dy herë për ta shtuar."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Pozicioni <xliff:g id="POSITION">%1$d</xliff:g>. Trokit dy herë për ta zgjedhur."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> u hoq"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> u zhvendos te pozicioni <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Redaktori i cilësimeve të shpejta."</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>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 501a3e3..772aca4 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -169,8 +169,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Одбаците <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Апликација <xliff:g id="APP">%s</xliff:g> је одбачена."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Све недавно коришћене апликације су одбачене."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Отворите информације о апликацији <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Покрећемо <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Обавештење је одбачено."</string>
@@ -422,6 +421,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> је дијалог за јачину звука"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Додирните да бисте вратили оригинал."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Користите профил за Work"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Тјунер за кориснички интерфејс система"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Приказуј уграђени проценат батерије"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Приказивање нивоа напуњености батерије у процентима унутар иконе на статусној траци када се батерија не пуни"</string>
@@ -597,7 +602,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Апликација можда неће функционисати са више прозора"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>. позиција, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Двапут додирните да бисте изменили."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Двапут додирните да бисте додали."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g>. позиција. Двапут додирните да бисте изабрали."</string>
@@ -607,4 +611,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Плочица <xliff:g id="TILE_NAME">%1$s</xliff:g> је уклоњена"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Плочица <xliff:g id="TILE_NAME">%1$s</xliff:g> је премештена на <xliff:g id="POSITION">%2$d</xliff:g>. позицију"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Уређивач за Брза подешавања."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Апликација можда неће функционисати са подељеним екраном."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Апликација не подржава подељени екран."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 959128e..5acbc61 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ta bort <xliff:g id="APP">%s</xliff:g> från listan."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> togs bort permanent."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alla appar har tagits bort från listan Senaste."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Öppna appinformation för <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Startar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Meddelandet ignorerades."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> används som volymkontroll"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Tryck här om du vill återställa den ursprungliga appen."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Du använder din jobbprofil"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Inställningar för systemgränssnitt"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Visa inbäddad batteriprocent"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Visa batterinivå i procent i statusfältsikonen när enheten inte laddas"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Appen fungerar eventuellt inte i flerfönsterläge"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Tryck snabbt två gånger om du vill redigera positionen."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Lägg till genom att trycka snabbt två gånger."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Position <xliff:g id="POSITION">%1$d</xliff:g>. Välj den genom att trycka snabbt två gånger."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> har tagits bort"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> har flyttats till position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Redigerare för snabbinställningar."</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>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 4b936c9..d4d278d 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ondoa <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> imeondolewa."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Programu za hivi majuzi zimeondolewa."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Fungua maelezo kuhusu programu ya <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Inaanzisha <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Arifa imetupwa."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ni mazungumzo ya sauti"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Gusa ili urejeshe ya awali."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Unatumia wasifu wako wa kazini"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Kipokea Ishara cha SystemUI"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Onyesha asilimia ya betri iliyopachikwa"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Onyesha asilimia ya kiwango cha betri ndani ya aikoni ya sehemu ya arifa inapokuwa haichaji"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Huenda programu isifanye kazi kwenye madirisha mengi"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Nafasi ya <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Gonga mara mbili ili ubadilishe."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Gonga mara mbili ili uongeze."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Nafasi ya <xliff:g id="POSITION">%1$d</xliff:g>. Gonga mara mbili ili uchague."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> imeondolewa"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> imehamishiwa kwenye nafasi ya <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Kihariri cha Mipangilio ya haraka."</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>
</resources>
diff --git a/packages/SystemUI/res/values-sw410dp/config.xml b/packages/SystemUI/res/values-sw410dp/config.xml
new file mode 100644
index 0000000..08b2f88
--- /dev/null
+++ b/packages/SystemUI/res/values-sw410dp/config.xml
@@ -0,0 +1,24 @@
+<?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 different hardware and product builds. -->
+<resources>
+ <integer name="quick_settings_num_rows">2</integer>
+</resources>
diff --git a/packages/SystemUI/res/values-sw410dp/dimens.xml b/packages/SystemUI/res/values-sw410dp/dimens.xml
new file mode 100644
index 0000000..5ce6524
--- /dev/null
+++ b/packages/SystemUI/res/values-sw410dp/dimens.xml
@@ -0,0 +1,24 @@
+<?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 different hardware and product builds. -->
+<resources>
+ <dimen name="qs_detail_items_padding_top">16dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values-sw540dp/config.xml b/packages/SystemUI/res/values-sw540dp/config.xml
new file mode 100644
index 0000000..e554fc6d
--- /dev/null
+++ b/packages/SystemUI/res/values-sw540dp/config.xml
@@ -0,0 +1,24 @@
+<?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 different hardware and product builds. -->
+<resources>
+ <integer name="quick_settings_num_rows">3</integer>
+</resources>
diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
index 4ed15d5..49a7a29 100644
--- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
@@ -40,4 +40,8 @@
<dimen name="battery_detail_graph_space_top">27dp</dimen>
<dimen name="battery_detail_graph_space_bottom">27dp</dimen>
+
+ <dimen name="qs_tile_margin_top">16dp</dimen>
+ <dimen name="qs_brightness_padding_top">6dp</dimen>
+ <dimen name="qs_detail_margin_top">28dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 5489be9..3714c06 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ஐ நிராகரி."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> விலக்கப்பட்டது."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"எல்லா சமீபத்திய பயன்பாடுகளும் விலக்கப்பட்டன."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> பயன்பாட்டின் தகவலைத் திற."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ஐத் தொடங்குகிறது."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"அறிவிப்பு நிராகரிக்கப்பட்டது."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"ஒலியளவு செய்தி: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"அசலை மீட்டமைக்கத் தொடவும்."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"பணி சுயவிவரத்தைப் பயன்படுத்துகிறீர்கள்"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"உள்ளிணைந்த பேட்டரி சதவீதத்தைக் காட்டு"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"சார்ஜ் செய்யாத போது, நிலைப் பட்டி ஐகானின் உள்ளே பேட்டரி அளவு சதவீதத்தைக் காட்டும்"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"பல சாளர அம்சத்தில் பயன்பாடு வேலைசெய்யாமல் போகக்கூடும்"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"நிலை <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. திருத்த, இருமுறை தட்டவும்."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. சேர்க்க, இருமுறை தட்டவும்."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"நிலை <xliff:g id="POSITION">%1$d</xliff:g>. தேர்ந்தெடுக்க, இருமுறை தட்டவும்."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> அகற்றப்பட்டது"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> நிலை <xliff:g id="POSITION">%2$d</xliff:g>க்கு நகர்த்தப்பட்டது"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"விரைவு அமைப்புகள் திருத்தி."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"திரைப் பிரிப்பில் பயன்பாடு வேலைசெய்யாமல் போகக்கூடும்."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"திரையைப் பிரிப்பதைப் பயன்பாடு ஆதரிக்கவில்லை."</string>
</resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 3a72809..1dd7254b 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>ని తీసివేయండి."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> తీసివేయబడింది."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"అన్ని ఇటీవలి అనువర్తనాలు తీసివేయబడ్డాయి."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> అనువర్తన సమాచారాన్ని తెరుస్తుంది."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>ని ప్రారంభిస్తోంది."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"నోటిఫికేషన్ తీసివేయబడింది."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> అనేది వాల్యూమ్ డైలాగ్"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"అసలుదాన్ని పునరుద్ధరించడానికి తాకండి."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"మీరు మీ కార్యాలయ ప్రొఫైల్ను ఉపయోగిస్తున్నారు"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"సిస్టమ్ UI ట్యూనర్"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"పొందుపరిచిన బ్యాటరీ శాతం చూపు"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"ఛార్జింగ్లో లేనప్పుడు స్థితి పట్టీ చిహ్నం లోపల బ్యాటరీ స్థాయి శాతం చూపుతుంది"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"అనువర్తనం బహుళ విండోల రూపంలో పని చేయకపోవచ్చు"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"స్థానం <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. సవరించడానికి రెండుసార్లు నొక్కండి."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. జోడించడానికి రెండుసార్లు నొక్కండి."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"స్థానం <xliff:g id="POSITION">%1$d</xliff:g>. ఎంచుకోవడానికి రెండుసార్లు నొక్కండి."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> తీసివేయబడింది"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>వ స్థానానికి తరలించబడింది"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"శీఘ్ర సెట్టింగ్ల ఎడిటర్."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"స్క్రీన్ విభజనతో అనువర్తనం పని చేయకపోవచ్చు."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"అనువర్తనంలో స్క్రీన్ విభజనకు మద్దతు లేదు."</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 4844c84..59b420d 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"ยกเลิก <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ถูกลบไปแล้ว"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ปิดแอปพลิเคชันล่าสุดทั้งหมดแล้ว"</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"เปิดข้อมูลแอปพลิเคชัน <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"กำลังเริ่มต้น <xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"ปิดการแจ้งเตือนแล้ว"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> เป็นช่องโต้ตอบระดับเสียง"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"แตะเพื่อคืนค่าดั้งเดิม"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"คุณกำลังใช้โปรไฟล์งานของคุณ"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"ตัวรับสัญญาณ UI ระบบ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"แสดงเปอร์เซ็นต์ของแบตเตอรี่ในตัว"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"แสดงเปอร์เซ็นต์ของระดับแบตเตอรี่ภายในไอคอนแถบสถานะเมื่อไม่มีการชาร์จ"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"แอปอาจทำงานกับหลายหน้าต่างไม่ได้"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ตำแหน่ง <xliff:g id="POSITION">%1$d</xliff:g> <xliff:g id="TILE_NAME">%2$s</xliff:g> แตะ 2 ครั้งเพื่อแก้ไข"</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g> แตะ 2 ครั้งเพื่อเพิ่ม"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ตำแหน่ง <xliff:g id="POSITION">%1$d</xliff:g> แตะ 2 ครั้งเพื่อเลือก"</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"นำ <xliff:g id="TILE_NAME">%1$s</xliff:g> ออกแล้ว"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"ย้าย <xliff:g id="TILE_NAME">%1$s</xliff:g> ไปยังตำแหน่ง <xliff:g id="POSITION">%2$d</xliff:g> แล้ว"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"ตัวแก้ไขการตั้งค่าด่วน"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"แอปอาจใช้ไม่ได้กับโหมดแยกหน้าจอ"</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"แอปไม่สนับสนุนการแยกหน้าจอ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 0672959..629963d 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"I-dismiss ang <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Hindi pinansin ang <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Na-dismiss ang lahat ng kamakailang application."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Buksan ang impormasyon ng <xliff:g id="APP">%s</xliff:g> application."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Sinisimulan ang <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Na-dismiss ang notification."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ang volume dialog"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Pindutin upang ibalik ang orihinal."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Ginagamit mo ang iyong profile sa trabaho"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Tuner ng System UI"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Ipakita ang naka-embed na porsyento ng baterya"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Ipakita ang porsyento ng antas ng baterya na nasa icon ng status bar kapag nagcha-charge"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Maaaring hindi gumana ang app sa maraming window"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Posisyon <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. I-double tap upang i-edit."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. I-double tap upang idagdag."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Posisyon <xliff:g id="POSITION">%1$d</xliff:g>. I-double tap upang piliin."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"Inalis ang <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"Inilipat ang <xliff:g id="TILE_NAME">%1$s</xliff:g> sa posisyon <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Editor ng Mga mabilisang setting."</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>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 58d488c..02c0d59 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> uygulamasını kapat."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> kaldırıldı."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Tüm son uygulamalar kapatıldı."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> uygulaması bilgilerini açın."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> başlatılıyor."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Bildirim kapatıldı."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ses denetimi iletişim kutusu olarak ayarlandı"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Orijinali geri yüklemek için dokunun."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"İş profilinizi kullanıyorsunuz"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Sistem Arayüzü Ayarlayıcısı"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Yerleşik pil yüzdesini göster"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Şarj olmazken durum çubuğu simgesinin içinde pil düzeyi yüzdesini göster"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Uygulama birden fazla pencerede çalışmayabilir"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>. konum, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Düzenlemek için iki kez hafifçe dokunun."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Eklemek için iki kez hafifçe dokunun."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"<xliff:g id="POSITION">%1$d</xliff:g>. konum. Seçmek için iki kez hafifçe dokunun."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> kaldırıldı"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>. konumuna taşındı"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Hızlı ayar düzenleyicisi."</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>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index c75891c..a1b2ee1 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -170,8 +170,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Видалити додаток <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Програму <xliff:g id="APP">%s</xliff:g> закрито."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Усі останні додатки закрито."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Відкрити інформацію про додаток <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Запуск додатка <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Сповіщення відхилено."</string>
@@ -423,6 +422,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> призначено регулятором гучності"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Торкніться, щоб відновити оригінал."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Ви в робочому профілі"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Показувати заряд акумулятора у відсотках"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Показувати заряд акумулятора у відсотках в рядку стану, коли пристрій не заряджається"</string>
@@ -598,7 +603,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Додаток може не працювати в багатовіконному режимі"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Позиція <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Двічі торкніться, щоб змінити."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Двічі торкніться, щоб додати."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Позиція <xliff:g id="POSITION">%1$d</xliff:g>. Двічі торкніться, щоб вибрати."</string>
@@ -608,4 +612,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> видалено"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> переміщено на позицію <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Редактор швидких налаштувань."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Додаток може не працювати в режимі розділеного екрана."</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Додаток не підтримує розділення екрана."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 807a923..5c4ae9a 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> کو مسترد کریں۔"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> کو ہٹا دیا گیا۔"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"سبھی حالیہ ایپلیکیشنز کو برخاست کر دیا گیا۔"</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> ایپلیکیشن معلومات کھولیں۔"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> شروع ہو رہی ہے۔"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"اطلاع مسترد ہوگئی۔"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> والیوم ڈائلاگ ہے"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"اصل کو بحال کرنے کیلئے ٹچ کریں۔"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"آپ اپنا دفتری پروفائل استعمال کر رہے ہیں۔"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"سسٹم UI ٹیونر"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"سرایت کردہ بیٹری کی فیصد دکھائیں"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"جب چارج نہ ہو رہا ہو تو بیٹری کی سطح کی فیصد اسٹیٹس بار آئیکن کے اندر دکھائیں"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"ایپ شاید ملٹی ونڈو کے ساتھ کام نہ کرے"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"پوزیشن <xliff:g id="POSITION">%1$d</xliff:g>، <xliff:g id="TILE_NAME">%2$s</xliff:g>۔ ترمیم کرنے کیلئے دو بار تھپتھپائیں۔"</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>۔ شامل کرنے کیلئے دو بار تھپتھپائیں۔"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"پوزیشن <xliff:g id="POSITION">%1$d</xliff:g>۔ منتخب کرنے کیلئے دو بار تھپتھپائیں۔"</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ہٹا دیا گیا"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="POSITION">%2$d</xliff:g> پوزیشن پر <xliff:g id="TILE_NAME">%1$s</xliff:g> منتقل ہو گیا ہے"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"فوری ترتیبات کا ایڈیٹر۔"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"ممکن ہے کہ ایپ سپلٹ اسکرین کے ساتھ کام نہ کرے۔"</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"ایپ سپلٹ اسکرین کو سپورٹ نہیں کرتی۔"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index fe67b52..27039d6 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Olib tashlash: <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> olib tashlangan."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Yaqinda ishlatilgan barcha ilovalar olib tashlandi."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> ilovasi haqidagi ma’lumotlarni ochadi."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ishga tushirilmoqda."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Xabarnoma e‘tiborsiz qoldirildi."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ovoz balandligini boshqaradi"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Aslini tiklash uchun bosing."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Siz ishchi profildan foydalanmoqdasiz"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"SystemUI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Batareya foizi ko‘rsatilsin"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Batareya quvvat olmayotgan vaqtda uning foizi holat qatorida ko‘rsatilsin"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Ilova ko‘p oynali rejimni qo‘llab-quvvatlamaydi"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"<xliff:g id="POSITION">%1$d</xliff:g>-joy, “<xliff:g id="TILE_NAME">%2$s</xliff:g>” tugmasi. Tahrirlash uchun ustiga ikki marta bosing."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"“<xliff:g id="TILE_NAME">%1$s</xliff:g>” tugmasi. Qo‘shish uchun ustiga ikki marta bosing."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Joylashuv: <xliff:g id="POSITION">%1$d</xliff:g>. Belgilash uchun ustiga ikki marta bosing."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"“<xliff:g id="TILE_NAME">%1$s</xliff:g>” tugmasi o‘chirildi"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"“<xliff:g id="TILE_NAME">%1$s</xliff:g>” tugmasi endi <xliff:g id="POSITION">%2$d</xliff:g>-joyni egallanmoqda"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Tezkor sozlamalar muharriri"</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>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index ca7c59b..ef87f01 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Xóa bỏ <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> đã bị loại bỏ."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Đã bỏ qua tất cả các ứng dụng gần đây."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Mở thông tin ứng dụng <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Bắt đầu <xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Đã loại bỏ thông báo."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> là hộp thoại khối lượng"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Chạm để khôi phục bản gốc."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Bạn đang sử dụng hồ sơ công việc của mình"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Bộ điều hướng giao diện người dùng hệ thống"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Hiển thị tỷ lệ phần trăm pin được nhúng"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Hiển thị tỷ lệ phần trăm mức pin bên trong biểu tượng thanh trạng thái khi không sạc"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Ứng dụng có thể không hoạt động với nhiều cửa sổ"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Vị trí <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Nhấn đúp để chỉnh sửa."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Nhấn đúp để thêm."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Vị trí <xliff:g id="POSITION">%1$d</xliff:g>. Nhấn đúp để chọn."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> được di chuyển"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> được di chuyển sang vị trí <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Trình chỉnh sửa cài đặt nhanh."</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>
</resources>
diff --git a/packages/SystemUI/res/values-w550dp-land/dimens.xml b/packages/SystemUI/res/values-w550dp-land/dimens.xml
index cd17bed..4160c83 100644
--- a/packages/SystemUI/res/values-w550dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-w550dp-land/dimens.xml
@@ -20,7 +20,4 @@
<dimen name="notification_panel_width">544dp</dimen>
<dimen name="qs_expand_margin">32dp</dimen>
-
- <dimen name="battery_detail_graph_space_top">9dp</dimen>
- <dimen name="battery_detail_graph_space_bottom">9dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index a25b9f1..85c8bf6 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"移除<xliff:g id="APP">%s</xliff:g>。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"已删除<xliff:g id="APP">%s</xliff:g>"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"已关闭所有最近用过的应用。"</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"打开<xliff:g id="APP">%s</xliff:g>应用信息。"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在启动<xliff:g id="APP">%s</xliff:g>。"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"已关闭通知。"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”已用作音量控制对话框"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"触摸即可恢复原始设置。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"您当前正在使用工作资料"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"系统界面调谐器"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"嵌入式显示电池电量百分比 显示嵌入的电池电量百分比"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"未充电时在状态栏图标内显示电池电量百分比"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"应用可能无法在多窗口模式下正常运行"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。点按两次即可修改。"</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>。点按两次即可添加。"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"位置 <xliff:g id="POSITION">%1$d</xliff:g>。点按两次即可选择。"</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"已移除<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"已将<xliff:g id="TILE_NAME">%1$s</xliff:g>移至位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"快捷设置编辑器。"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"应用可能无法在分屏模式下正常运行。"</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"应用不支持分屏。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 083cd5e..4d5e495 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"關閉「<xliff:g id="APP">%s</xliff:g>」。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"所有最近使用的應用程式均已關閉。"</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"開啟「<xliff:g id="APP">%s</xliff:g>」應用程式的資料。"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g><xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"通知已關閉。"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」為音量對話框"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"輕觸即可復原。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"您正在使用工作設定檔"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"系統使用者介面調諧器"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"顯示嵌入的電池百分比"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"非充電時,在狀態列圖示顯示電量百分比"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"應用程式可能無法在多重視窗下運作"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。輕按兩下即可編輯。"</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>。輕按兩下即可新增。"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"位置 <xliff:g id="POSITION">%1$d</xliff:g>。輕按兩下即可選取。"</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 已移除"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 已移至位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"快速設定編輯工具。"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"應用程式可能無法在分割畫面中運作。"</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"應用程式不支援分割畫面。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 3c95a93..6d15234 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"關閉「<xliff:g id="APP">%s</xliff:g>」。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"最近使用的應用程式已全部關閉。"</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"開啟「<xliff:g id="APP">%s</xliff:g>」應用程式資訊。"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"已關閉通知。"</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」現在是預設的音量控制對話方塊。"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"輕觸這裡即可恢復原始設定。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"您正在使用 Work 設定檔"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"系統使用者介面調整精靈"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"顯示嵌入式電池百分比"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"未充電時在狀態列圖示中顯示電量百分比"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"應用程式可能無法在多視窗模式下運作"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。輕按兩下即可編輯。"</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>。輕按兩下即可新增。"</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"位置 <xliff:g id="POSITION">%1$d</xliff:g>。輕按兩下即可選取。"</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"已移除 <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"已將 <xliff:g id="TILE_NAME">%1$s</xliff:g> 移到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"快速設定編輯器。"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"應用程式可能無法在分割畫面中運作。"</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"這個應用程式不支援分割畫面。"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index e03e642..4d63511 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -168,8 +168,7 @@
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Cashisa i-<xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ivaliwe."</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Zonke izinhlelo zokusebenza zakamuva zicashisiwe."</string>
- <!-- no translation found for accessibility_recents_item_open_app_info (5107479759905883540) -->
- <skip />
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"Vula ulwazi lohlelo lokusebenza le-<xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iqala i-<xliff:g id="APP">%s</xliff:g>."</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"Isaziso sichithiwe."</string>
@@ -421,6 +420,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> yingxoxo yevolumu"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Thinta ukuze ubuyisele kokwangempela."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Usebenzisa iphrofayela yakho yomsebenzi"</string>
+ <!-- no translation found for volume_stream_content_description_unmute (4436631538779230857) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_vibrate (1187944970457807498) -->
+ <skip />
+ <!-- no translation found for volume_stream_content_description_mute (3625049841390467354) -->
+ <skip />
<string name="system_ui_tuner" msgid="708224127392452018">"Isishuni se-UI yesistimu"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Bonisa amaphesenti ebhethri elinamathiselwe"</string>
<string name="show_battery_percentage_summary" msgid="3215025775576786037">"Bonisa amaphesenti eleveli yebhethri ngaphakathi kwesithonjana sebha yesimo uma kungashajwa"</string>
@@ -596,7 +601,6 @@
<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>
- <string name="forced_resizable_info_text" msgid="7591061837558867999">"Uhlelo lokusebenza kungenzeka lungasebenzi namawindi amaningi"</string>
<string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"Isimo esingu-<xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Thepha kabili ukuze uhlele."</string>
<string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Thepha kabili ukuze ungeze."</string>
<string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"Isimo esingu-<xliff:g id="POSITION">%1$d</xliff:g>. Thepha kabili ukuze ukhethe."</string>
@@ -606,4 +610,6 @@
<string name="accessibility_qs_edit_tile_removed" msgid="8584304916627913440">"I-<xliff:g id="TILE_NAME">%1$s</xliff:g> isusiwe"</string>
<string name="accessibility_qs_edit_tile_moved" msgid="4343693412689365038">"I-<xliff:g id="TILE_NAME">%1$s</xliff:g> ihanjiswe kusimo esingu-<xliff:g id="POSITION">%2$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Isihleli sezilungiselelo ezisheshayo."</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>
</resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 1e979fd..1543360 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -53,10 +53,14 @@
<enum name="vertical" value="1" />
</attr>
<declare-styleable name="UserAvatarView">
+ <attr name="avatarPadding" format="dimension" />
<attr name="frameWidth" format="dimension" />
<attr name="framePadding" format="dimension" />
+ <!-- {@deprecated Use a statelist in frameColor instead.} -->
<attr name="activeFrameColor" format="color" />
- <attr name="frameColor" />
+ <attr name="frameColor" format="color" />
+ <attr name="badgeDiameter" format="dimension" />
+ <attr name="badgeMargin" format="dimension" />
</declare-styleable>
<declare-styleable name="UserDetailItemView">
<attr name="regularFontFamily" format="string" />
@@ -97,5 +101,9 @@
<declare-styleable name="DensityContainer">
<attr name="android:layout" />
</declare-styleable>
+
+ <declare-styleable name="AutoSizingList">
+ <attr name="itemHeight" format="dimension" />
+ </declare-styleable>
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index b9aa26b..18fc419 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -151,7 +151,7 @@
<color name="docked_divider_background">#ff000000</color>
<color name="docked_divider_handle">#ffffff</color>
- <drawable name="forced_resizable_background">#80000000</drawable>
+ <drawable name="forced_resizable_background">#40000000</drawable>
<color name="default_remote_input_background">@*android:color/notification_default_color</color>
<color name="remote_input_hint">#99ffffff</color>
@@ -166,9 +166,11 @@
<color name="switch_accent_color">#ff7fcac3</color>
<!-- Keyboard shortcuts colors -->
- <color name="ksh_system_group_color">#ff00bcd4</color>
+ <color name="ksh_system_group_color">@color/material_deep_teal_500</color>
<color name="ksh_application_group_color">#fff44336</color>
<color name="ksh_keyword_color">#d9000000</color>
+ <color name="ksh_key_item_color">@color/material_grey_600</color>
+ <color name="ksh_key_item_background">@color/material_grey_100</color>
<!-- Background color of edit overflow -->
<color name="qs_edit_overflow_bg">#455A64</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 6ce2a5d..42798a4 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -92,11 +92,8 @@
<!-- The number of columns in the QuickSettings -->
<integer name="quick_settings_num_columns">3</integer>
- <!-- The maximum number of rows in the QuickSettings -->
- <integer name="quick_settings_max_rows">4</integer>
-
- <!-- The maximum number of rows in the QuickSettings when on the keyguard -->
- <integer name="quick_settings_max_rows_keyguard">3</integer>
+ <!-- The number of rows in the QuickSettings -->
+ <integer name="quick_settings_num_rows">1</integer>
<!-- The number of columns that the top level tiles span in the QuickSettings -->
<integer name="quick_settings_user_time_settings_tile_span">1</integer>
@@ -116,9 +113,6 @@
<integer name="quick_settings_brightness_dialog_short_timeout">2000</integer>
<integer name="quick_settings_brightness_dialog_long_timeout">4000</integer>
- <!-- The maximum number of items to be displayed in quick settings -->
- <integer name="quick_settings_detail_max_item_count">5</integer>
-
<!-- Should "4G" be shown instead of "LTE" when the network is NETWORK_TYPE_LTE? -->
<bool name="config_show4GForLTE">true</bool>
diff --git a/packages/SystemUI/res/values/config_tv.xml b/packages/SystemUI/res/values/config_tv.xml
index 22b7578..40e3b12 100644
--- a/packages/SystemUI/res/values/config_tv.xml
+++ b/packages/SystemUI/res/values/config_tv.xml
@@ -16,6 +16,10 @@
<resources>
<!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows,
+ when the PIP menu is shown with settings. -->
+ <string translatable="false" name="pip_settings_bounds">"662 54 1142 324"</string>
+
+ <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows,
when the PIP menu is shown in center. -->
<string translatable="false" name="pip_menu_bounds">"596 280 1324 690"</string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c094da9..cf2e338 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -172,6 +172,7 @@
<dimen name="qs_tile_height">88dp</dimen>
<dimen name="qs_tile_margin">16dp</dimen>
+ <dimen name="qs_tile_margin_top">16dp</dimen>
<dimen name="qs_quick_tile_size">48dp</dimen>
<dimen name="qs_quick_tile_padding">12dp</dimen>
<dimen name="qs_date_anim_translation">32dp</dimen>
@@ -201,10 +202,12 @@
<dimen name="qs_detail_item_primary_text_size">16sp</dimen>
<dimen name="qs_detail_item_secondary_text_size">14sp</dimen>
<dimen name="qs_detail_empty_text_size">14sp</dimen>
+ <dimen name="qs_detail_margin_top">28dp</dimen>
<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="qs_detail_items_padding_top">4dp</dimen>
<dimen name="segmented_button_spacing">0dp</dimen>
<dimen name="borderless_button_radius">2dp</dimen>
@@ -385,6 +388,9 @@
quick settings header -->
<dimen name="max_avatar_size">48dp</dimen>
+ <!-- Size of user icon + frame in the qs/keyguard user picker (incl. frame) -->
+ <dimen name="framed_avatar_size">54dp</dimen>
+
<!-- Margin on the left side of the carrier text on Keyguard -->
<dimen name="keyguard_carrier_text_margin">16dp</dimen>
@@ -561,6 +567,9 @@
<!-- Keyboard shortcuts helper -->
<dimen name="ksh_layout_width">@dimen/match_parent</dimen>
+ <dimen name="ksh_item_text_size">14sp</dimen>
+ <dimen name="ksh_item_padding">4dp</dimen>
+ <dimen name="ksh_item_margin_start">4dp</dimen>
<!-- Recents Layout -->
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml
index 4e6a4b1..f536f86 100644
--- a/packages/SystemUI/res/values/dimens_tv.xml
+++ b/packages/SystemUI/res/values/dimens_tv.xml
@@ -57,4 +57,6 @@
<!-- Extra space around the PIP control button icon to match with the focused circle -->
<dimen name="tv_pip_button_icon_padding">5dp</dimen>
+ <!-- Values for entering Recents and exiting Recents -->
+ <dimen name="recents_tv_home_recents_shift">125dip</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/integers_tv.xml b/packages/SystemUI/res/values/integers_tv.xml
index 20cd330..6984d5a 100644
--- a/packages/SystemUI/res/values/integers_tv.xml
+++ b/packages/SystemUI/res/values/integers_tv.xml
@@ -17,5 +17,11 @@
<integer name="item_scale_anim_duration">150</integer>
<integer name="dismiss_short_duration">200</integer>
<integer name="dismiss_long_duration">400</integer>
+
<integer name="recents_tv_pip_focus_anim_duration">200</integer>
+
+ <!-- Duration for how long it takes cards to slide in or out when going to and from recents. -->
+ <integer name="recents_home_duration">400</integer>
+ <!-- Delay between the start of slide in animation for each card. -->
+ <integer name="recents_home_delay">40</integer>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 060e050..9f41dff 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1082,6 +1082,10 @@
<string name="volume_stream_limited_dnd" translatable="false">%s — Priority only</string>
<string name="volume_stream_vibrate_dnd" translatable="false">%s vibrate — Priority only</string>
+ <string name="volume_stream_content_description_unmute">%1$s. Tap to unmute.</string>
+ <string name="volume_stream_content_description_vibrate">%1$s. Tap to set to vibrate. Accessibility services may be muted.</string>
+ <string name="volume_stream_content_description_mute">%1$s. Tap to mute. Accessibility services may be muted.</string>
+
<!-- Name of special SystemUI debug settings -->
<string name="system_ui_tuner">System UI Tuner</string>
@@ -1557,9 +1561,6 @@
<!-- Accessibility action for moving down the docked stack divider [CHAR LIMIT=NONE] -->
<string name="accessibility_action_divider_move_right">Move right</string>
- <!-- Text that gets shown on top of current activity to inform the user that the system force-resized the current activity and that things might crash/not work properly [CHAR LIMIT=NONE] -->
- <string name="forced_resizable_info_text">App may not work with multi-window</string>
-
<!-- Accessibility description of a QS tile while editing positions [CHAR LIMIT=NONE] -->
<string name="accessibility_qs_edit_tile_label">Position <xliff:g id="position" example="2">%1$d</xliff:g>, <xliff:g id="tile_name" example="Wi-Fi">%2$s</xliff:g>. Double tap to edit.</string>
@@ -1587,4 +1588,13 @@
<!-- Accessibility label for window when QS editing is happening [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_quick_settings_edit">Quick settings editor.</string>
+ <!-- Multi-Window strings -->
+ <!-- Text that gets shown on top of current activity to inform the user that the system force-resized the current activity and that things might crash/not work properly [CHAR LIMIT=NONE] -->
+ <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>
+
+ <!-- accessibility label for button to expand quick settings [CHAR LIMIT=NONE] -->
+ <string name="accessibility_quick_settings_expand">Expand quick settings.</string>
+
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 2b134af..f560a13 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -49,6 +49,9 @@
<style name="Animation.ForcedResizable" parent="@android:style/Animation">
<item name="android:activityOpenEnterAnimation">@anim/forced_resizable_enter</item>
+
+ <!-- If the target stack doesn't have focus, we do a task to front animation. -->
+ <item name="android:taskToFrontEnterAnimation">@anim/forced_resizable_enter</item>
<item name="android:activityCloseExitAnimation">@anim/forced_resizable_exit</item>
</style>
@@ -180,6 +183,11 @@
<item name="android:textColor">@color/data_usage_secondary</item>
</style>
+ <style name="TextAppearance.QS.TileLabel">
+ <item name="android:textSize">@dimen/qs_tile_text_size</item>
+ <item name="android:fontFamily">sans-serif-condensed</item>
+ </style>
+
<style name="BaseBrightnessDialogContainer">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
diff --git a/packages/SystemUI/src/com/android/systemui/BitmapHelper.java b/packages/SystemUI/src/com/android/systemui/BitmapHelper.java
deleted file mode 100644
index 1933bbc..0000000
--- a/packages/SystemUI/src/com/android/systemui/BitmapHelper.java
+++ /dev/null
@@ -1,54 +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 com.android.systemui;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.RectF;
-import android.graphics.Shader;
-
-public class BitmapHelper {
- /**
- * Generate a new bitmap (width x height pixels, ARGB_8888) with the input bitmap scaled
- * to fit and clipped to an inscribed circle.
- * @param input Bitmap to resize and clip
- * @param width Width of output bitmap (and diameter of circle)
- * @param height Height of output bitmap
- * @return A shiny new bitmap for you to use
- */
- public static Bitmap createCircularClip(Bitmap input, int width, int height) {
- if (input == null) return null;
-
- final int inWidth = input.getWidth();
- final int inHeight = input.getHeight();
- final Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- final Canvas canvas = new Canvas(output);
- final Paint paint = new Paint();
- paint.setShader(new BitmapShader(input, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
- paint.setAntiAlias(true);
- final RectF srcRect = new RectF(0, 0, inWidth, inHeight);
- final RectF dstRect = new RectF(0, 0, width, height);
- final Matrix m = new Matrix();
- m.setRectToRect(srcRect, dstRect, Matrix.ScaleToFit.CENTER);
- canvas.setMatrix(m);
- canvas.drawCircle(inWidth / 2, inHeight / 2, inWidth / 2, paint);
- return output;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/ResizingSpace.java b/packages/SystemUI/src/com/android/systemui/ResizingSpace.java
new file mode 100644
index 0000000..c2bc53e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ResizingSpace.java
@@ -0,0 +1,104 @@
+/*
+ * 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.content.Context;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+
+public class ResizingSpace extends View {
+
+ private final int mWidth;
+ private final int mHeight;
+
+ public ResizingSpace(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ if (getVisibility() == VISIBLE) {
+ setVisibility(INVISIBLE);
+ }
+ TypedArray a = context.obtainStyledAttributes(attrs, android.R.styleable.ViewGroup_Layout);
+ mWidth = a.getResourceId(android.R.styleable.ViewGroup_Layout_layout_width, 0);
+ mHeight = a.getResourceId(android.R.styleable.ViewGroup_Layout_layout_height, 0);
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ LayoutParams params = getLayoutParams();
+ boolean changed = false;
+ if (mWidth > 0) {
+ int width = getContext().getResources().getDimensionPixelOffset(mWidth);
+ if (width != params.width) {
+ params.width = width;
+ changed = true;
+ }
+ }
+ if (mHeight > 0) {
+ int height = getContext().getResources().getDimensionPixelOffset(mHeight);
+ if (height != params.height) {
+ params.height = height;
+ changed = true;
+ }
+ }
+ if (changed) {
+ setLayoutParams(params);
+ }
+ }
+
+ /**
+ * Draw nothing.
+ *
+ * @param canvas an unused parameter.
+ */
+ @Override
+ public void draw(Canvas canvas) {
+ }
+
+ /**
+ * Compare to: {@link View#getDefaultSize(int, int)}
+ * If mode is AT_MOST, return the child size instead of the parent size
+ * (unless it is too big).
+ */
+ private static int getDefaultSize2(int size, int measureSpec) {
+ int result = size;
+ int specMode = MeasureSpec.getMode(measureSpec);
+ int specSize = MeasureSpec.getSize(measureSpec);
+
+ switch (specMode) {
+ case MeasureSpec.UNSPECIFIED:
+ result = size;
+ break;
+ case MeasureSpec.AT_MOST:
+ result = Math.min(size, specSize);
+ break;
+ case MeasureSpec.EXACTLY:
+ result = specSize;
+ break;
+ }
+ return result;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ setMeasuredDimension(
+ getDefaultSize2(getSuggestedMinimumWidth(), widthMeasureSpec),
+ getDefaultSize2(getSuggestedMinimumHeight(), heightMeasureSpec));
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index c0a565db..e838191 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -329,7 +329,7 @@
*/
public void dismissChild(final View view, float velocity, boolean useAccelerateInterpolator) {
dismissChild(view, velocity, null /* endAction */, 0 /* delay */,
- useAccelerateInterpolator, 0 /* fixedDuration */);
+ useAccelerateInterpolator, 0 /* fixedDuration */, false /* isDismissAll */);
}
/**
@@ -341,17 +341,22 @@
* @param fixedDuration If not 0, this exact duration will be taken
*/
public void dismissChild(final View animView, float velocity, final Runnable endAction,
- long delay, boolean useAccelerateInterpolator, long fixedDuration) {
+ long delay, boolean useAccelerateInterpolator, long fixedDuration,
+ boolean isDismissAll) {
final boolean canBeDismissed = mCallback.canChildBeDismissed(animView);
float newPos;
boolean isLayoutRtl = animView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
- if (velocity < 0
- || (velocity == 0 && getTranslation(animView) < 0)
- // if we use the Menu to dismiss an item in landscape, animate up
- || (velocity == 0 && getTranslation(animView) == 0 && mSwipeDirection == Y)
- // if the language is rtl we prefer swiping to the left
- || (velocity == 0 && getTranslation(animView) == 0 && isLayoutRtl)) {
+ // if we use the Menu to dismiss an item in landscape, animate up
+ boolean animateUpForMenu = velocity == 0 && (getTranslation(animView) == 0 || isDismissAll)
+ && mSwipeDirection == Y;
+ // if the language is rtl we prefer swiping to the left
+ boolean animateLeftForRtl = velocity == 0 && (getTranslation(animView) == 0 || isDismissAll)
+ && isLayoutRtl;
+ boolean animateLeft = velocity < 0
+ || (velocity == 0 && getTranslation(animView) < 0 && !isDismissAll);
+
+ if (animateLeft || animateLeftForRtl || animateUpForMenu) {
newPos = -getSize(animView);
} else {
newPos = getSize(animView);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 0d822cb..0798590 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -250,7 +250,6 @@
FalsingLog.i("onSucccessfulUnlock", "");
}
mDataCollector.onSucccessfulUnlock();
- sessionExitpoint(true /* force */);
}
public void onBouncerShown() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index e00bf6c..f892fd6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -804,7 +804,7 @@
// From DevicePolicyAdmin
final long policyTimeout = mLockPatternUtils.getDevicePolicyManager()
- .getMaximumTimeToLock(null, userId);
+ .getMaximumTimeToLockForUserAndProfiles(userId);
long timeout;
@@ -847,17 +847,16 @@
private void doKeyguardLaterForChildProfilesLocked() {
UserManager um = UserManager.get(mContext);
- List<UserInfo> profiles = um.getEnabledProfiles(UserHandle.myUserId());
- for (UserInfo info : profiles) {
- if (mLockPatternUtils.isSeparateProfileChallengeEnabled(info.id)) {
- long userTimeout = getLockTimeout(info.id);
+ for (int profileId : um.getEnabledProfileIds(UserHandle.myUserId())) {
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(profileId)) {
+ long userTimeout = getLockTimeout(profileId);
if (userTimeout == 0) {
doKeyguardForChildProfilesLocked();
} else {
long userWhen = SystemClock.elapsedRealtime() + userTimeout;
Intent lockIntent = new Intent(DELAYED_LOCK_PROFILE_ACTION);
lockIntent.putExtra("seq", mDelayedProfileShowingSequence);
- lockIntent.putExtra(Intent.EXTRA_USER_ID, info.id);
+ lockIntent.putExtra(Intent.EXTRA_USER_ID, profileId);
PendingIntent lockSender = PendingIntent.getBroadcast(
mContext, 0, lockIntent, PendingIntent.FLAG_CANCEL_CURRENT);
mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
@@ -869,10 +868,9 @@
private void doKeyguardForChildProfilesLocked() {
UserManager um = UserManager.get(mContext);
- List<UserInfo> profiles = um.getEnabledProfiles(UserHandle.myUserId());
- for (UserInfo info : profiles) {
- if (mLockPatternUtils.isSeparateProfileChallengeEnabled(info.id)) {
- lockProfile(info.id);
+ for (int profileId : um.getEnabledProfileIds(UserHandle.myUserId())) {
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(profileId)) {
+ lockProfile(profileId);
}
}
}
@@ -1482,9 +1480,8 @@
final UserHandle currentUser = new UserHandle(KeyguardUpdateMonitor.getCurrentUser());
final UserManager um = (UserManager) mContext.getSystemService(
Context.USER_SERVICE);
- List <UserInfo> userHandles = um.getProfiles(currentUser.getIdentifier());
- for (UserInfo ui : userHandles) {
- mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, ui.getUserHandle());
+ for (int profileId : um.getProfileIdsWithDisabled(currentUser.getIdentifier())) {
+ mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, UserHandle.of(profileId));
}
} else {
mBootSendUserPresent = true;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java b/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java
new file mode 100644
index 0000000..00e6221
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java
@@ -0,0 +1,121 @@
+/*
+ * 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.annotation.Nullable;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.database.DataSetObserver;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.ListAdapter;
+import com.android.systemui.R;
+
+/**
+ * Similar to a ListView, but it will show only as many items as fit on screen and
+ * bind those instead of scrolling.
+ */
+public class AutoSizingList extends LinearLayout {
+
+ private static final String TAG = "AutoSizingList";
+ private final int mItemSize;
+ private final Handler mHandler;
+
+ private ListAdapter mAdapter;
+ private int mCount;
+
+ public AutoSizingList(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+
+ mHandler = new Handler();
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AutoSizingList);
+ mItemSize = a.getDimensionPixelSize(R.styleable.AutoSizingList_itemHeight, 0);
+ }
+
+ public void setAdapter(ListAdapter adapter) {
+ if (mAdapter != null) {
+ mAdapter.unregisterDataSetObserver(mDataObserver);
+ }
+ mAdapter = adapter;
+ if (adapter != null) {
+ adapter.registerDataSetObserver(mDataObserver);
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int requestedHeight = MeasureSpec.getSize(heightMeasureSpec);
+ if (requestedHeight != 0) {
+ int count = Math.min(requestedHeight / mItemSize, getDesiredCount());
+ if (mCount != count) {
+ postRebindChildren();
+ mCount = count;
+ }
+ }
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ private int getDesiredCount() {
+ return mAdapter != null ? mAdapter.getCount() : 0;
+ }
+
+ private void postRebindChildren() {
+ mHandler.post(mBindChildren);
+ }
+
+ private void rebindChildren() {
+ if (mAdapter == null) {
+ return;
+ }
+ for (int i = 0; i < mCount; i++) {
+ View v = i < getChildCount() ? getChildAt(i) : null;
+ View newView = mAdapter.getView(i, v, this);
+ if (newView != v) {
+ if (v != null) {
+ removeView(v);
+ }
+ addView(newView, i);
+ }
+ }
+ // Ditch extra views.
+ while (getChildCount() > mCount) {
+ removeViewAt(getChildCount() - 1);
+ }
+ }
+
+ private final Runnable mBindChildren = new Runnable() {
+ @Override
+ public void run() {
+ rebindChildren();
+ }
+ };
+
+ private final DataSetObserver mDataObserver = new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ if (mCount > getDesiredCount()) {
+ mCount = getDesiredCount();
+ }
+ postRebindChildren();
+ }
+
+ @Override
+ public void onInvalidated() {
+ postRebindChildren();
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
index ba07bf4..5cb46ac 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
@@ -118,6 +118,10 @@
}
ImageView first = (ImageView) getChildAt(firstIndex);
ImageView second = (ImageView) getChildAt(secondIndex);
+ if (second == null) {
+ // Weird state where number of pages must not have propagated yet.
+ return;
+ }
// Lay the two views on top of each other.
second.setTranslationX(first.getX() - second.getX());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 115c9d0..5a23610 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -1,6 +1,8 @@
package com.android.systemui.qs;
import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
@@ -199,11 +201,22 @@
@Override
public boolean updateResources() {
- if (super.updateResources()) {
- mMaxRows = mColumns != 3 ? 2 : 3;
- return true;
+ final int rows = getRows();
+ boolean changed = rows != mMaxRows;
+ if (changed) {
+ mMaxRows = rows;
+ requestLayout();
}
- return false;
+ return super.updateResources() || changed;
+ }
+
+ private int getRows() {
+ final Resources res = getContext().getResources();
+ if (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
+ // Always have 3 rows in portrait.
+ return 3;
+ }
+ return Math.max(1, res.getInteger(R.integer.quick_settings_num_rows));
}
public void setMaxRows(int maxRows) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index de8eec4..4d959d8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -157,7 +157,7 @@
for (QSTile<?> tile : tiles) {
QSTileBaseView tileView = mQsPanel.getTileView(tile);
final TextView label = ((QSTileView) tileView).getLabel();
- final View tileIcon = tileView.getIcon();
+ final View tileIcon = tileView.getIcon().getIconView();
if (count < mNumQuickTiles && mAllowFancy) {
// Quick tiles.
QSTileBaseView quickTileView = mQuickQsPanel.getTileView(tile);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
index 5d06aeb..e3a4909 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
@@ -47,10 +47,10 @@
private final Rect mQsBounds = new Rect();
private int mHeightOverride = -1;
- private QSPanel mQSPanel;
+ protected QSPanel mQSPanel;
private QSDetail mQSDetail;
protected BaseStatusBarHeader mHeader;
- private float mQsExpansion;
+ protected float mQsExpansion;
private boolean mQsExpanded;
private boolean mHeaderAnimating;
private boolean mKeyguardShowing;
@@ -100,7 +100,13 @@
// 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);
+ mQSPanel.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(
+ MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED));
+ int width = mQSPanel.getMeasuredWidth();
+ int height = ((LayoutParams) mQSPanel.getLayoutParams()).topMargin
+ + mQSPanel.getMeasuredHeight();
+ super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
// QSCustomizer is always be the height of the screen, but do this after
// other measuring to avoid changing the height of the QSContainer.
@@ -156,14 +162,18 @@
}
private void updateBottom() {
- int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
- int height = mQSCustomizer.isCustomizing() ? mQSCustomizer.getHeight()
- : (int) (mQsExpansion * (heightOverride - mHeader.getCollapsedHeight()))
- + mHeader.getCollapsedHeight();
+ int height = calculateContainerHeight();
setBottom(getTop() + height);
mQSDetail.setBottom(getTop() + height);
}
+ protected int calculateContainerHeight() {
+ int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
+ return mQSCustomizer.isCustomizing() ? mQSCustomizer.getHeight()
+ : (int) (mQsExpansion * (heightOverride - mHeader.getCollapsedHeight()))
+ + mHeader.getCollapsedHeight();
+ }
+
private void updateQsState() {
boolean expandVisually = mQsExpanded || mStackScrollerOverscrolling || mHeaderAnimating;
mQSPanel.setExpanded(mQsExpanded);
@@ -296,4 +306,8 @@
updateQsState();
}
};
+
+ public int getQsMinExpansionHeight() {
+ return mHeader.getHeight();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
index 25b9105..2dd4a0a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
@@ -28,11 +28,10 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
-import android.widget.LinearLayout;
import android.widget.TextView;
-
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
@@ -45,16 +44,17 @@
private final Context mContext;
private final H mHandler = new H();
+ private final Adapter mAdapter = new Adapter();
private String mTag;
private Callback mCallback;
private boolean mItemsVisible = true;
- private LinearLayout mItems;
+ private AutoSizingList mItemList;
private View mEmpty;
- private View mMinHeightSpacer;
private TextView mEmptyText;
private ImageView mEmptyIcon;
- private int mMaxItems;
+
+ private Item[] mItems;
public QSDetailItems(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -73,27 +73,22 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mItems = (LinearLayout) findViewById(android.R.id.list);
- mItems.setVisibility(GONE);
+ mItemList = (AutoSizingList) findViewById(android.R.id.list);
+ mItemList.setVisibility(GONE);
+ mItemList.setAdapter(mAdapter);
mEmpty = findViewById(android.R.id.empty);
mEmpty.setVisibility(GONE);
mEmptyText = (TextView) mEmpty.findViewById(android.R.id.title);
mEmptyIcon = (ImageView) mEmpty.findViewById(android.R.id.icon);
- mMinHeightSpacer = findViewById(R.id.min_height_spacer);
-
- // By default, a detail item view has fixed size.
- mMaxItems = getResources().getInteger(
- R.integer.quick_settings_detail_max_item_count);
- setMinHeightInItems(mMaxItems);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
FontSizeUtils.updateFontSize(mEmptyText, R.dimen.qs_detail_empty_text_size);
- int count = mItems.getChildCount();
+ int count = mItemList.getChildCount();
for (int i = 0; i < count; i++) {
- View item = mItems.getChildAt(i);
+ View item = mItemList.getChildAt(i);
FontSizeUtils.updateFontSize(item, android.R.id.title,
R.dimen.qs_detail_item_primary_text_size);
FontSizeUtils.updateFontSize(item, android.R.id.summary,
@@ -110,16 +105,6 @@
mEmptyText.setText(text);
}
- /**
- * Set the minimum height of this detail view, in item count.
- */
- public void setMinHeightInItems(int minHeightInItems) {
- ViewGroup.LayoutParams lp = mMinHeightSpacer.getLayoutParams();
- lp.height = minHeightInItems * getResources().getDimensionPixelSize(
- R.dimen.qs_detail_item_height);
- mMinHeightSpacer.setLayoutParams(lp);
- }
-
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -153,65 +138,82 @@
}
private void handleSetItems(Item[] items) {
- final int itemCount = items != null ? Math.min(items.length, mMaxItems) : 0;
+ final int itemCount = items != null ? items.length : 0;
mEmpty.setVisibility(itemCount == 0 ? VISIBLE : GONE);
- mItems.setVisibility(itemCount == 0 ? GONE : VISIBLE);
- for (int i = mItems.getChildCount() - 1; i >= itemCount; i--) {
- mItems.removeViewAt(i);
- }
- for (int i = 0; i < itemCount; i++) {
- bind(items[i], mItems.getChildAt(i));
- }
+ mItemList.setVisibility(itemCount == 0 ? GONE : VISIBLE);
+ mItems = items;
+ mAdapter.notifyDataSetChanged();
}
private void handleSetItemsVisible(boolean visible) {
if (mItemsVisible == visible) return;
mItemsVisible = visible;
- for (int i = 0; i < mItems.getChildCount(); i++) {
- mItems.getChildAt(i).setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
+ for (int i = 0; i < mItemList.getChildCount(); i++) {
+ mItemList.getChildAt(i).setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
}
}
- private void bind(final Item item, View view) {
- if (view == null) {
- view = LayoutInflater.from(mContext).inflate(R.layout.qs_detail_item, this, false);
- mItems.addView(view);
+ private class Adapter extends BaseAdapter {
+
+ @Override
+ public int getCount() {
+ return mItems != null ? mItems.length : 0;
}
- view.setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
- final ImageView iv = (ImageView) view.findViewById(android.R.id.icon);
- iv.setImageResource(item.icon);
- iv.getOverlay().clear();
- if (item.overlay != null) {
- item.overlay.setBounds(0, 0, item.overlay.getIntrinsicWidth(),
- item.overlay.getIntrinsicHeight());
- iv.getOverlay().add(item.overlay);
+
+ @Override
+ public Object getItem(int position) {
+ return mItems[position];
}
- final TextView title = (TextView) view.findViewById(android.R.id.title);
- title.setText(item.line1);
- final TextView summary = (TextView) view.findViewById(android.R.id.summary);
- final boolean twoLines = !TextUtils.isEmpty(item.line2);
- title.setMaxLines(twoLines ? 1 : 2);
- summary.setVisibility(twoLines ? VISIBLE : GONE);
- summary.setText(twoLines ? item.line2 : null);
- view.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mCallback != null) {
- mCallback.onDetailItemClick(item);
- }
+
+ @Override
+ public long getItemId(int position) {
+ return 0;
+ }
+
+ @Override
+ public View getView(int position, View view, ViewGroup parent) {
+ final Item item = mItems[position];
+ if (view == null) {
+ view = LayoutInflater.from(mContext).inflate(R.layout.qs_detail_item, parent,
+ false);
}
- });
- final ImageView disconnect = (ImageView) view.findViewById(android.R.id.icon2);
- disconnect.setVisibility(item.canDisconnect ? VISIBLE : GONE);
- disconnect.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mCallback != null) {
- mCallback.onDetailItemDisconnect(item);
- }
+ view.setVisibility(mItemsVisible ? VISIBLE : INVISIBLE);
+ final ImageView iv = (ImageView) view.findViewById(android.R.id.icon);
+ iv.setImageResource(item.icon);
+ iv.getOverlay().clear();
+ if (item.overlay != null) {
+ item.overlay.setBounds(0, 0, item.overlay.getIntrinsicWidth(),
+ item.overlay.getIntrinsicHeight());
+ iv.getOverlay().add(item.overlay);
}
- });
- }
+ final TextView title = (TextView) view.findViewById(android.R.id.title);
+ title.setText(item.line1);
+ final TextView summary = (TextView) view.findViewById(android.R.id.summary);
+ final boolean twoLines = !TextUtils.isEmpty(item.line2);
+ title.setMaxLines(twoLines ? 1 : 2);
+ summary.setVisibility(twoLines ? VISIBLE : GONE);
+ summary.setText(twoLines ? item.line2 : null);
+ view.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mCallback != null) {
+ mCallback.onDetailItemClick(item);
+ }
+ }
+ });
+ final ImageView disconnect = (ImageView) view.findViewById(android.R.id.icon2);
+ disconnect.setVisibility(item.canDisconnect ? VISIBLE : GONE);
+ disconnect.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mCallback != null) {
+ mCallback.onDetailItemDisconnect(item);
+ }
+ }
+ });
+ return view;
+ }
+ };
private class H extends Handler {
private static final int SET_ITEMS = 1;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
index 546f8c3..6c224f7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
@@ -30,9 +30,9 @@
public class QSIconView extends ViewGroup {
- private final View mIcon;
- private final int mIconSizePx;
- private final int mTilePaddingBelowIconPx;
+ protected final View mIcon;
+ protected final int mIconSizePx;
+ protected final int mTilePaddingBelowIconPx;
private boolean mAnimationEnabled = true;
public QSIconView(Context context) {
@@ -50,6 +50,10 @@
mAnimationEnabled = false;
}
+ public View getIconView() {
+ return mIcon;
+ }
+
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int w = MeasureSpec.getSize(widthMeasureSpec);
@@ -109,11 +113,11 @@
return icon;
}
- protected static int exactly(int size) {
+ protected final int exactly(int size) {
return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
}
- protected static void layout(View child, int left, int top) {
+ protected final void layout(View child, int left, int top) {
child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index a05818a..1149c59 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -85,20 +85,7 @@
R.layout.quick_settings_brightness_dialog, this, false);
addView(mBrightnessView);
- mTileLayout = (QSTileLayout) LayoutInflater.from(mContext).inflate(
- 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) {
- mHost.startRunnableDismissingKeyguard(new Runnable() {
- @Override
- public void run() {
- showEdit(v);
- }
- });
- }
- });
+ setupTileLayout();
mFooter = new QSFooter(this, context);
addView(mFooter.getView());
@@ -111,6 +98,14 @@
}
+ protected void setupTileLayout() {
+ mTileLayout = (QSTileLayout) LayoutInflater.from(mContext).inflate(
+ R.layout.qs_paged_tile_layout, this, false);
+ addView((View) mTileLayout);
+ findViewById(android.R.id.edit).setOnClickListener(view ->
+ mHost.startRunnableDismissingKeyguard(() -> showEdit(view)));
+ }
+
public boolean isShowingCustomize() {
return mCustomizePanel != null && mCustomizePanel.isCustomizing();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index 57a1a4a..c3766e8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -33,7 +33,6 @@
/** View that represents a standard quick settings tile. **/
public class QSTileView extends QSTileBaseView {
protected final Context mContext;
- private QSIconView mIconView;
private final int mTileSpacingPx;
private int mTilePaddingTopPx;
@@ -44,7 +43,6 @@
super(context, icon);
mContext = context;
- mIconView = icon;
final Resources res = context.getResources();
mTileSpacingPx = res.getDimensionPixelSize(R.dimen.qs_tile_spacing);
@@ -82,13 +80,13 @@
}
protected void createLabel() {
- final Resources res = mContext.getResources();
View view = LayoutInflater.from(mContext).inflate(R.layout.qs_tile_label, null);
mLabel = (TextView) view.findViewById(R.id.tile_label);
mPadLock = (ImageView) view.findViewById(R.id.restricted_padlock);
addView(view);
}
+ @Override
protected void handleStateChanged(QSTile.State state) {
super.handleStateChanged(state);
if (!Objects.equal(mLabel.getText(), state.label)) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 55eda98..1e3c458 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -19,11 +19,12 @@
private static final String TAG = "TileLayout";
protected int mColumns;
- private int mCellWidth;
- private int mCellHeight;
- private int mCellMargin;
+ protected int mCellWidth;
+ protected int mCellHeight;
+ protected int mCellMargin;
protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
+ private int mCellMarginTop;
public TileLayout(Context context) {
this(context, null);
@@ -60,9 +61,10 @@
final int columns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
mCellHeight = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_height);
mCellMargin = res.getDimensionPixelSize(R.dimen.qs_tile_margin);
+ mCellMarginTop = res.getDimensionPixelSize(R.dimen.qs_tile_margin_top);
if (mColumns != columns) {
mColumns = columns;
- postInvalidate();
+ requestLayout();
return true;
}
return false;
@@ -81,7 +83,8 @@
record.tileView.measure(exactly(mCellWidth), exactly(mCellHeight));
previousView = record.tileView.updateAccessibilityOrder(previousView);
}
- setMeasuredDimension(width, (mCellHeight + mCellMargin) * rows);
+ setMeasuredDimension(width,
+ (mCellHeight + mCellMargin) * rows + (mCellMarginTop - mCellMargin));
}
private static int exactly(int size) {
@@ -114,7 +117,7 @@
}
private int getRowTop(int row) {
- return row * (mCellHeight + mCellMargin) + mCellMargin;
+ return row * (mCellHeight + mCellMargin) + mCellMarginTop;
}
private int getColumnStart(int column) {
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 6114573..6b20681 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -138,7 +138,7 @@
mListening = listening;
try {
if (listening) {
- if (mServiceManager.getType() == TileService.TILE_MODE_PASSIVE) {
+ if (!mServiceManager.isActiveTile()) {
mServiceManager.setBindRequested(true);
mService.onStartListening();
}
@@ -209,7 +209,7 @@
} catch (RemoteException e) {
}
try {
- if (mServiceManager.getType() == TileService.TILE_MODE_ACTIVE) {
+ if (mServiceManager.isActiveTile()) {
mServiceManager.setBindRequested(true);
mService.onStartListening();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 8910d44..5a26a4a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -15,8 +15,6 @@
*/
package com.android.systemui.qs.external;
-import libcore.util.Objects;
-
import android.app.AppGlobals;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -25,6 +23,7 @@
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ServiceInfo;
import android.net.Uri;
import android.os.Handler;
@@ -34,9 +33,11 @@
import android.service.quicksettings.IQSService;
import android.service.quicksettings.IQSTileService;
import android.service.quicksettings.Tile;
+import android.service.quicksettings.TileService;
import android.support.annotation.VisibleForTesting;
import android.util.ArraySet;
import android.util.Log;
+import libcore.util.Objects;
import java.util.Set;
@@ -98,6 +99,17 @@
}
}
+ public boolean isActiveTile() {
+ try {
+ ServiceInfo info = mContext.getPackageManager().getServiceInfo(mIntent.getComponent(),
+ PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_META_DATA);
+ return info.metaData != null
+ && info.metaData.getBoolean(TileService.META_DATA_ACTIVE_TILE, false);
+ } catch (NameNotFoundException e) {
+ return false;
+ }
+ }
+
/**
* Binds just long enough to send any queued messages, then unbinds.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index 664ddd6..ab21532 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -21,7 +21,6 @@
import android.os.Handler;
import android.os.UserHandle;
import android.service.quicksettings.IQSTileService;
-import android.service.quicksettings.TileService;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
@@ -51,7 +50,6 @@
private int mPriority;
private boolean mJustBound;
private long mLastUpdate;
- private int mType;
private boolean mShowingDialog;
// Whether we have a pending bind going out to the service without a response yet.
// This defaults to true to ensure tiles start out unavailable.
@@ -69,25 +67,11 @@
mServices = tileServices;
mHandler = handler;
mStateManager = tileLifecycleManager;
- mType = tileServices.getContext().getSharedPreferences(PREFS_FILE, 0)
- .getInt(tileLifecycleManager.getComponent().flattenToString(),
- TileService.TILE_MODE_UNSET);
mStateManager.setQSService(tileServices);
- if (mType == TileService.TILE_MODE_UNSET) {
- bindService();
- mStateManager.onTileAdded();
- }
}
- public int getType() {
- return mType;
- }
-
- public void setType(int type) {
- mServices.getContext().getSharedPreferences(PREFS_FILE, 0).edit()
- .putInt(mStateManager.getComponent().flattenToString(), type).commit();
- mType = type;
- mServices.recalculateBindAllowance();
+ public boolean isActiveTile() {
+ return mStateManager.isActiveTile();
}
public void setShowingDialog(boolean dialog) {
@@ -114,7 +98,7 @@
public void setLastUpdate(long lastUpdate) {
mLastUpdate = lastUpdate;
- if (mBound && mType == TileService.TILE_MODE_ACTIVE) {
+ if (mBound && isActiveTile()) {
mStateManager.onStopListening();
setBindRequested(false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 5bb2a35..f36d013 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -153,7 +153,7 @@
return;
}
TileServiceManager service = mServices.get(customTile);
- if (service.getType() != TileService.TILE_MODE_ACTIVE) {
+ if (!service.isActiveTile()) {
return;
}
service.setBindRequested(true);
@@ -165,17 +165,6 @@
}
@Override
- public void setTileMode(ComponentName component, int mode) {
- verifyCaller(component.getPackageName());
- CustomTile customTile = getTileForComponent(component);
- if (customTile != null) {
- synchronized (mServices) {
- mServices.get(customTile).setType(mode);
- }
- }
- }
-
- @Override
public void updateQsTile(Tile tile) {
ComponentName componentName = tile.getComponentName();
verifyCaller(componentName.getPackageName());
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 2032783..77eaa3b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -25,6 +25,7 @@
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.RelativeSizeSpan;
+import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
@@ -129,6 +130,8 @@
}
};
state.label = percentage;
+ state.contentDescription = mContext.getString(R.string.accessibility_quick_settings_battery,
+ percentage);
}
@Override
@@ -207,18 +210,21 @@
}
}
});
+ final TextView batterySaverTitle =
+ (TextView) mCurrentView.findViewById(android.R.id.title);
+ final TextView batterySaverSummary =
+ (TextView) mCurrentView.findViewById(android.R.id.summary);
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);
+ mCurrentView.findViewById(R.id.switch_container).setAlpha(.7f);
+ batterySaverTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
+ batterySaverTitle.setText(R.string.battery_detail_charging_summary);
mCurrentView.findViewById(android.R.id.toggle).setVisibility(View.GONE);
mCurrentView.findViewById(R.id.switch_container).setClickable(false);
} else {
- ((TextView) mCurrentView.findViewById(android.R.id.title)).setText(
- R.string.battery_detail_switch_title);
- ((TextView) mCurrentView.findViewById(android.R.id.summary)).setText(
- R.string.battery_detail_switch_summary);
- mCurrentView.findViewById(android.R.id.icon).setVisibility(View.VISIBLE);
+ mCurrentView.findViewById(R.id.switch_container).setAlpha(1);
+ batterySaverTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
+ batterySaverTitle.setText(R.string.battery_detail_switch_title);
+ batterySaverSummary.setText(R.string.battery_detail_switch_summary);
mCurrentView.findViewById(android.R.id.toggle).setVisibility(View.VISIBLE);
mCurrentView.findViewById(R.id.switch_container).setClickable(true);
mCurrentView.findViewById(R.id.switch_container).setOnClickListener(this);
@@ -227,7 +233,7 @@
private void bindBatteryInfo(BatteryInfo info) {
SpannableStringBuilder builder = new SpannableStringBuilder();
- builder.append(info.batteryPercentString, new RelativeSizeSpan(2),
+ builder.append(info.batteryPercentString, new RelativeSizeSpan(2.6f),
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
if (info.remainingLabel != null) {
if (mContext.getResources().getBoolean(R.bool.quick_settings_wide)) {
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 1fef8f1..63c85db 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -216,7 +216,6 @@
mItems.setEmptyState(R.drawable.ic_qs_bluetooth_detail_empty,
R.string.quick_settings_bluetooth_detail_empty_text);
mItems.setCallback(this);
- mItems.setMinHeightInItems(0);
updateItems();
setItemsVisible(mState.value);
return mItems;
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 fcf758b..99eae02 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
@@ -30,6 +30,7 @@
import android.widget.TextView;
import com.android.internal.util.ArrayUtils;
+import com.android.settingslib.drawable.UserIconDrawable;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.UserAvatarView;
@@ -87,25 +88,29 @@
return (UserDetailItemView) convertView;
}
- public void bind(String name, Bitmap picture) {
+ public void bind(String name, Bitmap picture, int userId) {
mName.setText(name);
- mAvatar.setBitmap(picture);
+ mAvatar.setAvatarWithBadge(picture, userId);
}
- public void bind(String name, Drawable picture) {
+ public void bind(String name, Drawable picture, int userId) {
mName.setText(name);
- mAvatar.setDrawable(picture);
+ mAvatar.setDrawableWithBadge(picture, userId);
+ }
+
+ public void setAvatarEnabled(boolean enabled) {
+ mAvatar.setEnabled(enabled);
}
public void setDisabledByAdmin(boolean disabled) {
mRestrictedPadlock.setVisibility(disabled ? View.VISIBLE : View.GONE);
mName.setEnabled(!disabled);
- mAvatar.setDisabled(disabled);
+ mAvatar.setEnabled(!disabled);
}
public void setEnabled(boolean enabled) {
mName.setEnabled(enabled);
- mAvatar.setDisabled(!enabled);
+ mAvatar.setEnabled(enabled);
}
@Override
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 da98762..d4fa765 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -76,9 +76,9 @@
}
String name = getName(mContext, item);
if (item.picture == null) {
- v.bind(name, getDrawable(mContext, item));
+ v.bind(name, getDrawable(mContext, item), item.resolveId());
} else {
- v.bind(name, item.picture);
+ v.bind(name, item.picture, item.info.id);
}
v.setActivated(item.isCurrent);
v.setDisabledByAdmin(item.isDisabledByAdmin);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index aba05aa..fda340d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -17,6 +17,7 @@
package com.android.systemui.recents;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.view.View.MeasureSpec;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -36,7 +37,6 @@
import android.util.MutableBoolean;
import android.view.AppTransitionAnimationSpec;
import android.view.LayoutInflater;
-import android.view.View;
import android.view.ViewConfiguration;
import com.android.internal.logging.MetricsLogger;
@@ -45,7 +45,6 @@
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
-import com.android.systemui.recents.events.activity.ForcedResizableEvent;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
import com.android.systemui.recents.events.activity.IterateRecentsEvent;
import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
@@ -125,13 +124,6 @@
loader.loadTasks(mContext, plan, launchOpts);
}
}
-
- @Override
- public void onActivityForcedResizable(String packageName, int taskId) {
- EventBus.getDefault().sendOntoMainThread(
- new ForcedResizableEvent(packageName, taskId));
-
- }
}
protected static RecentsTaskLoadPlan sInstanceLoadPlan;
@@ -608,23 +600,25 @@
mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */);
Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
- int taskViewWidth = taskViewBounds.width();
- synchronized (mHeaderBarLock) {
- if (mHeaderBar.getMeasuredWidth() != taskViewWidth ||
- mHeaderBar.getMeasuredHeight() != mTaskBarHeight) {
- mHeaderBar.measure(
- View.MeasureSpec.makeMeasureSpec(taskViewWidth, View.MeasureSpec.EXACTLY),
- View.MeasureSpec.makeMeasureSpec(mTaskBarHeight, View.MeasureSpec.EXACTLY));
+ if (!taskViewBounds.isEmpty()) {
+ int taskViewWidth = taskViewBounds.width();
+ synchronized (mHeaderBarLock) {
+ if (mHeaderBar.getMeasuredWidth() != taskViewWidth ||
+ mHeaderBar.getMeasuredHeight() != mTaskBarHeight) {
+ mHeaderBar.measure(
+ MeasureSpec.makeMeasureSpec(taskViewWidth, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(mTaskBarHeight, MeasureSpec.EXACTLY));
+ }
+ mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight);
}
- mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight);
- }
- // Update the transition bitmap to match the new header bar height
- if (mThumbTransitionBitmapCache == null ||
- (mThumbTransitionBitmapCache.getWidth() != taskViewWidth) ||
- (mThumbTransitionBitmapCache.getHeight() != mTaskBarHeight)) {
- mThumbTransitionBitmapCache = Bitmap.createBitmap(taskViewWidth,
- mTaskBarHeight, Bitmap.Config.ARGB_8888);
+ // Update the transition bitmap to match the new header bar height
+ if (mThumbTransitionBitmapCache == null ||
+ (mThumbTransitionBitmapCache.getWidth() != taskViewWidth) ||
+ (mThumbTransitionBitmapCache.getHeight() != mTaskBarHeight)) {
+ mThumbTransitionBitmapCache = Bitmap.createBitmap(taskViewWidth,
+ mTaskBarHeight, Bitmap.Config.ARGB_8888);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ForcedResizableEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ForcedResizableEvent.java
deleted file mode 100644
index cdcabf0..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ForcedResizableEvent.java
+++ /dev/null
@@ -1,34 +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.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * Sent when recents received the information that an activity got forced resizable, and we need
- * to inform the user about that.
- */
-public class ForcedResizableEvent extends EventBus.Event {
-
- public final String packageName;
- public final int taskId;
-
- public ForcedResizableEvent(String packageName, int taskId) {
- this.packageName = packageName;
- this.taskId = taskId;
- }
-}
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 1a4b40f..2d5addb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -144,6 +144,7 @@
public void onPinnedActivityRestartAttempt() { }
public void onPinnedStackAnimationEnded() { }
public void onActivityForcedResizable(String packageName, int taskId) { }
+ public void onActivityDismissingDockedStack() { }
}
/**
@@ -182,6 +183,11 @@
mHandler.obtainMessage(H.ON_ACTIVITY_FORCED_RESIZABLE, taskId, 0, packageName)
.sendToTarget();
}
+
+ @Override
+ public void onActivityDismissingDockedStack() throws RemoteException {
+ mHandler.sendEmptyMessage(H.ON_ACTIVITY_DISMISSING_DOCKED_STACK);
+ }
};
/**
@@ -1091,6 +1097,7 @@
private static final int ON_PINNED_ACTIVITY_RESTART_ATTEMPT = 3;
private static final int ON_PINNED_STACK_ANIMATION_ENDED = 4;
private static final int ON_ACTIVITY_FORCED_RESIZABLE = 5;
+ private static final int ON_ACTIVITY_DISMISSING_DOCKED_STACK = 6;
@Override
public void handleMessage(Message msg) {
@@ -1126,6 +1133,12 @@
}
break;
}
+ case ON_ACTIVITY_DISMISSING_DOCKED_STACK: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onActivityDismissingDockedStack();
+ }
+ break;
+ }
}
}
}
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 f9f851a..13e1a14 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
@@ -37,14 +37,12 @@
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
-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.ToggleRecentsEvent;
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.UpdateFreeformTaskViewVisibilityEvent;
import com.android.systemui.recents.events.ui.UserInteractionEvent;
import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -53,7 +51,9 @@
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.tv.animations.HomeRecentsEnterExitAnimationHolder;
import com.android.systemui.recents.tv.views.RecentsTvView;
+import com.android.systemui.recents.tv.views.TaskStackHorizontalGridView;
import com.android.systemui.recents.tv.views.TaskStackHorizontalViewAdapter;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.tv.pip.PipManager;
@@ -76,11 +76,14 @@
private RecentsPackageMonitor mPackageMonitor;
private long mLastTabKeyEventTime;
private boolean mIgnoreAltTabRelease;
+ private boolean mLaunchedFromHome;
private RecentsTvView mRecentsView;
private View mPipView;
private TaskStackHorizontalViewAdapter mTaskStackViewAdapter;
+ private TaskStackHorizontalGridView mTaskStackHorizontalGridView;
private FinishRecentsRunnable mFinishLaunchHomeRunnable;
+ private HomeRecentsEnterExitAnimationHolder mHomeRecentsEnterExitAnimationHolder;
private final PipManager mPipManager = PipManager.getInstance();
private final PipManager.Listener mPipListener = new PipManager.Listener() {
@@ -174,6 +177,7 @@
if (!plan.hasTasks()) {
loader.preloadTasks(plan, -1, launchState.launchedFromHome);
}
+ mLaunchedFromHome = launchState.launchedFromHome;
TaskStack stack = plan.getTaskStack();
RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
loadOpts.runningTaskId = launchState.launchedToTaskId;
@@ -187,7 +191,8 @@
Collections.reverse(stackTasks);
if (mTaskStackViewAdapter == null) {
mTaskStackViewAdapter = new TaskStackHorizontalViewAdapter(stackTasks);
- mRecentsView.setTaskStackViewAdapter(mTaskStackViewAdapter);
+ mTaskStackHorizontalGridView = mRecentsView
+ .setTaskStackViewAdapter(mTaskStackViewAdapter);
} else {
mTaskStackViewAdapter.setNewStackTasks(stackTasks);
}
@@ -229,17 +234,24 @@
}
void dismissRecentsToHome(boolean animateTaskViews) {
- DismissRecentsToHomeAnimationStarted dismissEvent =
- new DismissRecentsToHomeAnimationStarted(animateTaskViews);
- dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
- dismissEvent.addPostAnimationCallback(new Runnable() {
+ Runnable closeSystemWindows = new Runnable() {
@Override
public void run() {
Recents.getSystemServices().sendCloseSystemWindows(
BaseStatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
}
- });
- EventBus.getDefault().send(dismissEvent);
+ };
+ DismissRecentsToHomeAnimationStarted dismissEvent =
+ new DismissRecentsToHomeAnimationStarted(animateTaskViews);
+ dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
+ dismissEvent.addPostAnimationCallback(closeSystemWindows);
+
+ if(mTaskStackHorizontalGridView.getChildCount() > 0) {
+ mHomeRecentsEnterExitAnimationHolder.startExitAnimation(dismissEvent);
+ } else {
+ closeSystemWindows.run();
+ mFinishLaunchHomeRunnable.run();
+ }
}
boolean dismissRecentsToHomeIfVisible(boolean animated) {
@@ -319,6 +331,19 @@
// Update the recent tasks
updateRecentsTasks();
+ mHomeRecentsEnterExitAnimationHolder = new HomeRecentsEnterExitAnimationHolder(
+ getApplicationContext(), mTaskStackHorizontalGridView);
+ if(mTaskStackHorizontalGridView != null &&
+ mTaskStackHorizontalGridView.getChildCount() > 0) {
+ if(mLaunchedFromHome) {
+ mHomeRecentsEnterExitAnimationHolder.setEnterFromHomeStartingAnimationValues();
+ } else {
+ mHomeRecentsEnterExitAnimationHolder.setEnterFromAppStartingAnimationValues();
+ }
+ } else {
+ mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
+ }
+
// 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
@@ -340,6 +365,9 @@
@Override
public void onEnterAnimationComplete() {
super.onEnterAnimationComplete();
+ if(mLaunchedFromHome) {
+ mHomeRecentsEnterExitAnimationHolder.startEnterAnimation();
+ }
EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
}
@@ -444,12 +472,6 @@
}
}
- public final void onBusEvent(EnterRecentsWindowLastAnimationFrameEvent event) {
- EventBus.getDefault().send(new UpdateFreeformTaskViewVisibilityEvent(true));
- mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
- mRecentsView.invalidate();
- }
-
public final void onBusEvent(CancelEnterRecentsWindowAnimationEvent event) {
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
int launchToTaskId = launchState.launchedToTaskId;
@@ -489,6 +511,11 @@
@Override
public boolean onPreDraw() {
mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
+ if(mLaunchedFromHome) {
+ mHomeRecentsEnterExitAnimationHolder.setEnterFromHomeStartingAnimationValues();
+ } else {
+ mHomeRecentsEnterExitAnimationHolder.setEnterFromAppStartingAnimationValues();
+ }
// We post to make sure that this information is delivered after this traversals is
// finished.
mRecentsView.post(new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
index fb62aff..fd31872 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
@@ -25,15 +25,19 @@
import android.os.SystemClock;
import android.os.UserHandle;
+import com.android.systemui.SystemUIApplication;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsImpl;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.model.ThumbnailData;
import com.android.systemui.recents.tv.views.TaskCardView;
+import com.android.systemui.statusbar.tv.TvStatusBar;
public class RecentsTvImpl extends RecentsImpl{
public final static String RECENTS_TV_ACTIVITY =
@@ -81,16 +85,7 @@
}
if (!useThumbnailTransition) {
- // If there is no thumbnail transition, but is launching from home into recents, then
- // use a quick home transition and do the animation from home
- if (hasRecentTasks) {
- ActivityOptions opts = getHomeTransitionActivityOptions();
- startRecentsActivity(topTask, opts, true /* fromHome */, false /* fromThumbnail */);
- } else {
- // Otherwise we do the normal fade from an unknown source
- ActivityOptions opts = getUnknownTransitionActivityOptions();
- startRecentsActivity(topTask, opts, true /* fromHome */, false /* fromThumbnail */);
- }
+ startRecentsActivity(topTask, null, true /* fromHome */, false /* fromThumbnail */);
}
mLastToggleTime = SystemClock.elapsedRealtime();
}
@@ -124,14 +119,26 @@
*/
private ActivityOptions getThumbnailTransitionActivityOptionsForTV(
ActivityManager.RunningTaskInfo topTask) {
- Bitmap thumbnail = mThumbTransitionBitmapCache;
Rect rect = TaskCardView.getStartingCardThumbnailRect(mContext);
- if (thumbnail != null) {
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ ThumbnailData thumbnailData = ssp.getTaskThumbnail(topTask.id);
+ if (thumbnailData.thumbnail != null) {
+ Bitmap thumbnail = Bitmap.createScaledBitmap(thumbnailData.thumbnail, rect.width(),
+ rect.height(), false);
return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
- null, (int) rect.left, (int) rect.top,
- (int) rect.width(), (int) rect.height(), mHandler, null);
+ thumbnail, (int) rect.left, (int) rect.top, (int) rect.width(),
+ (int) rect.height(), mHandler, null);
}
// If both the screenshot and thumbnail fails, then just fall back to the default transition
return getUnknownTransitionActivityOptions();
}
+
+ @Override
+ public void onVisibilityChanged(Context context, boolean visible) {
+ SystemUIApplication app = (SystemUIApplication) context;
+ TvStatusBar statusBar = app.getComponent(TvStatusBar.class);
+ if (statusBar != null) {
+ statusBar.updateRecentsVisibility(visible);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java
index 8996d0b..fbcfa97 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java
@@ -18,9 +18,8 @@
import android.animation.Animator;
import android.content.res.Resources;
-import android.support.v4.view.animation.FastOutSlowInInterpolator;
-import android.view.View;
import android.widget.LinearLayout;
+import com.android.systemui.Interpolators;
import com.android.systemui.recents.tv.views.TaskCardView;
import com.android.systemui.R;
@@ -28,7 +27,6 @@
public class DismissAnimationsHolder {
private LinearLayout mDismissArea;
private LinearLayout mTaskCardView;
- private FastOutSlowInInterpolator mFastOutSlowIn;
private int mCardYDelta;
private long mShortDuration;
private long mLongDuration;
@@ -36,7 +34,6 @@
public DismissAnimationsHolder(TaskCardView taskCardView) {
mTaskCardView = (LinearLayout) taskCardView.findViewById(R.id.recents_tv_card);
mDismissArea = (LinearLayout) taskCardView.findViewById(R.id.card_dismiss);
- mFastOutSlowIn = new FastOutSlowInInterpolator();
Resources res = taskCardView.getResources();
mCardYDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_shift_down);
@@ -45,36 +42,42 @@
}
public void startEnterAnimation() {
- mDismissArea.animate().setDuration(mShortDuration);
- mDismissArea.animate().setInterpolator(mFastOutSlowIn);
- mDismissArea.animate().alpha(1.0f);
+ mDismissArea.animate()
+ .setDuration(mShortDuration)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .alpha(1.0f);
- mTaskCardView.animate().setDuration(mShortDuration);
- mTaskCardView.animate().setInterpolator(mFastOutSlowIn);
- mTaskCardView.animate().translationYBy(mCardYDelta);
- mTaskCardView.animate().alpha(0.5f);
+ mTaskCardView.animate()
+ .setDuration(mShortDuration)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .translationYBy(mCardYDelta)
+ .alpha(0.5f);
}
public void startExitAnimation() {
- mDismissArea.animate().setDuration(mShortDuration);
- mDismissArea.animate().setInterpolator(mFastOutSlowIn);
- mDismissArea.animate().alpha(0.0f);
+ mDismissArea.animate()
+ .setDuration(mShortDuration)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .alpha(0.0f);
- mTaskCardView.animate().setDuration(mShortDuration);
- mTaskCardView.animate().setInterpolator(mFastOutSlowIn);
- mTaskCardView.animate().translationYBy(-mCardYDelta);
- mTaskCardView.animate().alpha(1.0f);
+ mTaskCardView.animate()
+ .setDuration(mShortDuration)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .translationYBy(-mCardYDelta)
+ .alpha(1.0f);
}
public void startDismissAnimation(Animator.AnimatorListener listener) {
- mDismissArea.animate().setDuration(mShortDuration);
- mDismissArea.animate().setInterpolator(mFastOutSlowIn);
- mDismissArea.animate().alpha(0.0f);
+ mDismissArea.animate()
+ .setDuration(mShortDuration)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .alpha(0.0f);
- mTaskCardView.animate().setDuration(mLongDuration);
- mTaskCardView.animate().setInterpolator(mFastOutSlowIn);
- mTaskCardView.animate().translationYBy(mCardYDelta);
- mTaskCardView.animate().alpha(0.0f);
- mTaskCardView.animate().setListener(listener);
+ mTaskCardView.animate()
+ .setDuration(mLongDuration)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .translationYBy(mCardYDelta)
+ .alpha(0.0f)
+ .setListener(listener);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java
new file mode 100644
index 0000000..278de87
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java
@@ -0,0 +1,91 @@
+/*
+ * 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.animations;
+
+import android.content.Context;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
+import com.android.systemui.recents.tv.views.TaskCardView;
+import com.android.systemui.recents.tv.views.TaskStackHorizontalGridView;
+
+
+public class HomeRecentsEnterExitAnimationHolder {
+
+ private Context mContext;
+ private TaskStackHorizontalGridView mGridView;
+ private long mDelay;
+ private int mDuration;
+ private int mTranslationX;
+
+ public HomeRecentsEnterExitAnimationHolder(Context context,
+ TaskStackHorizontalGridView gridView) {
+ mContext = context;
+ mGridView = gridView;
+ mTranslationX = mContext.getResources()
+ .getDimensionPixelSize(R.dimen.recents_tv_home_recents_shift);
+ mDelay = mContext.getResources().getInteger(R.integer.recents_home_delay);
+ mDuration = mContext.getResources().getInteger(R.integer.recents_home_duration);
+ }
+
+ public void startEnterAnimation() {
+ for(int i = 0; i < mGridView.getChildCount(); i++) {
+ TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
+ view.setTranslationX(-mTranslationX);
+ view.setAlpha(0.0f);
+ view.animate()
+ .alpha(1.0f)
+ .translationX(0)
+ .setDuration(mDuration)
+ .setStartDelay(mDelay * i)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ }
+ }
+
+ public void startExitAnimation(DismissRecentsToHomeAnimationStarted dismissEvent) {
+ for(int i = mGridView.getChildCount() - 1; i >= 0; i--) {
+ TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
+ view.animate()
+ .alpha(0.0f)
+ .translationXBy(-mTranslationX)
+ .setDuration(mDuration)
+ .setStartDelay(mDelay * (mGridView.getChildCount() - 1 - i))
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ if(i == 0) {
+ view.animate().setListener(dismissEvent.getAnimationTrigger()
+ .decrementOnAnimationEnd());
+ dismissEvent.getAnimationTrigger().increment();
+ }
+ }
+ }
+
+ public void setEnterFromHomeStartingAnimationValues() {
+ for(int i = 0; i < mGridView.getChildCount(); i++) {
+ TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
+ view.setTranslationX(-mTranslationX);
+ view.setAlpha(0.0f);
+ }
+ }
+
+ public void setEnterFromAppStartingAnimationValues() {
+ for(int i = 0; i < mGridView.getChildCount(); i++) {
+ TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
+ view.setTranslationX(0);
+ view.setAlpha(1.0f);
+ }
+ }
+}
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
index a69f8a2..fb1127e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
@@ -16,8 +16,10 @@
package com.android.systemui.recents.tv.views;
import android.annotation.Nullable;
+import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Context;
+import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
@@ -120,8 +122,10 @@
}
try {
Rect taskRect = taskView.getFocusedThumbnailRect();
+ Bitmap thumbnail = Bitmap.createScaledBitmap(task.thumbnail, taskRect.width(),
+ taskRect.height(), false);
WindowManagerGlobal.getWindowManagerService()
- .overridePendingAppTransitionAspectScaledThumb(task.thumbnail, taskRect.left,
+ .overridePendingAppTransitionAspectScaledThumb(thumbnail, taskRect.left,
taskRect.top, taskRect.width(), taskRect.height(), 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 9da8eed..53fdf62 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
@@ -18,7 +18,10 @@
import android.content.Context;
import android.graphics.Rect;
import android.os.Handler;
+import android.support.v7.widget.DefaultItemAnimator;
+import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowInsets;
@@ -32,15 +35,15 @@
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.ExitRecentsWindowFirstAnimationFrameEvent;
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;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.tv.animations.RecentsRowFocusAnimationHolder;
-
-import java.util.ArrayList;
-import java.util.List;
+import android.support.v7.widget.RecyclerView.OnScrollListener;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
/**
* Top level layout of recents for TV. This will show the TaskStacks using a HorizontalGridView.
@@ -58,7 +61,7 @@
private Rect mSystemInsets = new Rect();
private RecentsTvTransitionHelper mTransitionHelper;
private Handler mHandler;
-
+ private OnScrollListener mScrollListener;
public RecentsTvView(Context context) {
this(context, null);
}
@@ -111,8 +114,7 @@
if (mTaskStackHorizontalView != null) {
Task task = mTaskStackHorizontalView.getFocusedTask();
if (task != null) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- ssp.startActivityFromRecents(getContext(), task.key, task.title, null);
+ launchTaskFomRecents(task);
return true;
}
}
@@ -125,25 +127,53 @@
TaskStack stack = mTaskStackHorizontalView.getStack();
Task task = stack.getLaunchTarget();
if (task != null) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- ssp.startActivityFromRecents(getContext(), task.key, task.title, null);
+ launchTaskFomRecents(task);
return true;
}
}
return false;
}
- /** Launches a given task. */
- public boolean launchTask(Task task, Rect taskBounds, int destinationStack) {
- if (mTaskStackHorizontalView != null) {
- // Iterate the stack views and try and find the given task.
- if (mTaskStackHorizontalView.getChildViewForTask(task) != null) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- ssp.startActivityFromRecents(getContext(), task.key, task.title, null);
- return true;
+ /**
+ * Launch the given task from recents with animation. If the task is not focused, this will
+ * attempt to scroll to focus the task before launching.
+ * @param task
+ */
+ private void launchTaskFomRecents(final Task task) {
+ if(task != mTaskStackHorizontalView.getFocusedTask()) {
+ if(mScrollListener != null) {
+ mTaskStackHorizontalView.removeOnScrollListener(mScrollListener);
}
+ mScrollListener = new OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+ super.onScrollStateChanged(recyclerView, newState);
+ if(newState == RecyclerView.SCROLL_STATE_IDLE) {
+ TaskCardView cardView = mTaskStackHorizontalView.getChildViewForTask(task);
+ if(cardView != null) {
+ mTransitionHelper.launchTaskFromRecents(mStack, task,
+ mTaskStackHorizontalView, cardView, null, INVALID_STACK_ID);
+ } else {
+ // This should not happen normally. If this happens then the data in
+ // the grid view was altered during the scroll. Log error and launch
+ // task with no animation.
+ Log.e(TAG, "Card view for task : " + task + ", returned null.");
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ ssp.startActivityFromRecents(getContext(), task.key, task.title, null);
+ }
+ mTaskStackHorizontalView.removeOnScrollListener(mScrollListener);
+ }
+ }
+ };
+ mTaskStackHorizontalView.addOnScrollListener(mScrollListener);
+ mTaskStackHorizontalView.setSelectedPositionSmooth(
+ ((TaskStackHorizontalViewAdapter) mTaskStackHorizontalView.getAdapter())
+ .getPositionOfTask(task));
+ } else {
+ mTransitionHelper.launchTaskFromRecents(mStack, task, mTaskStackHorizontalView,
+ mTaskStackHorizontalView.getChildViewForTask(task), null,
+ INVALID_STACK_ID);
}
- return false;
}
/**
@@ -218,9 +248,15 @@
}
}
- public void setTaskStackViewAdapter(TaskStackHorizontalViewAdapter taskStackViewAdapter) {
+ public TaskStackHorizontalGridView setTaskStackViewAdapter(
+ TaskStackHorizontalViewAdapter taskStackViewAdapter) {
if(mTaskStackHorizontalView != null) {
mTaskStackHorizontalView.setAdapter(taskStackViewAdapter);
}
+ return mTaskStackHorizontalView;
+ }
+
+ public TaskStackHorizontalGridView getGridView() {
+ return mTaskStackHorizontalView;
}
}
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 d605748..99d478b 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
@@ -64,6 +64,7 @@
@Override
protected void onFinishInflate() {
+ super.onFinishInflate();
mThumbnailView = (ImageView) findViewById(R.id.card_view_thumbnail);
mTitleTextView = (TextView) findViewById(R.id.card_title_text);
mBadgeView = (ImageView) findViewById(R.id.card_extra_badge);
@@ -91,13 +92,6 @@
public Rect getFocusedThumbnailRect() {
Rect r = new Rect();
mThumbnailView.getGlobalVisibleRect(r);
- TypedValue out = new TypedValue();
- getContext().getResources().getValue(R.integer.selected_scale, out, true);
- float deltaScale = (out.getFloat() - 1.0f) / 2;
- r.set((int) (r.left - r.left * deltaScale),
- (int) (r.top - r.top * deltaScale),
- (int) (r.right + r.right * deltaScale),
- (int) (r.bottom + r.bottom * deltaScale));
return r;
}
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 3788719..97712ea 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
@@ -131,4 +131,9 @@
mTaskList.remove(position);
notifyItemRemoved(position);
}
+
+ public int getPositionOfTask(Task task) {
+ int position = mTaskList.indexOf(task);
+ return (position >= 0) ? position : 0;
+ }
}
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 9eec2ce..fd8df99 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -116,6 +116,7 @@
// window transition
EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
+ stackView.cancelAllTaskViewAnimations();
if (screenPinningRequested) {
// Request screen pinning after the animation runs
@@ -133,6 +134,7 @@
// window transition
EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
+ stackView.cancelAllTaskViewAnimations();
}
};
}
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 33d5bb7..a867bde 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -19,15 +19,20 @@
import android.app.ActivityManager;
import android.content.res.Configuration;
import android.graphics.Point;
+import android.graphics.Rect;
+import android.provider.Settings;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.widget.Toast;
+import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.RecentsImpl;
import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
@@ -81,12 +86,20 @@
private float mDragSlop;
private DropTarget mLastDropTarget;
+ private DividerSnapAlgorithm mDividerSnapAlgorithm;
private ArrayList<DropTarget> mDropTargets = new ArrayList<>();
private ArrayList<TaskStack.DockState> mVisibleDockStates = new ArrayList<>();
public RecentsViewTouchHandler(RecentsView rv) {
mRv = rv;
mDragSlop = ViewConfiguration.get(rv.getContext()).getScaledTouchSlop();
+ updateSnapAlgorithm();
+ }
+
+ private void updateSnapAlgorithm() {
+ Rect insets = new Rect();
+ SystemServicesProxy.getInstance(mRv.getContext()).getStableInsets(insets);
+ mDividerSnapAlgorithm = DividerSnapAlgorithm.create(mRv.getContext(), insets);
}
/**
@@ -150,7 +163,8 @@
mTaskView.setTranslationY(y);
mVisibleDockStates.clear();
- if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask()) {
+ if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask()
+ && mDividerSnapAlgorithm.isSplitScreenFeasible()) {
if (!event.task.isDockable) {
Toast.makeText(mRv.getContext(), R.string.recents_drag_non_dockable_task_message,
Toast.LENGTH_SHORT).show();
@@ -176,6 +190,10 @@
mLastDropTarget = null;
}
+ public final void onBusEvent(ConfigurationChangedEvent event) {
+ updateSnapAlgorithm();
+ }
+
/**
* Handles dragging touch events
*/
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 f8ed700..6e585ae 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -146,6 +146,8 @@
AnimateableViewBounds mViewBounds;
private AnimatorSet mTransformAnimation;
+ private ObjectAnimator mDimAnimator;
+ private ObjectAnimator mOutlineAnimator;
private final TaskViewTransform mTargetAnimationTransform = new TaskViewTransform();
private ArrayList<Animator> mTmpAnimators = new ArrayList<>();
@@ -308,14 +310,14 @@
} else {
// Both the progress and the update are a function of the bounds movement of the task
if (Float.compare(getDimAlpha(), toTransform.dimAlpha) != 0) {
- ObjectAnimator anim = ObjectAnimator.ofFloat(this, DIM_ALPHA, getDimAlpha(),
+ mDimAnimator = ObjectAnimator.ofFloat(this, DIM_ALPHA, getDimAlpha(),
toTransform.dimAlpha);
- mTmpAnimators.add(toAnimation.apply(AnimationProps.BOUNDS, anim));
+ mTmpAnimators.add(toAnimation.apply(AnimationProps.BOUNDS, mDimAnimator));
}
if (Float.compare(mViewBounds.getAlpha(), toTransform.viewOutlineAlpha) != 0) {
- ObjectAnimator anim = ObjectAnimator.ofFloat(this, VIEW_OUTLINE_ALPHA,
+ mOutlineAnimator = ObjectAnimator.ofFloat(this, VIEW_OUTLINE_ALPHA,
mViewBounds.getAlpha(), toTransform.viewOutlineAlpha);
- mTmpAnimators.add(toAnimation.apply(AnimationProps.BOUNDS, anim));
+ mTmpAnimators.add(toAnimation.apply(AnimationProps.BOUNDS, mOutlineAnimator));
}
if (updateCallback != null) {
ValueAnimator updateCallbackAnim = ValueAnimator.ofInt(0, 1);
@@ -358,6 +360,8 @@
*/
public void cancelTransformAnimation() {
Utilities.cancelAnimationWithoutCallbacks(mTransformAnimation);
+ Utilities.cancelAnimationWithoutCallbacks(mDimAnimator);
+ Utilities.cancelAnimationWithoutCallbacks(mOutlineAnimator);
}
/** Enables/disables handling touch on this task view. */
@@ -537,13 +541,15 @@
@Override
public void onStartLaunchTargetEnterAnimation(TaskViewTransform transform, int duration,
boolean screenPinningEnabled, ReferenceCountedTrigger postAnimationTrigger) {
+ Utilities.cancelAnimationWithoutCallbacks(mDimAnimator);
+
// Dim the view after the app window transitions down into recents
postAnimationTrigger.increment();
AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT);
- Animator anim = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
+ mDimAnimator = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
DIM_ALPHA_WITHOUT_HEADER, getDimAlpha(), transform.dimAlpha));
- anim.addListener(postAnimationTrigger.decrementOnAnimationEnd());
- anim.start();
+ mDimAnimator.addListener(postAnimationTrigger.decrementOnAnimationEnd());
+ mDimAnimator.start();
if (screenPinningEnabled) {
showActionButton(true /* fadeIn */, duration /* fadeInDuration */);
@@ -553,11 +559,13 @@
@Override
public void onStartLaunchTargetLaunchAnimation(int duration, boolean screenPinningRequested,
ReferenceCountedTrigger postAnimationTrigger) {
+ Utilities.cancelAnimationWithoutCallbacks(mDimAnimator);
+
// Un-dim the view before/while launching the target
AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT);
- Animator anim = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
+ mDimAnimator = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
DIM_ALPHA, getDimAlpha(), 0));
- anim.start();
+ mDimAnimator.start();
postAnimationTrigger.increment();
hideActionButton(true /* fadeOut */, duration,
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
index f728dab..d4922c3 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
@@ -23,6 +23,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
+import android.widget.TextView;
import com.android.systemui.R;
@@ -45,6 +46,8 @@
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.forced_resizable_activity);
+ TextView tv = (TextView) findViewById(com.android.internal.R.id.message);
+ tv.setText(R.string.dock_forced_resizable);
getWindow().getDecorView().setOnTouchListener(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
index 9b56037..9294ecd 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
@@ -20,12 +20,14 @@
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
-import android.util.ArrayMap;
import android.util.ArraySet;
+import android.widget.Toast;
+import com.android.systemui.R;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
-import com.android.systemui.recents.events.activity.ForcedResizableEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
import com.android.systemui.stackdivider.events.StartedDragingEvent;
import com.android.systemui.stackdivider.events.StoppedDragingEvent;
@@ -53,6 +55,18 @@
public ForcedResizableInfoActivityController(Context context) {
mContext = context;
EventBus.getDefault().register(this);
+ SystemServicesProxy.getInstance(context).registerTaskStackListener(
+ new TaskStackListener() {
+ @Override
+ public void onActivityForcedResizable(String packageName, int taskId) {
+ activityForcedResizable(packageName, taskId);
+ }
+
+ @Override
+ public void onActivityDismissingDockedStack() {
+ activityDismissingDockedStack();
+ }
+ });
}
public void notifyDockedStackExistsChanged(boolean exists) {
@@ -61,14 +75,6 @@
}
}
- public final void onBusEvent(ForcedResizableEvent forcedResizableEvent) {
- if (debounce(forcedResizableEvent.packageName)) {
- return;
- }
- mPendingTaskIds.add(forcedResizableEvent.taskId);
- postTimeout();
- }
-
public final void onBusEvent(AppTransitionFinishedEvent event) {
if (!mDividerDraging) {
showPending();
@@ -85,6 +91,20 @@
showPending();
}
+ private void activityForcedResizable(String packageName, int taskId) {
+ if (debounce(packageName)) {
+ return;
+ }
+ mPendingTaskIds.add(taskId);
+ postTimeout();
+ }
+
+ private void activityDismissingDockedStack() {
+ Toast toast = Toast.makeText(mContext, R.string.dock_non_resizeble_failed_to_dock_text,
+ Toast.LENGTH_SHORT);
+ toast.show();
+ }
+
private void showPending() {
mHandler.removeCallbacks(mTimeoutRunnable);
for (int i = mPendingTaskIds.size() - 1; i >= 0; i--) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index c459da9..1b2393a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -91,6 +91,7 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.systemui.DejankUtils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -100,6 +101,7 @@
import com.android.systemui.assist.AssistManager;
import com.android.systemui.recents.Recents;
import com.android.systemui.statusbar.NotificationData.Entry;
+import com.android.systemui.statusbar.NotificationGuts.OnGutsClosedListener;
import com.android.systemui.statusbar.phone.NavigationBarView;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -114,12 +116,12 @@
import java.util.Locale;
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,
+ OnGutsClosedListener {
public static final String TAG = "StatusBar";
public static final boolean DEBUG = false;
public static final boolean MULTIUSER_DEBUG = false;
@@ -285,9 +287,10 @@
private final ContentObserver mLockscreenSettingsObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
- // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
- // so we just dump our cache ...
+ // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS or
+ // LOCK_SCREEN_SHOW_NOTIFICATIONS, so we just dump our cache ...
mUsersAllowingPrivateNotifications.clear();
+ mUsersAllowingNotifications.clear();
// ... and refresh all the notifications
updateNotifications();
}
@@ -1010,6 +1013,7 @@
PackageManager pmUser = getPackageManagerForUser(mContext, sbn.getUser().getIdentifier());
row.setTag(sbn.getPackageName());
final NotificationGuts guts = row.getGuts();
+ guts.setClosedListener(this);
final String pkg = sbn.getPackageName();
String appname = pkg;
Drawable pkgicon = null;
@@ -1037,6 +1041,7 @@
settingsButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_INFO);
+ guts.resetFalsingCheck();
startAppNotificationSettingsActivity(pkg, appUidF);
}
});
@@ -1069,6 +1074,7 @@
private void saveImportanceCloseControls(StatusBarNotification sbn,
ExpandableNotificationRow row, NotificationGuts guts, View done) {
+ guts.resetFalsingCheck();
guts.saveImportance(sbn);
int[] rowLocation = new int[2];
@@ -1137,7 +1143,8 @@
}
});
a.start();
- guts.setExposed(true);
+ guts.setExposed(true /* exposed */,
+ mState == StatusBarState.KEYGUARD /* needsFalsingProtection */);
row.closeRemoteInput();
mStackScroller.onHeightChanged(null, true /* needsAnimation */);
mNotificationGutsExposed = guts;
@@ -1165,31 +1172,7 @@
public void dismissPopups(int x, int y, boolean resetGear, boolean animate) {
if (mNotificationGutsExposed != null) {
- final NotificationGuts v = mNotificationGutsExposed;
- mNotificationGutsExposed = null;
-
- if (v.getWindowToken() == null) return;
- if (x == -1 || y == -1) {
- x = (v.getLeft() + v.getRight()) / 2;
- y = (v.getTop() + v.getHeight() / 2);
- }
- final double horz = Math.max(v.getWidth() - x, x);
- final double vert = Math.max(v.getHeight() - y, y);
- final float r = (float) Math.hypot(horz, vert);
- final Animator a = ViewAnimationUtils.createCircularReveal(v,
- x, y, r, 0);
- a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
- a.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- v.setVisibility(View.GONE);
- }
- });
- a.start();
- v.setExposed(false);
- mStackScroller.onHeightChanged(null, true /* needsAnimation */);
+ mNotificationGutsExposed.closeControls(x, y, true /* notify */);
}
if (resetGear) {
mStackScroller.resetExposedGearView(animate, true /* force */);
@@ -1197,6 +1180,12 @@
}
@Override
+ public void onGutsClosed(NotificationGuts guts) {
+ mStackScroller.onHeightChanged(null, true /* needsAnimation */);
+ mNotificationGutsExposed = null;
+ }
+
+ @Override
public void showRecentApps(boolean triggeredFromAltTab) {
int msg = MSG_SHOW_RECENT_APPS;
mHandler.removeMessages(msg);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java b/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
index 3067714..2045ec8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar;
import android.content.Context;
+import android.content.res.Configuration;
import android.util.AttributeSet;
import android.view.View;
@@ -51,6 +52,12 @@
|| touchY > mContent.getY() + mContent.getHeight();
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ mDismissButton.setText(R.string.clear_all_notifications_text);
+ }
+
public boolean isButtonVisible() {
return mDismissButton.getAlpha() != 0.0f;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 7ca7d12..e25f9de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -618,6 +618,19 @@
return mOnKeyguard;
}
+ public void removeAllChildren() {
+ List<ExpandableNotificationRow> notificationChildren
+ = mChildrenContainer.getNotificationChildren();
+ ArrayList<ExpandableNotificationRow> clonedList = new ArrayList<>(notificationChildren);
+ for (int i = 0; i < clonedList.size(); i++) {
+ ExpandableNotificationRow row = clonedList.get(i);
+ mChildrenContainer.removeNotification(row);
+ mHeaderUtil.restoreNotificationHeader(row);
+ row.setIsChildInGroup(false, null);
+ }
+ onChildrenCountChanged();
+ }
+
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 2b365dc..86c1fca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -17,13 +17,24 @@
package com.android.systemui.statusbar;
import android.app.AlertDialog;
+import android.app.AppGlobals;
import android.app.Dialog;
+import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Icon;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.Looper;
+import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;
import android.view.ContextThemeWrapper;
@@ -37,265 +48,250 @@
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager.KeyboardShortcutsReceiver;
+import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
import android.widget.TextView;
+import com.android.internal.app.AssistUtils;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import static android.content.Context.LAYOUT_INFLATER_SERVICE;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
+import com.google.android.collect.Lists;
+
/**
* Contains functionality for handling keyboard shortcuts.
*/
-public class KeyboardShortcuts {
+public final class KeyboardShortcuts {
private static final String TAG = KeyboardShortcuts.class.getSimpleName();
-
- private static final SparseArray<String> SPECIAL_CHARACTER_NAMES = new SparseArray<>();
- private static final SparseArray<String> MODIFIER_NAMES = new SparseArray<>();
-
- private static void loadSpecialCharacterNames(Context context) {
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_HOME, context.getString(R.string.keyboard_key_home));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_BACK, context.getString(R.string.keyboard_key_back));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_DPAD_UP, context.getString(R.string.keyboard_key_dpad_up));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_DPAD_DOWN, context.getString(R.string.keyboard_key_dpad_down));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_DPAD_LEFT, context.getString(R.string.keyboard_key_dpad_left));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_DPAD_RIGHT, context.getString(R.string.keyboard_key_dpad_right));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_DPAD_CENTER, context.getString(R.string.keyboard_key_dpad_center));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_PERIOD, ".");
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_TAB, context.getString(R.string.keyboard_key_tab));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_SPACE, context.getString(R.string.keyboard_key_space));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_ENTER, context.getString(R.string.keyboard_key_enter));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_DEL, context.getString(R.string.keyboard_key_backspace));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE,
- context.getString(R.string.keyboard_key_media_play_pause));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_MEDIA_STOP, context.getString(R.string.keyboard_key_media_stop));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_MEDIA_NEXT, context.getString(R.string.keyboard_key_media_next));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_PREVIOUS,
- context.getString(R.string.keyboard_key_media_previous));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_REWIND,
- context.getString(R.string.keyboard_key_media_rewind));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD,
- context.getString(R.string.keyboard_key_media_fast_forward));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_PAGE_UP, context.getString(R.string.keyboard_key_page_up));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_PAGE_DOWN, context.getString(R.string.keyboard_key_page_down));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_A,
- context.getString(R.string.keyboard_key_button_template, "A"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_B,
- context.getString(R.string.keyboard_key_button_template, "B"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_C,
- context.getString(R.string.keyboard_key_button_template, "C"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_X,
- context.getString(R.string.keyboard_key_button_template, "X"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_Y,
- context.getString(R.string.keyboard_key_button_template, "Y"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_Z,
- context.getString(R.string.keyboard_key_button_template, "Z"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_L1,
- context.getString(R.string.keyboard_key_button_template, "L1"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_R1,
- context.getString(R.string.keyboard_key_button_template, "R1"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_L2,
- context.getString(R.string.keyboard_key_button_template, "L2"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_R2,
- context.getString(R.string.keyboard_key_button_template, "R2"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_START,
- context.getString(R.string.keyboard_key_button_template, "Start"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_SELECT,
- context.getString(R.string.keyboard_key_button_template, "Select"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BUTTON_MODE,
- context.getString(R.string.keyboard_key_button_template, "Mode"));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_FORWARD_DEL, context.getString(R.string.keyboard_key_forward_del));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_ESCAPE, "Esc");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_SYSRQ, "SysRq");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_BREAK, "Break");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_SCROLL_LOCK, "Scroll Lock");
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_MOVE_HOME, context.getString(R.string.keyboard_key_move_home));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_MOVE_END, context.getString(R.string.keyboard_key_move_end));
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_INSERT, context.getString(R.string.keyboard_key_insert));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F1, "F1");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F2, "F2");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F3, "F3");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F4, "F4");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F5, "F5");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F6, "F6");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F7, "F7");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F8, "F8");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F9, "F9");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F10, "F10");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F11, "F11");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_F12, "F12");
- SPECIAL_CHARACTER_NAMES.put(
- KeyEvent.KEYCODE_NUM_LOCK, context.getString(R.string.keyboard_key_num_lock));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_0,
- context.getString(R.string.keyboard_key_numpad_template, "0"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_1,
- context.getString(R.string.keyboard_key_numpad_template, "1"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_2,
- context.getString(R.string.keyboard_key_numpad_template, "2"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_3,
- context.getString(R.string.keyboard_key_numpad_template, "3"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_4,
- context.getString(R.string.keyboard_key_numpad_template, "4"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_5,
- context.getString(R.string.keyboard_key_numpad_template, "5"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_6,
- context.getString(R.string.keyboard_key_numpad_template, "6"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_7,
- context.getString(R.string.keyboard_key_numpad_template, "7"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_8,
- context.getString(R.string.keyboard_key_numpad_template, "8"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_9,
- context.getString(R.string.keyboard_key_numpad_template, "9"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_DIVIDE,
- context.getString(R.string.keyboard_key_numpad_template, "/"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_MULTIPLY,
- context.getString(R.string.keyboard_key_numpad_template, "*"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_SUBTRACT,
- context.getString(R.string.keyboard_key_numpad_template, "-"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_ADD,
- context.getString(R.string.keyboard_key_numpad_template, "+"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_DOT,
- context.getString(R.string.keyboard_key_numpad_template, "."));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_COMMA,
- context.getString(R.string.keyboard_key_numpad_template, ","));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_ENTER,
- context.getString(R.string.keyboard_key_numpad_template,
- context.getString(R.string.keyboard_key_enter)));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_EQUALS,
- context.getString(R.string.keyboard_key_numpad_template, "="));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN,
- context.getString(R.string.keyboard_key_numpad_template, "("));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN,
- context.getString(R.string.keyboard_key_numpad_template, ")"));
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_ZENKAKU_HANKAKU, "半角/全角");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_EISU, "英数");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_MUHENKAN, "無変換");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_HENKAN, "変換");
- SPECIAL_CHARACTER_NAMES.put(KeyEvent.KEYCODE_KATAKANA_HIRAGANA, "かな");
-
- MODIFIER_NAMES.put(KeyEvent.META_META_ON, "Meta");
- MODIFIER_NAMES.put(KeyEvent.META_CTRL_ON, "Ctrl");
- MODIFIER_NAMES.put(KeyEvent.META_ALT_ON, "Alt");
- MODIFIER_NAMES.put(KeyEvent.META_SHIFT_ON, "Shift");
- MODIFIER_NAMES.put(KeyEvent.META_SYM_ON, "Sym");
- MODIFIER_NAMES.put(KeyEvent.META_FUNCTION_ON, "Fn");
- }
+ private final SparseArray<String> mSpecialCharacterNames = new SparseArray<>();
+ private final SparseArray<String> mModifierNames = new SparseArray<>();
+ private final SparseArray<Drawable> mSpecialCharacterDrawables = new SparseArray<>();
+ private final SparseArray<Drawable> mModifierDrawables = new SparseArray<>();
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final Context mContext;
- private final OnClickListener dialogCloseListener = new DialogInterface.OnClickListener() {
+ private final IPackageManager mPackageManager;
+ private final OnClickListener mDialogCloseListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dismissKeyboardShortcutsDialog();
}
};
+ private final Comparator<KeyboardShortcutInfo> mApplicationItemsComparator =
+ new Comparator<KeyboardShortcutInfo>() {
+ @Override
+ public int compare(KeyboardShortcutInfo ksh1, KeyboardShortcutInfo ksh2) {
+ boolean ksh1ShouldBeLast = ksh1.getLabel() == null
+ || ksh1.getLabel().toString().isEmpty();
+ boolean ksh2ShouldBeLast = ksh2.getLabel() == null
+ || ksh2.getLabel().toString().isEmpty();
+ if (ksh1ShouldBeLast && ksh2ShouldBeLast) {
+ return 0;
+ }
+ if (ksh1ShouldBeLast) {
+ return 1;
+ }
+ if (ksh2ShouldBeLast) {
+ return -1;
+ }
+ return (ksh1.getLabel().toString()).compareToIgnoreCase(
+ ksh2.getLabel().toString());
+ }
+ };
private Dialog mKeyboardShortcutsDialog;
private KeyCharacterMap mKeyCharacterMap;
public KeyboardShortcuts(Context context) {
this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_Material_Light);
- if (SPECIAL_CHARACTER_NAMES.size() == 0) {
- loadSpecialCharacterNames(context);
- }
+ this.mPackageManager = AppGlobals.getPackageManager();
+ loadResources(context);
+ }
+
+ private void loadResources(Context context) {
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_HOME, context.getString(R.string.keyboard_key_home));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_BACK, context.getString(R.string.keyboard_key_back));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_DPAD_UP, context.getString(R.string.keyboard_key_dpad_up));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_DPAD_DOWN, context.getString(R.string.keyboard_key_dpad_down));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_DPAD_LEFT, context.getString(R.string.keyboard_key_dpad_left));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_DPAD_RIGHT, context.getString(R.string.keyboard_key_dpad_right));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_DPAD_CENTER, context.getString(R.string.keyboard_key_dpad_center));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_PERIOD, ".");
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_TAB, context.getString(R.string.keyboard_key_tab));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_SPACE, context.getString(R.string.keyboard_key_space));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_ENTER, context.getString(R.string.keyboard_key_enter));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_DEL, context.getString(R.string.keyboard_key_backspace));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE,
+ context.getString(R.string.keyboard_key_media_play_pause));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_MEDIA_STOP, context.getString(R.string.keyboard_key_media_stop));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_MEDIA_NEXT, context.getString(R.string.keyboard_key_media_next));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_PREVIOUS,
+ context.getString(R.string.keyboard_key_media_previous));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_REWIND,
+ context.getString(R.string.keyboard_key_media_rewind));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD,
+ context.getString(R.string.keyboard_key_media_fast_forward));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_PAGE_UP, context.getString(R.string.keyboard_key_page_up));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_PAGE_DOWN, context.getString(R.string.keyboard_key_page_down));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_A,
+ context.getString(R.string.keyboard_key_button_template, "A"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_B,
+ context.getString(R.string.keyboard_key_button_template, "B"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_C,
+ context.getString(R.string.keyboard_key_button_template, "C"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_X,
+ context.getString(R.string.keyboard_key_button_template, "X"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_Y,
+ context.getString(R.string.keyboard_key_button_template, "Y"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_Z,
+ context.getString(R.string.keyboard_key_button_template, "Z"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_L1,
+ context.getString(R.string.keyboard_key_button_template, "L1"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_R1,
+ context.getString(R.string.keyboard_key_button_template, "R1"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_L2,
+ context.getString(R.string.keyboard_key_button_template, "L2"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_R2,
+ context.getString(R.string.keyboard_key_button_template, "R2"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_START,
+ context.getString(R.string.keyboard_key_button_template, "Start"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_SELECT,
+ context.getString(R.string.keyboard_key_button_template, "Select"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BUTTON_MODE,
+ context.getString(R.string.keyboard_key_button_template, "Mode"));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_FORWARD_DEL, context.getString(R.string.keyboard_key_forward_del));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_ESCAPE, "Esc");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_SYSRQ, "SysRq");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_BREAK, "Break");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_SCROLL_LOCK, "Scroll Lock");
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_MOVE_HOME, context.getString(R.string.keyboard_key_move_home));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_MOVE_END, context.getString(R.string.keyboard_key_move_end));
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_INSERT, context.getString(R.string.keyboard_key_insert));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F1, "F1");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F2, "F2");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F3, "F3");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F4, "F4");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F5, "F5");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F6, "F6");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F7, "F7");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F8, "F8");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F9, "F9");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F10, "F10");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F11, "F11");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_F12, "F12");
+ mSpecialCharacterNames.put(
+ KeyEvent.KEYCODE_NUM_LOCK, context.getString(R.string.keyboard_key_num_lock));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_0,
+ context.getString(R.string.keyboard_key_numpad_template, "0"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_1,
+ context.getString(R.string.keyboard_key_numpad_template, "1"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_2,
+ context.getString(R.string.keyboard_key_numpad_template, "2"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_3,
+ context.getString(R.string.keyboard_key_numpad_template, "3"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_4,
+ context.getString(R.string.keyboard_key_numpad_template, "4"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_5,
+ context.getString(R.string.keyboard_key_numpad_template, "5"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_6,
+ context.getString(R.string.keyboard_key_numpad_template, "6"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_7,
+ context.getString(R.string.keyboard_key_numpad_template, "7"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_8,
+ context.getString(R.string.keyboard_key_numpad_template, "8"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_9,
+ context.getString(R.string.keyboard_key_numpad_template, "9"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_DIVIDE,
+ context.getString(R.string.keyboard_key_numpad_template, "/"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_MULTIPLY,
+ context.getString(R.string.keyboard_key_numpad_template, "*"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_SUBTRACT,
+ context.getString(R.string.keyboard_key_numpad_template, "-"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_ADD,
+ context.getString(R.string.keyboard_key_numpad_template, "+"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_DOT,
+ context.getString(R.string.keyboard_key_numpad_template, "."));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_COMMA,
+ context.getString(R.string.keyboard_key_numpad_template, ","));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_ENTER,
+ context.getString(R.string.keyboard_key_numpad_template,
+ context.getString(R.string.keyboard_key_enter)));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_EQUALS,
+ context.getString(R.string.keyboard_key_numpad_template, "="));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_LEFT_PAREN,
+ context.getString(R.string.keyboard_key_numpad_template, "("));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_NUMPAD_RIGHT_PAREN,
+ context.getString(R.string.keyboard_key_numpad_template, ")"));
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_ZENKAKU_HANKAKU, "半角/全角");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_EISU, "英数");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_MUHENKAN, "無変換");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_HENKAN, "変換");
+ mSpecialCharacterNames.put(KeyEvent.KEYCODE_KATAKANA_HIRAGANA, "かな");
+
+ mModifierNames.put(KeyEvent.META_META_ON, "Meta");
+ mModifierNames.put(KeyEvent.META_CTRL_ON, "Ctrl");
+ mModifierNames.put(KeyEvent.META_ALT_ON, "Alt");
+ mModifierNames.put(KeyEvent.META_SHIFT_ON, "Shift");
+ mModifierNames.put(KeyEvent.META_SYM_ON, "Sym");
+ mModifierNames.put(KeyEvent.META_FUNCTION_ON, "Fn");
+
+ mSpecialCharacterDrawables.put(
+ KeyEvent.KEYCODE_DEL, context.getDrawable(R.drawable.ic_ksh_key_backspace));
+ mSpecialCharacterDrawables.put(
+ KeyEvent.KEYCODE_ENTER, context.getDrawable(R.drawable.ic_ksh_key_enter));
+ mSpecialCharacterDrawables.put(
+ KeyEvent.KEYCODE_DPAD_UP, context.getDrawable(R.drawable.ic_ksh_key_up));
+ mSpecialCharacterDrawables.put(
+ KeyEvent.KEYCODE_DPAD_RIGHT, context.getDrawable(R.drawable.ic_ksh_key_right));
+ mSpecialCharacterDrawables.put(
+ KeyEvent.KEYCODE_DPAD_DOWN, context.getDrawable(R.drawable.ic_ksh_key_down));
+ mSpecialCharacterDrawables.put(
+ KeyEvent.KEYCODE_DPAD_LEFT, context.getDrawable(R.drawable.ic_ksh_key_left));
+
+ mModifierDrawables.put(
+ KeyEvent.META_META_ON, context.getDrawable(R.drawable.ic_ksh_key_meta));
}
public void toggleKeyboardShortcuts(int deviceId) {
- InputDevice inputDevice = InputManager.getInstance().getInputDevice(deviceId);
- if (inputDevice != null) {
- mKeyCharacterMap = inputDevice.getKeyCharacterMap();
- }
+ retrieveKeyCharacterMap(deviceId);
if (mKeyboardShortcutsDialog == null) {
Recents.getSystemServices().requestKeyboardShortcuts(mContext,
new KeyboardShortcutsReceiver() {
@Override
public void onKeyboardShortcutsReceived(
final List<KeyboardShortcutGroup> result) {
- KeyboardShortcutGroup systemGroup = new KeyboardShortcutGroup(
- mContext.getString(R.string.keyboard_shortcut_group_system), true);
- systemGroup.addItem(new KeyboardShortcutInfo(
- mContext.getString(R.string.keyboard_shortcut_group_system_home),
- KeyEvent.KEYCODE_ENTER, KeyEvent.META_META_ON));
- systemGroup.addItem(new KeyboardShortcutInfo(
- mContext.getString(R.string.keyboard_shortcut_group_system_back),
- KeyEvent.KEYCODE_DEL, KeyEvent.META_META_ON));
- systemGroup.addItem(new KeyboardShortcutInfo(
- mContext.getString(R.string.keyboard_shortcut_group_system_recents),
- KeyEvent.KEYCODE_TAB, KeyEvent.META_ALT_ON));
- systemGroup.addItem(new KeyboardShortcutInfo(
- mContext.getString(
- R.string.keyboard_shortcut_group_system_notifications),
- KeyEvent.KEYCODE_N, KeyEvent.META_META_ON));
- systemGroup.addItem(new KeyboardShortcutInfo(
- mContext.getString(
- R.string.keyboard_shortcut_group_system_shortcuts_helper),
- KeyEvent.KEYCODE_SLASH, KeyEvent.META_META_ON));
- systemGroup.addItem(new KeyboardShortcutInfo(
- mContext.getString(
- R.string.keyboard_shortcut_group_system_switch_input),
- KeyEvent.KEYCODE_SPACE, KeyEvent.META_META_ON));
- result.add(systemGroup);
-
- KeyboardShortcutGroup applicationGroup = new KeyboardShortcutGroup(
- mContext.getString(R.string.keyboard_shortcut_group_applications),
- true);
- applicationGroup.addItem(new KeyboardShortcutInfo(
- mContext.getString(
- R.string.keyboard_shortcut_group_applications_assist),
- KeyEvent.KEYCODE_UNKNOWN, KeyEvent.META_META_ON));
- applicationGroup.addItem(new KeyboardShortcutInfo(
- mContext.getString(
- R.string.keyboard_shortcut_group_applications_browser),
- KeyEvent.KEYCODE_B, KeyEvent.META_META_ON));
- applicationGroup.addItem(new KeyboardShortcutInfo(
- mContext.getString(
- R.string.keyboard_shortcut_group_applications_contacts),
- KeyEvent.KEYCODE_C, KeyEvent.META_META_ON));
- applicationGroup.addItem(new KeyboardShortcutInfo(
- mContext.getString(
- R.string.keyboard_shortcut_group_applications_email),
- KeyEvent.KEYCODE_E, KeyEvent.META_META_ON));
- applicationGroup.addItem(new KeyboardShortcutInfo(
- mContext.getString(
- R.string.keyboard_shortcut_group_applications_im),
- KeyEvent.KEYCODE_T, KeyEvent.META_META_ON));
- applicationGroup.addItem(new KeyboardShortcutInfo(
- mContext.getString(
- R.string.keyboard_shortcut_group_applications_music),
- KeyEvent.KEYCODE_P, KeyEvent.META_META_ON));
- applicationGroup.addItem(new KeyboardShortcutInfo(
- mContext.getString(
- R.string.keyboard_shortcut_group_applications_youtube),
- KeyEvent.KEYCODE_Y, KeyEvent.META_META_ON));
- applicationGroup.addItem(new KeyboardShortcutInfo(
- mContext.getString(
- R.string.keyboard_shortcut_group_applications_calendar),
- KeyEvent.KEYCODE_L, KeyEvent.META_META_ON));
- result.add(applicationGroup);
-
+ result.add(getSystemShortcuts());
+ final KeyboardShortcutGroup appShortcuts = getDefaultApplicationShortcuts();
+ if (appShortcuts != null) {
+ result.add(appShortcuts);
+ }
showKeyboardShortcutsDialog(result);
}
}, deviceId);
@@ -304,6 +300,35 @@
}
}
+ /**
+ * Retrieves a {@link KeyCharacterMap} and assigns it to mKeyCharacterMap. If the given id is an
+ * existing device, that device's map is used. Otherwise, it checks first all available devices
+ * and if there is a full keyboard it uses that map, otherwise falls back to the Virtual
+ * Keyboard with its default map.
+ */
+ private void retrieveKeyCharacterMap(int deviceId) {
+ final InputManager inputManager = InputManager.getInstance();
+ if (deviceId != -1) {
+ final InputDevice inputDevice = inputManager.getInputDevice(deviceId);
+ if (inputDevice != null) {
+ mKeyCharacterMap = inputDevice.getKeyCharacterMap();
+ return;
+ }
+ }
+ final int[] deviceIds = inputManager.getInputDeviceIds();
+ for (int i = 0; i < deviceIds.length; ++i) {
+ final InputDevice inputDevice = inputManager.getInputDevice(deviceIds[i]);
+ // -1 is the Virtual Keyboard, with the default key map. Use that one only as last
+ // resort.
+ if (inputDevice.getId() != -1 && inputDevice.isFullKeyboard()) {
+ mKeyCharacterMap = inputDevice.getKeyCharacterMap();
+ return;
+ }
+ }
+ final InputDevice inputDevice = inputManager.getInputDevice(-1);
+ mKeyCharacterMap = inputDevice.getKeyCharacterMap();
+ }
+
public void dismissKeyboardShortcutsDialog() {
if (mKeyboardShortcutsDialog != null) {
mKeyboardShortcutsDialog.dismiss();
@@ -311,6 +336,168 @@
}
}
+ private KeyboardShortcutGroup getSystemShortcuts() {
+ final KeyboardShortcutGroup systemGroup = new KeyboardShortcutGroup(
+ mContext.getString(R.string.keyboard_shortcut_group_system), true);
+ systemGroup.addItem(new KeyboardShortcutInfo(
+ mContext.getString(R.string.keyboard_shortcut_group_system_home),
+ KeyEvent.KEYCODE_ENTER,
+ KeyEvent.META_META_ON));
+ systemGroup.addItem(new KeyboardShortcutInfo(
+ mContext.getString(R.string.keyboard_shortcut_group_system_back),
+ KeyEvent.KEYCODE_DEL,
+ KeyEvent.META_META_ON));
+ systemGroup.addItem(new KeyboardShortcutInfo(
+ mContext.getString(R.string.keyboard_shortcut_group_system_recents),
+ KeyEvent.KEYCODE_TAB,
+ KeyEvent.META_ALT_ON));
+ systemGroup.addItem(new KeyboardShortcutInfo(
+ mContext.getString(
+ R.string.keyboard_shortcut_group_system_notifications),
+ KeyEvent.KEYCODE_N,
+ KeyEvent.META_META_ON));
+ systemGroup.addItem(new KeyboardShortcutInfo(
+ mContext.getString(
+ R.string.keyboard_shortcut_group_system_shortcuts_helper),
+ KeyEvent.KEYCODE_SLASH,
+ KeyEvent.META_META_ON));
+ systemGroup.addItem(new KeyboardShortcutInfo(
+ mContext.getString(
+ R.string.keyboard_shortcut_group_system_switch_input),
+ KeyEvent.KEYCODE_SPACE,
+ KeyEvent.META_META_ON));
+ return systemGroup;
+ }
+
+ private KeyboardShortcutGroup getDefaultApplicationShortcuts() {
+ final int userId = mContext.getUserId();
+ List<KeyboardShortcutInfo> keyboardShortcutInfoAppItems = Lists.newArrayList();
+
+ // Assist.
+ final AssistUtils assistUtils = new AssistUtils(mContext);
+ final ComponentName assistComponent = assistUtils.getAssistComponentForUser(userId);
+ PackageInfo assistPackageInfo = null;
+ try {
+ assistPackageInfo = mPackageManager.getPackageInfo(
+ assistComponent.getPackageName(), 0, userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "PackageManagerService is dead");
+ }
+
+ if (assistPackageInfo != null) {
+ final Icon assistIcon = Icon.createWithResource(
+ assistPackageInfo.applicationInfo.packageName,
+ assistPackageInfo.applicationInfo.icon);
+
+ keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo(
+ mContext.getString(R.string.keyboard_shortcut_group_applications_assist),
+ assistIcon,
+ KeyEvent.KEYCODE_UNKNOWN,
+ KeyEvent.META_META_ON));
+ }
+
+ // Browser.
+ final Icon browserIcon = getIconForIntentCategory(Intent.CATEGORY_APP_BROWSER, userId);
+ if (browserIcon != null) {
+ keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo(
+ mContext.getString(R.string.keyboard_shortcut_group_applications_browser),
+ browserIcon,
+ KeyEvent.KEYCODE_B,
+ KeyEvent.META_META_ON));
+ }
+
+
+ // Contacts.
+ final Icon contactsIcon = getIconForIntentCategory(Intent.CATEGORY_APP_CONTACTS, userId);
+ if (contactsIcon != null) {
+ keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo(
+ mContext.getString(R.string.keyboard_shortcut_group_applications_contacts),
+ contactsIcon,
+ KeyEvent.KEYCODE_C,
+ KeyEvent.META_META_ON));
+ }
+
+ // Email.
+ final Icon emailIcon = getIconForIntentCategory(Intent.CATEGORY_APP_EMAIL, userId);
+ if (emailIcon != null) {
+ keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo(
+ mContext.getString(R.string.keyboard_shortcut_group_applications_email),
+ emailIcon,
+ KeyEvent.KEYCODE_E,
+ KeyEvent.META_META_ON));
+ }
+
+ // Messaging.
+ final Icon messagingIcon = getIconForIntentCategory(Intent.CATEGORY_APP_MESSAGING, userId);
+ if (messagingIcon != null) {
+ keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo(
+ mContext.getString(R.string.keyboard_shortcut_group_applications_im),
+ messagingIcon,
+ KeyEvent.KEYCODE_T,
+ KeyEvent.META_META_ON));
+ }
+
+ // Music.
+ final Icon musicIcon = getIconForIntentCategory(Intent.CATEGORY_APP_MUSIC, userId);
+ if (musicIcon != null) {
+ keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo(
+ mContext.getString(R.string.keyboard_shortcut_group_applications_music),
+ musicIcon,
+ KeyEvent.KEYCODE_P,
+ KeyEvent.META_META_ON));
+ }
+
+ // Calendar.
+ final Icon calendarIcon = getIconForIntentCategory(Intent.CATEGORY_APP_CALENDAR, userId);
+ if (calendarIcon != null) {
+ keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo(
+ mContext.getString(R.string.keyboard_shortcut_group_applications_calendar),
+ calendarIcon,
+ KeyEvent.KEYCODE_L,
+ KeyEvent.META_META_ON));
+ }
+
+ final int itemsSize = keyboardShortcutInfoAppItems.size();
+ if (itemsSize == 0) {
+ return null;
+ }
+
+ // Sorts by label, case insensitive with nulls and/or empty labels last.
+ Collections.sort(keyboardShortcutInfoAppItems, mApplicationItemsComparator);
+ return new KeyboardShortcutGroup(
+ mContext.getString(R.string.keyboard_shortcut_group_applications),
+ keyboardShortcutInfoAppItems,
+ true);
+ }
+
+ private Icon getIconForIntentCategory(String intentCategory, int userId) {
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(intentCategory);
+
+ final PackageInfo packageInfo = getPackageInfoForIntent(intent, userId);
+ if (packageInfo != null && packageInfo.applicationInfo.icon != 0) {
+ return Icon.createWithResource(
+ packageInfo.applicationInfo.packageName,
+ packageInfo.applicationInfo.icon);
+ }
+ return null;
+ }
+
+ private PackageInfo getPackageInfoForIntent(Intent intent, int userId) {
+ try {
+ ResolveInfo handler;
+ handler = mPackageManager.resolveIntent(
+ intent, intent.resolveTypeIfNeeded(mContext.getContentResolver()), 0, userId);
+ if (handler == null || handler.activityInfo == null) {
+ return null;
+ }
+ return mPackageManager.getPackageInfo(handler.activityInfo.packageName, 0, userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "PackageManagerService is dead", e);
+ return null;
+ }
+ }
+
private void showKeyboardShortcutsDialog(
final List<KeyboardShortcutGroup> keyboardShortcutGroups) {
// Need to post on the main thread.
@@ -331,7 +518,7 @@
populateKeyboardShortcuts((LinearLayout) keyboardShortcutsView.findViewById(
R.id.keyboard_shortcuts_container), keyboardShortcutGroups);
dialogBuilder.setView(keyboardShortcutsView);
- dialogBuilder.setPositiveButton(R.string.quick_settings_done, dialogCloseListener);
+ dialogBuilder.setPositiveButton(R.string.quick_settings_done, mDialogCloseListener);
mKeyboardShortcutsDialog = dialogBuilder.create();
mKeyboardShortcutsDialog.setCanceledOnTouchOutside(true);
Window keyboardShortcutsWindow = mKeyboardShortcutsDialog.getWindow();
@@ -343,6 +530,15 @@
List<KeyboardShortcutGroup> keyboardShortcutGroups) {
LayoutInflater inflater = LayoutInflater.from(mContext);
final int keyboardShortcutGroupsSize = keyboardShortcutGroups.size();
+ TextView shortcutsKeyView = (TextView) inflater.inflate(
+ R.layout.keyboard_shortcuts_key_view, null, false);
+ shortcutsKeyView.measure(
+ View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+ final int shortcutKeyTextItemMinWidth = shortcutsKeyView.getMeasuredHeight();
+ // Needed to be able to scale the image items to the same height as the text items.
+ final int shortcutKeyIconItemHeightWidth = shortcutsKeyView.getMeasuredHeight()
+ - shortcutsKeyView.getPaddingTop()
+ - shortcutsKeyView.getPaddingBottom();
for (int i = 0; i < keyboardShortcutGroupsSize; i++) {
KeyboardShortcutGroup group = keyboardShortcutGroups.get(i);
TextView categoryTitle = (TextView) inflater.inflate(
@@ -358,13 +554,7 @@
final int itemsSize = group.getItems().size();
for (int j = 0; j < itemsSize; j++) {
KeyboardShortcutInfo info = group.getItems().get(j);
- if (info.getKeycode() != KeyEvent.KEYCODE_UNKNOWN
- && !KeyCharacterMap.deviceHasKey(info.getKeycode())) {
- // The user can't achieve this shortcut, so skipping.
- Log.w(TAG, "Keyboard Shortcut contains key not on device, skipping.");
- continue;
- }
- List<String> shortcutKeys = getHumanReadableShortcutKeys(info);
+ List<StringOrDrawable> shortcutKeys = getHumanReadableShortcutKeys(info);
if (shortcutKeys == null) {
// Ignore shortcuts we can't display keys for.
Log.w(TAG, "Keyboard Shortcut contains unsupported keys, skipping.");
@@ -372,19 +562,49 @@
}
View shortcutView = inflater.inflate(R.layout.keyboard_shortcut_app_item,
shortcutContainer, false);
- TextView textView = (TextView) shortcutView
+
+ if (info.getIcon() != null) {
+ ImageView shortcutIcon = (ImageView) shortcutView
+ .findViewById(R.id.keyboard_shortcuts_icon);
+ shortcutIcon.setImageIcon(info.getIcon());
+ shortcutIcon.setVisibility(View.VISIBLE);
+ }
+
+ TextView shortcutKeyword = (TextView) shortcutView
.findViewById(R.id.keyboard_shortcuts_keyword);
- textView.setText(info.getLabel());
+ shortcutKeyword.setText(info.getLabel());
+ if (info.getIcon() != null) {
+ RelativeLayout.LayoutParams lp =
+ (RelativeLayout.LayoutParams) shortcutKeyword.getLayoutParams();
+ lp.removeRule(RelativeLayout.ALIGN_PARENT_START);
+ shortcutKeyword.setLayoutParams(lp);
+ }
ViewGroup shortcutItemsContainer = (ViewGroup) shortcutView
.findViewById(R.id.keyboard_shortcuts_item_container);
final int shortcutKeysSize = shortcutKeys.size();
for (int k = 0; k < shortcutKeysSize; k++) {
- String shortcutKey = shortcutKeys.get(k);
- TextView shortcutKeyView = (TextView) inflater.inflate(
- R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer, false);
- shortcutKeyView.setText(shortcutKey);
- shortcutItemsContainer.addView(shortcutKeyView);
+ StringOrDrawable shortcutRepresentation = shortcutKeys.get(k);
+ if (shortcutRepresentation.drawable != null) {
+ ImageView shortcutKeyIconView = (ImageView) inflater.inflate(
+ R.layout.keyboard_shortcuts_key_icon_view, shortcutItemsContainer,
+ false);
+ Bitmap bitmap = Bitmap.createBitmap(shortcutKeyIconItemHeightWidth,
+ shortcutKeyIconItemHeightWidth, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ shortcutRepresentation.drawable.setBounds(0, 0, canvas.getWidth(),
+ canvas.getHeight());
+ shortcutRepresentation.drawable.draw(canvas);
+ shortcutKeyIconView.setImageBitmap(bitmap);
+ shortcutItemsContainer.addView(shortcutKeyIconView);
+ } else if (shortcutRepresentation.string != null) {
+ TextView shortcutKeyTextView = (TextView) inflater.inflate(
+ R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer,
+ false);
+ shortcutKeyTextView.setMinimumWidth(shortcutKeyTextItemMinWidth);
+ shortcutKeyTextView.setText(shortcutRepresentation.string);
+ shortcutItemsContainer.addView(shortcutKeyTextView);
+ }
}
shortcutContainer.addView(shortcutView);
}
@@ -398,44 +618,56 @@
}
}
- private List<String> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
- List<String> shortcutKeys = getHumanReadableModifiers(info);
+ private List<StringOrDrawable> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
+ List<StringOrDrawable> shortcutKeys = getHumanReadableModifiers(info);
if (shortcutKeys == null) {
return null;
}
- String displayLabelString;
+ String displayLabelString = null;
+ Drawable displayLabelDrawable = null;
if (info.getBaseCharacter() > Character.MIN_VALUE) {
displayLabelString = String.valueOf(info.getBaseCharacter());
- } else if (SPECIAL_CHARACTER_NAMES.get(info.getKeycode()) != null) {
- displayLabelString = SPECIAL_CHARACTER_NAMES.get(info.getKeycode());
+ } else if (mSpecialCharacterDrawables.get(info.getKeycode()) != null) {
+ displayLabelDrawable = mSpecialCharacterDrawables.get(info.getKeycode());
+ } else if (mSpecialCharacterNames.get(info.getKeycode()) != null) {
+ displayLabelString = mSpecialCharacterNames.get(info.getKeycode());
} else {
// Special case for shortcuts with no base key or keycode.
if (info.getKeycode() == KeyEvent.KEYCODE_UNKNOWN) {
return shortcutKeys;
}
- // TODO: Have a generic map for when we don't have the device's.
- char displayLabel = mKeyCharacterMap == null
- ? 0 : mKeyCharacterMap.getDisplayLabel(info.getKeycode());
+ char displayLabel = mKeyCharacterMap.getDisplayLabel(info.getKeycode());
if (displayLabel != 0) {
displayLabelString = String.valueOf(displayLabel);
} else {
return null;
}
}
- shortcutKeys.add(displayLabelString.toUpperCase());
+
+ if (displayLabelDrawable != null) {
+ shortcutKeys.add(new StringOrDrawable(displayLabelDrawable));
+ } else if (displayLabelString != null) {
+ shortcutKeys.add(new StringOrDrawable(displayLabelString.toUpperCase()));
+ }
return shortcutKeys;
}
- private List<String> getHumanReadableModifiers(KeyboardShortcutInfo info) {
- final List<String> shortcutKeys = new ArrayList<>();
+ private List<StringOrDrawable> getHumanReadableModifiers(KeyboardShortcutInfo info) {
+ final List<StringOrDrawable> shortcutKeys = new ArrayList<>();
int modifiers = info.getModifiers();
if (modifiers == 0) {
return shortcutKeys;
}
- for(int i = 0; i < MODIFIER_NAMES.size(); ++i) {
- final int supportedModifier = MODIFIER_NAMES.keyAt(i);
+ for(int i = 0; i < mModifierNames.size(); ++i) {
+ final int supportedModifier = mModifierNames.keyAt(i);
if ((modifiers & supportedModifier) != 0) {
- shortcutKeys.add(MODIFIER_NAMES.get(supportedModifier).toUpperCase());
+ if (mModifierDrawables.get(supportedModifier) != null) {
+ shortcutKeys.add(new StringOrDrawable(
+ mModifierDrawables.get(supportedModifier)));
+ } else {
+ shortcutKeys.add(new StringOrDrawable(
+ mModifierNames.get(supportedModifier).toUpperCase()));
+ }
modifiers &= ~supportedModifier;
}
}
@@ -445,4 +677,17 @@
}
return shortcutKeys;
}
+
+ private static final class StringOrDrawable {
+ public String string;
+ public Drawable drawable;
+
+ public StringOrDrawable(String string) {
+ this.string = string;
+ }
+
+ public StringOrDrawable(Drawable drawable) {
+ this.drawable = drawable;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java
new file mode 100644
index 0000000..5d22faf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java
@@ -0,0 +1,33 @@
+/*
+ * 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.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Receiver for the Keyboard Shortcuts Helper.
+ */
+public class KeyboardShortcutsReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS.equals(intent.getAction())) {
+ final KeyboardShortcuts keyboardShortcuts = new KeyboardShortcuts(context);
+ keyboardShortcuts.toggleKeyboardShortcuts(-1 /* deviceId unknown */);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index c9fe2bd..6570221 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.Map;
import java.util.Objects;
/**
@@ -257,16 +258,21 @@
}
public void add(Entry entry, RankingMap ranking) {
- mEntries.put(entry.notification.getKey(), entry);
- updateRankingAndSort(ranking);
+ synchronized (mEntries) {
+ mEntries.put(entry.notification.getKey(), entry);
+ }
mGroupManager.onEntryAdded(entry);
+ updateRankingAndSort(ranking);
}
public Entry remove(String key, RankingMap ranking) {
- Entry removed = mEntries.remove(key);
+ Entry removed = null;
+ synchronized (mEntries) {
+ removed = mEntries.remove(key);
+ }
if (removed == null) return null;
- updateRankingAndSort(ranking);
mGroupManager.onEntryRemoved(removed);
+ updateRankingAndSort(ranking);
return removed;
}
@@ -316,9 +322,30 @@
return Ranking.IMPORTANCE_UNSPECIFIED;
}
+ public String getOverrideGroupKey(String key) {
+ if (mRankingMap != null) {
+ mRankingMap.getRanking(key, mTmpRanking);
+ return mTmpRanking.getOverrideGroupKey();
+ }
+ return null;
+ }
+
private void updateRankingAndSort(RankingMap ranking) {
if (ranking != null) {
mRankingMap = ranking;
+ synchronized (mEntries) {
+ final int N = mEntries.size();
+ for (int i = 0; i < N; i++) {
+ Entry entry = mEntries.valueAt(i);
+ final StatusBarNotification oldSbn = entry.notification.clone();
+ final String overrideGroupKey = getOverrideGroupKey(entry.key);
+ if (!Objects.equals(oldSbn.getOverrideGroupKey(), overrideGroupKey)) {
+ entry.notification.setOverrideGroupKey(overrideGroupKey);
+ mGroupManager.onEntryUpdated(entry, oldSbn);
+ }
+ //mGroupManager.onEntryBundlingUpdated(entry, getOverrideGroupKey(entry.key));
+ }
+ }
}
filterAndSort();
}
@@ -328,16 +355,18 @@
public void filterAndSort() {
mSortedAndFiltered.clear();
- final int N = mEntries.size();
- for (int i = 0; i < N; i++) {
- Entry entry = mEntries.valueAt(i);
- StatusBarNotification sbn = entry.notification;
+ synchronized (mEntries) {
+ final int N = mEntries.size();
+ for (int i = 0; i < N; i++) {
+ Entry entry = mEntries.valueAt(i);
+ StatusBarNotification sbn = entry.notification;
- if (shouldFilterOut(sbn)) {
- continue;
+ if (shouldFilterOut(sbn)) {
+ continue;
+ }
+
+ mSortedAndFiltered.add(entry);
}
-
- mSortedAndFiltered.add(entry);
}
Collections.sort(mSortedAndFiltered, mRankingComparator);
@@ -398,16 +427,17 @@
NotificationData.Entry e = mSortedAndFiltered.get(active);
dumpEntry(pw, indent, active, e);
}
-
- int M = mEntries.size();
- pw.print(indent);
- pw.println("inactive notifications: " + (M - active));
- int inactiveCount = 0;
- for (int i = 0; i < M; i++) {
- Entry entry = mEntries.valueAt(i);
- if (!mSortedAndFiltered.contains(entry)) {
- dumpEntry(pw, indent, inactiveCount, entry);
- inactiveCount++;
+ synchronized (mEntries) {
+ int M = mEntries.size();
+ pw.print(indent);
+ pw.println("inactive notifications: " + (M - active));
+ int inactiveCount = 0;
+ for (int i = 0; i < M; i++) {
+ Entry entry = mEntries.valueAt(i);
+ if (!mSortedAndFiltered.contains(entry)) {
+ dumpEntry(pw, indent, inactiveCount, entry);
+ inactiveCount++;
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 3e0542f..3c464d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -16,28 +16,35 @@
package com.android.systemui.statusbar;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.app.INotificationManager;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
+import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
import android.view.View;
+import android.view.ViewAnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
+import android.widget.RadioGroup;
import android.widget.SeekBar;
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settingslib.Utils;
+import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
import com.android.systemui.tuner.TunerService;
/**
@@ -46,6 +53,8 @@
public class NotificationGuts extends LinearLayout implements TunerService.Tunable {
public static final String SHOW_SLIDER = "show_importance_slider";
+ private static final long CLOSE_GUTS_DELAY = 8000;
+
private Drawable mBackground;
private int mClipTopAmount;
private int mActualHeight;
@@ -59,10 +68,35 @@
private RadioButton mSilent;
private RadioButton mReset;
+ private Handler mHandler;
+ private Runnable mFalsingCheck;
+ private boolean mNeedsFalsingProtection;
+ private OnGutsClosedListener mListener;
+
+ public interface OnGutsClosedListener {
+ public void onGutsClosed(NotificationGuts guts);
+ }
+
public NotificationGuts(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(false);
TunerService.get(mContext).addTunable(this, SHOW_SLIDER);
+ mHandler = new Handler();
+ mFalsingCheck = new Runnable() {
+ @Override
+ public void run() {
+ if (mNeedsFalsingProtection && mExposed) {
+ closeControls(-1 /* x */, -1 /* y */, true /* notify */);
+ }
+ }
+ };
+ }
+
+ public void resetFalsingCheck() {
+ mHandler.removeCallbacks(mFalsingCheck);
+ if (mNeedsFalsingProtection && mExposed) {
+ mHandler.postDelayed(mFalsingCheck, CLOSE_GUTS_DELAY);
+ }
}
@Override
@@ -172,6 +206,13 @@
private void bindToggles(final View importanceButtons, final int importance,
final boolean systemApp) {
+ ((RadioGroup) importanceButtons).setOnCheckedChangeListener(
+ new RadioGroup.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(RadioGroup group, int checkedId) {
+ resetFalsingCheck();
+ }
+ });
mBlock = (RadioButton) importanceButtons.findViewById(R.id.block_importance);
mSilent = (RadioButton) importanceButtons.findViewById(R.id.silent_importance);
mReset = (RadioButton) importanceButtons.findViewById(R.id.reset_importance);
@@ -205,6 +246,7 @@
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ resetFalsingCheck();
if (progress < minProgress) {
seekBar.setProgress(minProgress);
progress = minProgress;
@@ -217,7 +259,7 @@
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
- // no-op
+ resetFalsingCheck();
}
@Override
@@ -263,6 +305,38 @@
mSeekBar.setProgress(mStartingImportance);
}
+ public void closeControls(int x, int y, boolean notify) {
+ if (getWindowToken() == null) {
+ if (notify && mListener != null) {
+ mListener.onGutsClosed(this);
+ }
+ return;
+ }
+ if (x == -1 || y == -1) {
+ x = (getLeft() + getRight()) / 2;
+ y = (getTop() + getHeight() / 2);
+ }
+ final double horz = Math.max(getWidth() - x, x);
+ final double vert = Math.max(getHeight() - y, y);
+ final float r = (float) Math.hypot(horz, vert);
+ final Animator a = ViewAnimationUtils.createCircularReveal(this,
+ x, y, r, 0);
+ a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+ a.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ setVisibility(View.GONE);
+ }
+ });
+ a.start();
+ setExposed(false, mNeedsFalsingProtection);
+ if (notify && mListener != null) {
+ mListener.onGutsClosed(this);
+ }
+ }
+
public void setActualHeight(int actualHeight) {
mActualHeight = actualHeight;
invalidate();
@@ -284,8 +358,18 @@
return false;
}
- public void setExposed(boolean exposed) {
+ public void setClosedListener(OnGutsClosedListener listener) {
+ mListener = listener;
+ }
+
+ public void setExposed(boolean exposed, boolean needsFalsingProtection) {
mExposed = exposed;
+ mNeedsFalsingProtection = needsFalsingProtection;
+ if (mExposed && mNeedsFalsingProtection) {
+ resetFalsingCheck();
+ } else {
+ mHandler.removeCallbacks(mFalsingCheck);
+ }
}
public boolean areGutsExposed() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java
new file mode 100644
index 0000000..03b51c6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java
@@ -0,0 +1,271 @@
+/*
+ * 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.car;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadsetClient;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothProfile.ServiceListener;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.systemui.statusbar.policy.BatteryController;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * A {@link BatteryController} that is specific to the Auto use-case. For Auto, the battery icon
+ * displays the battery status of a device that is connected via bluetooth and not the system's
+ * battery.
+ */
+public class CarBatteryController extends BroadcastReceiver implements BatteryController {
+ private static final String TAG = "CarBatteryController";
+
+ // According to the Bluetooth HFP 1.5 specification, battery levels are indicated by a
+ // value from 1-5, where these values represent the following:
+ // 0%% - 0, 1-25%% - 1, 26-50%% - 2, 51-75%% - 3, 76-99%% - 4, 100%% - 5
+ // As a result, set the level as the average within that range.
+ private static final int BATTERY_LEVEL_EMPTY = 0;
+ private static final int BATTERY_LEVEL_1 = 12;
+ private static final int BATTERY_LEVEL_2 = 28;
+ private static final int BATTERY_LEVEL_3 = 63;
+ private static final int BATTERY_LEVEL_4 = 87;
+ private static final int BATTERY_LEVEL_FULL = 100;
+
+ private static final int INVALID_BATTERY_LEVEL = -1;
+
+ private final Context mContext;
+
+ private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
+ private BluetoothHeadsetClient mBluetoothHeadsetClient;
+
+ private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
+
+ private int mLevel;
+
+ /**
+ * An interface indicating the container of a View that will display what the information
+ * in the {@link CarBatteryController}.
+ */
+ public interface BatteryViewHandler {
+ void hideBatteryView();
+ void showBatteryView();
+ }
+
+ private BatteryViewHandler mBatteryViewHandler;
+
+ public CarBatteryController(Context context) {
+ mContext = context;
+
+ mAdapter.getProfileProxy(context.getApplicationContext(), mHfpServiceListener,
+ BluetoothProfile.HEADSET_CLIENT);
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("CarBatteryController state:");
+ pw.print(" mLevel=");
+ pw.println(mLevel);
+ }
+
+ @Override
+ public void setPowerSaveMode(boolean powerSave) {
+ // No-op. No power save mode for the car.
+ }
+
+ @Override
+ public void addStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
+ mChangeCallbacks.add(cb);
+
+ // There is no way to know if the phone is plugged in or charging via bluetooth, so pass
+ // false for these values.
+ cb.onBatteryLevelChanged(mLevel, false /* pluggedIn */, false /* charging */);
+ cb.onPowerSaveChanged(false /* isPowerSave */);
+ }
+
+ @Override
+ public void removeStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
+ mChangeCallbacks.remove(cb);
+ }
+
+ public void addBatteryViewHandler(BatteryViewHandler batteryViewHandler) {
+ mBatteryViewHandler = batteryViewHandler;
+ }
+
+ public void startListening() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
+ filter.addAction(BluetoothHeadsetClient.ACTION_AG_EVENT);
+ mContext.registerReceiver(this, filter);
+ }
+
+ public void stopListening() {
+ mContext.unregisterReceiver(this);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "onReceive(). action: " + action);
+ }
+
+ if (BluetoothHeadsetClient.ACTION_AG_EVENT.equals(action)) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Received ACTION_AG_EVENT");
+ }
+
+ int batteryLevel = intent.getIntExtra(BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL,
+ INVALID_BATTERY_LEVEL);
+
+ updateBatteryLevel(batteryLevel);
+
+ if (batteryLevel != INVALID_BATTERY_LEVEL && mBatteryViewHandler != null) {
+ mBatteryViewHandler.showBatteryView();
+ }
+ } else if (BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
+ int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1);
+ Log.d(TAG, "ACTION_CONNECTION_STATE_CHANGED event: "
+ + oldState + " -> " + newState);
+
+ }
+ BluetoothDevice device =
+ (BluetoothDevice)intent.getExtra(BluetoothDevice.EXTRA_DEVICE);
+ updateBatteryIcon(device, newState);
+ }
+ }
+
+ /**
+ * Converts the battery level to a percentage that can be displayed on-screen and notifies
+ * any {@link BatteryStateChangeCallback}s of this.
+ */
+ private void updateBatteryLevel(int batteryLevel) {
+ if (batteryLevel == INVALID_BATTERY_LEVEL) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Battery level invalid. Ignoring.");
+ }
+ return;
+ }
+
+ // The battery level is a value between 0-5. Let the default battery level be 0.
+ switch (batteryLevel) {
+ case 5:
+ mLevel = BATTERY_LEVEL_FULL;
+ break;
+ case 4:
+ mLevel = BATTERY_LEVEL_4;
+ break;
+ case 3:
+ mLevel = BATTERY_LEVEL_3;
+ break;
+ case 2:
+ mLevel = BATTERY_LEVEL_2;
+ break;
+ case 1:
+ mLevel = BATTERY_LEVEL_1;
+ break;
+ case 0:
+ default:
+ mLevel = BATTERY_LEVEL_EMPTY;
+ }
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Battery level: " + batteryLevel + "; setting mLevel as: " + mLevel);
+ }
+
+ notifyBatteryLevelChanged();
+ }
+
+ /**
+ * Updates the display of the battery icon depending on the given connection state from the
+ * given {@link BluetoothDevice}.
+ */
+ private void updateBatteryIcon(BluetoothDevice device, int newState) {
+ if (newState == BluetoothProfile.STATE_CONNECTED) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Device connected");
+ }
+
+ if (mBatteryViewHandler != null) {
+ mBatteryViewHandler.showBatteryView();
+ }
+
+ if (mBluetoothHeadsetClient == null || device == null) {
+ return;
+ }
+
+ // Check if battery information is available and immediately update.
+ Bundle featuresBundle = mBluetoothHeadsetClient.getCurrentAgEvents(device);
+ if (featuresBundle == null) {
+ return;
+ }
+
+ int batteryLevel = featuresBundle.getInt(BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL,
+ INVALID_BATTERY_LEVEL);
+ updateBatteryLevel(batteryLevel);
+ } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Device disconnected");
+ }
+
+ if (mBatteryViewHandler != null) {
+ mBatteryViewHandler.hideBatteryView();
+ }
+ }
+ }
+
+ @Override
+ public boolean isPowerSave() {
+ // Power save is not valid for the car, so always return false.
+ return false;
+ }
+
+ private void notifyBatteryLevelChanged() {
+ for (int i = 0, size = mChangeCallbacks.size(); i < size; i++) {
+ mChangeCallbacks.get(i)
+ .onBatteryLevelChanged(mLevel, false /* pluggedIn */, false /* charging */);
+ }
+ }
+
+ private final ServiceListener mHfpServiceListener = new ServiceListener() {
+ @Override
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (profile == BluetoothProfile.HEADSET_CLIENT) {
+ mBluetoothHeadsetClient = (BluetoothHeadsetClient) proxy;
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(int profile) {
+ if (profile == BluetoothProfile.HEADSET_CLIENT) {
+ mBluetoothHeadsetClient = null;
+ }
+ }
+ };
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 4add3cb..811687c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -22,37 +22,75 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.PixelFormat;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.RemoteException;
+import android.util.Log;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewStub;
import android.view.WindowManager;
-
+import com.android.systemui.BatteryMeterView;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.PhoneStatusBarView;
+import com.android.systemui.statusbar.policy.BatteryController;
/**
* A status bar (and navigation bar) tailored for the automotive use case.
*/
-public class CarStatusBar extends PhoneStatusBar {
+public class CarStatusBar extends PhoneStatusBar implements
+ CarBatteryController.BatteryViewHandler {
+ private static final String TAG = "CarStatusBar";
+
private TaskStackListenerImpl mTaskStackListener;
private CarNavigationBarView mCarNavigationBar;
private CarNavigationBarController mController;
private FullscreenUserSwitcher mFullscreenUserSwitcher;
+ private CarBatteryController mCarBatteryController;
+ private BatteryMeterView mBatteryMeterView;
+
@Override
public void start() {
super.start();
mTaskStackListener = new TaskStackListenerImpl();
SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener);
registerPackageChangeReceivers();
+
+ mCarBatteryController.startListening();
+ }
+
+ @Override
+ public void destroy() {
+ mCarBatteryController.stopListening();
+ super.destroy();
+ }
+
+ @Override
+ protected PhoneStatusBarView makeStatusBarView() {
+ PhoneStatusBarView statusBarView = super.makeStatusBarView();
+
+ mBatteryMeterView = ((BatteryMeterView) statusBarView.findViewById(R.id.battery));
+
+ // By default, the BatteryMeterView should not be visible. It will be toggled visible
+ // when a device has connected by bluetooth.
+ mBatteryMeterView.setVisibility(View.GONE);
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "makeStatusBarView(). mBatteryMeterView: " + mBatteryMeterView);
+ }
+
+ return statusBarView;
+ }
+
+ @Override
+ protected BatteryController createBatteryController() {
+ mCarBatteryController = new CarBatteryController(mContext);
+ mCarBatteryController.addBatteryViewHandler(this);
+ return mCarBatteryController;
}
@Override
@@ -85,6 +123,28 @@
}
+ @Override
+ public void showBatteryView() {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "showBatteryView(). mBatteryMeterView: " + mBatteryMeterView);
+ }
+
+ if (mBatteryMeterView != null) {
+ mBatteryMeterView.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public void hideBatteryView() {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "hideBatteryView(). mBatteryMeterView: " + mBatteryMeterView);
+ }
+
+ if (mBatteryMeterView != null) {
+ mBatteryMeterView.setVisibility(View.GONE);
+ }
+ }
+
private BroadcastReceiver mPackageChangeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 260c969..ec45d60 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -182,7 +182,7 @@
private void inflateButtons(String[] buttons, ViewGroup parent, boolean landscape) {
for (int i = 0; i < buttons.length; i++) {
- inflateButton(buttons[i], parent, landscape);
+ inflateButton(buttons[i], parent, landscape, i);
}
}
@@ -195,7 +195,8 @@
}
@Nullable
- protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape) {
+ protected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape,
+ int indexInParent) {
LayoutInflater inflater = landscape ? mLandscapeInflater : mLayoutInflater;
float size = extractSize(buttonSpec);
String button = extractButton(buttonSpec);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index f7a6b271..fffb20a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -26,6 +26,8 @@
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Objects;
/**
* A class to handle notifications and their corresponding groups.
@@ -36,6 +38,7 @@
private OnGroupChangeListener mListener;
private int mBarState = -1;
private HashMap<String, StatusBarNotification> mIsolatedEntries = new HashMap<>();
+ private HeadsUpManager mHeadsUpManager;
public void setOnGroupChangeListener(OnGroupChangeListener listener) {
mListener = listener;
@@ -121,6 +124,15 @@
}
}
+ public void onEntryBundlingUpdated(final NotificationData.Entry updated,
+ final String overrideGroupKey) {
+ final StatusBarNotification oldSbn = updated.notification.clone();
+ if (!Objects.equals(oldSbn.getOverrideGroupKey(), overrideGroupKey)) {
+ updated.notification.setOverrideGroupKey(overrideGroupKey);
+ onEntryUpdated(updated, oldSbn);
+ }
+ }
+
private void updateSuppression(NotificationGroup group) {
if (group == null) {
return;
@@ -129,9 +141,12 @@
group.suppressed = group.summary != null && !group.expanded
&& (group.children.size() == 1
|| (group.children.size() == 0
- && !group.summary.notification.getNotification().isGroupChild()
+ && group.summary.notification.getNotification().isGroupSummary()
&& hasIsolatedChildren(group)));
if (prevSuppressed != group.suppressed) {
+ if (group.suppressed) {
+ handleSuppressedSummaryHeadsUpped(group.summary);
+ }
mListener.onGroupsChanged();
}
}
@@ -150,6 +165,15 @@
return count;
}
+ private NotificationData.Entry getIsolatedChild(String groupKey) {
+ for (StatusBarNotification sbn : mIsolatedEntries.values()) {
+ if (sbn.getGroupKey().equals(groupKey) && isIsolated(sbn)) {
+ return mGroupMap.get(sbn.getKey()).summary;
+ }
+ }
+ return null;
+ }
+
public void onEntryUpdated(NotificationData.Entry entry,
StatusBarNotification oldNotification) {
if (mGroupMap.get(getGroupKey(oldNotification)) != null) {
@@ -173,7 +197,7 @@
public boolean isOnlyChildInSuppressedGroup(StatusBarNotification sbn) {
return isGroupSuppressed(sbn.getGroupKey())
- && sbn.getNotification().isGroupChild()
+ && !sbn.getNotification().isGroupSummary()
&& getTotalNumberOfChildren(sbn) == 1;
}
@@ -278,11 +302,12 @@
}
return sbn.getNotification().isGroupSummary();
}
+
private boolean isGroupChild(StatusBarNotification sbn) {
if (isIsolated(sbn)) {
return false;
}
- return sbn.getNotification().isGroupChild();
+ return sbn.isGroup() && !sbn.getNotification().isGroupSummary();
}
private String getGroupKey(StatusBarNotification sbn) {
@@ -321,6 +346,9 @@
// it doesn't lead to an update.
updateSuppression(mGroupMap.get(entry.notification.getGroupKey()));
mListener.onGroupsChanged();
+ } else {
+ handleSuppressedSummaryHeadsUpped(entry);
+
}
} else {
if (mIsolatedEntries.containsKey(sbn.getKey())) {
@@ -333,9 +361,35 @@
}
}
+ private void handleSuppressedSummaryHeadsUpped(NotificationData.Entry entry) {
+ StatusBarNotification sbn = entry.notification;
+ if (!isGroupSuppressed(sbn.getGroupKey())
+ || !sbn.getNotification().isGroupSummary()
+ || !entry.row.isHeadsUp()) {
+ return;
+ }
+ // The parent of a suppressed group got huned, lets hun the child!
+ NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey());
+ if (notificationGroup != null) {
+ Iterator<NotificationData.Entry> iterator = notificationGroup.children.iterator();
+ NotificationData.Entry child = iterator.hasNext() ? iterator.next() : null;
+ if (child == null) {
+ child = getIsolatedChild(sbn.getGroupKey());
+ }
+ if (child != null) {
+ if (mHeadsUpManager.isHeadsUp(child.key)) {
+ mHeadsUpManager.updateNotification(child, true);
+ } else {
+ mHeadsUpManager.showNotification(child);
+ }
+ }
+ }
+ mHeadsUpManager.releaseImmediately(entry.key);
+ }
+
private boolean shouldIsolate(StatusBarNotification sbn) {
NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey());
- return sbn.getNotification().isGroupChild()
+ return (sbn.isGroup() && !sbn.getNotification().isGroupSummary())
&& (sbn.getNotification().fullScreenIntent != null
|| notificationGroup == null
|| !notificationGroup.expanded
@@ -349,6 +403,10 @@
|| notificationGroup.summary.row.getTranslationY() < 0;
}
+ public void setHeadsUpManager(HeadsUpManager headsUpManager) {
+ mHeadsUpManager = headsUpManager;
+ }
+
public static class NotificationGroup {
public final HashSet<NotificationData.Entry> children = new HashSet<>();
public NotificationData.Entry summary;
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 45e94f7..62c0fa9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -306,7 +306,7 @@
// Calculate quick setting heights.
int oldMaxHeight = mQsMaxExpansionHeight;
- mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQsContainer.getHeader().getHeight();
+ mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQsContainer.getQsMinExpansionHeight();
mQsMaxExpansionHeight = mQsContainer.getDesiredHeight();
positionClockAndNotifications();
if (mQsExpanded && mQsFullyExpanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index c9bb15d..c4b7932 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -845,15 +845,19 @@
};
public void cancelPeek() {
+ boolean cancelled = mPeekPending;
if (mPeekAnimator != null) {
+ cancelled = true;
mPeekAnimator.cancel();
}
removeCallbacks(mPeekRunnable);
mPeekPending = false;
- // When peeking, we already tell mBar that we expanded ourselves. Make sure that we also
- // notify mBar that we might have closed ourselves.
- notifyBarPanelExpansionChanged();
+ if (cancelled) {
+ // When peeking, we already tell mBar that we expanded ourselves. Make sure that we also
+ // notify mBar that we might have closed ourselves.
+ notifyBarPanelExpansionChanged();
+ }
}
public void expand(final boolean animate) {
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 bf58592..75430ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -21,9 +21,7 @@
import android.animation.AnimatorListenerAdapter;
import android.annotation.NonNull;
import android.app.ActivityManager;
-import android.app.ActivityManager.StackId;
import android.app.ActivityManagerNative;
-import android.app.ActivityOptions;
import android.app.IActivityManager;
import android.app.Notification;
import android.app.PendingIntent;
@@ -147,6 +145,7 @@
import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
+import com.android.systemui.statusbar.policy.BatteryControllerImpl;
import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.statusbar.policy.CastControllerImpl;
@@ -730,6 +729,7 @@
mHeadsUpManager.addListener(mGroupManager);
mNotificationPanel.setHeadsUpManager(mHeadsUpManager);
mNotificationData.setHeadsUpManager(mHeadsUpManager);
+ mGroupManager.setHeadsUpManager(mHeadsUpManager);
if (MULTIUSER_DEBUG) {
mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(
@@ -826,7 +826,7 @@
// Other icons
mLocationController = new LocationControllerImpl(mContext,
mHandlerThread.getLooper()); // will post a notification
- mBatteryController = new BatteryController(mContext);
+ mBatteryController = createBatteryController();
mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() {
@Override
public void onPowerSaveChanged(boolean isPowerSave) {
@@ -943,6 +943,10 @@
return mStatusBarView;
}
+ protected BatteryController createBatteryController() {
+ return new BatteryControllerImpl(mContext);
+ }
+
@Override
protected void reInflateViews() {
super.reInflateViews();
@@ -1167,7 +1171,9 @@
@Override
public boolean onLongClick(View v) {
- if (mRecents == null || !ActivityManager.supportsMultiWindow()) {
+ if (mRecents == null || !ActivityManager.supportsMultiWindow()
+ || !getComponent(Divider.class).getView().getSnapAlgorithm()
+ .isSplitScreenFeasible()) {
return false;
}
@@ -1525,6 +1531,9 @@
// we are only transfering this notification to its parent, don't generate an animation
mStackScroller.setChildTransferInProgress(true);
}
+ if (remove.isSummaryWithChildren()) {
+ remove.removeAllChildren();
+ }
mStackScroller.removeView(remove);
mStackScroller.setChildTransferInProgress(false);
}
@@ -3461,7 +3470,7 @@
@Override
public void run() {
mLeaveOpenOnKeyguardHide = true;
- executeRunnableDismissingKeyguard(runnable, null, false, true);
+ executeRunnableDismissingKeyguard(runnable, null, false, false);
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 902fd3d..cc3b4bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -41,7 +41,9 @@
private Runnable mHideExpandedRunnable = new Runnable() {
@Override
public void run() {
- mBar.makeExpandedInvisible();
+ if (mPanelFraction == 0.0f) {
+ mBar.makeExpandedInvisible();
+ }
}
};
@@ -135,6 +137,7 @@
super.onTrackingStarted();
mBar.onTrackingStarted();
mScrimController.onTrackingStarted();
+ removePendingHideExpandedRunnables();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index f3aba4f..ea9a5a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -45,7 +45,7 @@
import com.android.systemui.tuner.TunerService;
public class QuickStatusBarHeader extends BaseStatusBarHeader implements
- NextAlarmChangeCallback, OnClickListener {
+ NextAlarmChangeCallback, OnClickListener, OnUserInfoChangedListener {
private static final String TAG = "QuickStatusBarHeader";
@@ -54,7 +54,7 @@
private ActivityStarter mActivityStarter;
private NextAlarmController mNextAlarmController;
private SettingsButton mSettingsButton;
- private View mSettingsContainer;
+ protected View mSettingsContainer;
private TextView mAlarmStatus;
private TextView mAlarmStatusCollapsed;
@@ -75,19 +75,19 @@
private QuickQSPanel mHeaderQsPanel;
private boolean mShowEmergencyCallsOnly;
- private MultiUserSwitch mMultiUserSwitch;
+ protected MultiUserSwitch mMultiUserSwitch;
private ImageView mMultiUserAvatar;
private float mDateTimeTranslation;
private float mDateTimeAlarmTranslation;
private float mDateScaleFactor;
- private float mGearTranslation;
+ protected float mGearTranslation;
private TouchAnimator mSecondHalfAnimator;
private TouchAnimator mFirstHalfAnimator;
private TouchAnimator mDateSizeAnimator;
private TouchAnimator mAlarmTranslation;
- private TouchAnimator mSettingsAlpha;
+ protected TouchAnimator mSettingsAlpha;
private float mExpansionAmount;
private QSTileHost mHost;
@@ -172,6 +172,11 @@
.addFloat(mDateTimeGroup, "scaleY", 1, mDateScaleFactor)
.setStartDelay(.36f)
.build();
+
+ updateSettingsAnimator();
+ }
+
+ protected void updateSettingsAnimator() {
mSettingsAlpha = new TouchAnimator.Builder()
.addFloat(mSettingsContainer, "translationY", -mGearTranslation, 0)
.addFloat(mMultiUserSwitch, "translationY", -mGearTranslation, 0)
@@ -241,7 +246,7 @@
@Override
protected void onDetachedFromWindow() {
setListening(false);
- mHost.getUserInfoController().remListener(mUserListener);
+ mHost.getUserInfoController().remListener(this);
mHost.getNetworkController().removeEmergencyListener(this);
super.onDetachedFromWindow();
}
@@ -275,7 +280,7 @@
updateVisibilities();
}
- private void updateVisibilities() {
+ protected void updateVisibilities() {
updateAlarmVisibilities();
mEmergencyOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly
? View.VISIBLE : View.INVISIBLE);
@@ -309,7 +314,7 @@
public void setupHost(final QSTileHost host) {
mHost = host;
- host.setHeaderView(this);
+ host.setHeaderView(mExpandIndicator);
mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
mHeaderQsPanel.setHost(host, null /* No customization in header */);
setUserInfoController(host.getUserInfoController());
@@ -365,7 +370,7 @@
@Override
public void setUserInfoController(UserInfoController userInfoController) {
- userInfoController.addListener(mUserListener);
+ userInfoController.addListener(this);
}
@Override
@@ -379,10 +384,8 @@
}
}
- private final OnUserInfoChangedListener mUserListener = new OnUserInfoChangedListener() {
- @Override
- public void onUserInfoChanged(String name, Drawable picture) {
- mMultiUserAvatar.setImageDrawable(picture);
- }
- };
+ @Override
+ public void onUserInfoChanged(String name, Drawable picture) {
+ mMultiUserAvatar.setImageDrawable(picture);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
index 093a827..dc1b35d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
@@ -17,69 +17,57 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
+import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
+import com.android.settingslib.drawable.UserIconDrawable;
import com.android.systemui.R;
/**
- * A view that displays a user image cropped to a circle with a frame.
+ * A view that displays a user image cropped to a circle with an optional frame.
*/
public class UserAvatarView extends View {
- private int mActiveFrameColor;
- private int mFrameColor;
- private float mFrameWidth;
- private float mFramePadding;
- private Bitmap mBitmap;
- private Drawable mDrawable;
- private boolean mIsDisabled;
-
- private final Paint mFramePaint = new Paint();
- private final Paint mBitmapPaint = new Paint();
- private final Matrix mDrawMatrix = new Matrix();
-
- private float mScale = 1;
+ private final UserIconDrawable mDrawable = new UserIconDrawable();
public UserAvatarView(Context context, AttributeSet attrs,
int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.UserAvatarView, defStyleAttr, defStyleRes);
final int N = a.getIndexCount();
for (int i = 0; i < N; i++) {
int attr = a.getIndex(i);
switch (attr) {
+ case R.styleable.UserAvatarView_avatarPadding:
+ setAvatarPadding(a.getDimension(attr, 0));
+ break;
case R.styleable.UserAvatarView_frameWidth:
setFrameWidth(a.getDimension(attr, 0));
break;
case R.styleable.UserAvatarView_framePadding:
setFramePadding(a.getDimension(attr, 0));
break;
- case R.styleable.UserAvatarView_activeFrameColor:
- setActiveFrameColor(a.getColor(attr, 0));
- break;
case R.styleable.UserAvatarView_frameColor:
- setFrameColor(a.getColor(attr, 0));
+ setFrameColor(a.getColorStateList(attr));
+ break;
+ case R.styleable.UserAvatarView_badgeDiameter:
+ setBadgeDiameter(a.getDimension(attr, 0));
+ break;
+ case R.styleable.UserAvatarView_badgeMargin:
+ setBadgeMargin(a.getDimension(attr, 0));
break;
}
}
a.recycle();
-
- mFramePaint.setAntiAlias(true);
- mFramePaint.setStyle(Paint.Style.STROKE);
- mBitmapPaint.setAntiAlias(true);
+ setBackground(mDrawable);
}
public UserAvatarView(Context context, AttributeSet attrs, int defStyleAttr) {
@@ -94,180 +82,61 @@
this(context, null);
}
+ /**
+ * @deprecated use {@link #setAvatar(Bitmap)} instead.
+ */
+ @Deprecated
public void setBitmap(Bitmap bitmap) {
- setDrawable(null);
- mBitmap = bitmap;
- if (mBitmap != null) {
- mBitmapPaint.setShader(new BitmapShader(
- bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
- } else {
- mBitmapPaint.setShader(null);
- }
- configureBounds();
- invalidate();
+ setAvatar(bitmap);
}
- public void setFrameColor(int frameColor) {
- mFrameColor = frameColor;
- invalidate();
- }
-
- public void setActiveFrameColor(int activeFrameColor) {
- mActiveFrameColor = activeFrameColor;
- invalidate();
+ public void setFrameColor(ColorStateList color) {
+ mDrawable.setFrameColor(color);
}
public void setFrameWidth(float frameWidth) {
- mFrameWidth = frameWidth;
- invalidate();
+ mDrawable.setFrameWidth(frameWidth);
}
public void setFramePadding(float framePadding) {
- mFramePadding = framePadding;
- invalidate();
+ mDrawable.setFramePadding(framePadding);
}
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- configureBounds();
+ public void setAvatarPadding(float avatarPadding) {
+ mDrawable.setPadding(avatarPadding);
}
- public void configureBounds() {
- int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
- int vheight = getHeight() - mPaddingTop - mPaddingBottom;
-
- int dwidth;
- int dheight;
- if (mBitmap != null) {
- dwidth = mBitmap.getWidth();
- dheight = mBitmap.getHeight();
- } else if (mDrawable != null) {
- vwidth -= 2 * (mFrameWidth - 1);
- vheight -= 2 * (mFrameWidth - 1);
- dwidth = vwidth;
- dheight = vheight;
- mDrawable.setBounds(0, 0, dwidth, dheight);
- } else {
- return;
- }
-
- float scale;
- float dx;
- float dy;
-
- scale = Math.min((float) vwidth / (float) dwidth,
- (float) vheight / (float) dheight);
-
- dx = (int) ((vwidth - dwidth * scale) * 0.5f + 0.5f);
- dy = (int) ((vheight - dheight * scale) * 0.5f + 0.5f);
-
- mDrawMatrix.setScale(scale, scale);
- mDrawMatrix.postTranslate(dx, dy);
- mScale = scale;
+ public void setBadgeDiameter(float diameter) {
+ mDrawable.setBadgeRadius(diameter * 0.5f);
}
- @Override
- protected void onDraw(Canvas canvas) {
- int frameColor = isActivated() ? mActiveFrameColor : mFrameColor;
- float halfW = getWidth() / 2f;
- float halfH = getHeight() / 2f;
- float halfSW = Math.min(halfH, halfW);
- updateDrawableIfDisabled();
- if (mBitmap != null && mScale > 0) {
- int saveCount = canvas.getSaveCount();
- canvas.save();
- canvas.translate(mPaddingLeft, mPaddingTop);
- canvas.concat(mDrawMatrix);
- float halfBW = mBitmap.getWidth() / 2f;
- float halfBH = mBitmap.getHeight() / 2f;
- float halfBSW = Math.min(halfBH, halfBW);
- canvas.drawCircle(halfBW, halfBH, halfBSW - mFrameWidth / mScale + 1, mBitmapPaint);
- canvas.restoreToCount(saveCount);
- } else if (mDrawable != null && mScale > 0) {
- int saveCount = canvas.getSaveCount();
- canvas.save();
- canvas.translate(mPaddingLeft, mPaddingTop);
- canvas.translate(mFrameWidth - 1, mFrameWidth - 1);
- canvas.concat(mDrawMatrix);
- mDrawable.draw(canvas);
- canvas.restoreToCount(saveCount);
- }
- if (frameColor != 0) {
- mFramePaint.setColor(frameColor);
- mFramePaint.setStrokeWidth(mFrameWidth);
- canvas.drawCircle(halfW, halfH, halfSW + (mFramePadding - mFrameWidth) / 2f,
- mFramePaint);
- }
+ public void setBadgeMargin(float margin) {
+ mDrawable.setBadgeMargin(margin);
+ }
+
+ public void setAvatar(Bitmap avatar) {
+ mDrawable.setIcon(avatar);
+ mDrawable.setBadge(null);
+ }
+
+ public void setAvatarWithBadge(Bitmap avatar, int userId) {
+ mDrawable.setIcon(avatar);
+ mDrawable.setBadgeIfManagedUser(getContext(), userId);
}
public void setDrawable(Drawable d) {
- if (mDrawable != null) {
- mDrawable.setCallback(null);
- unscheduleDrawable(mDrawable);
+ if (d instanceof UserIconDrawable) {
+ throw new RuntimeException("Recursively adding UserIconDrawable");
}
- mDrawable = d;
- if (d != null) {
- d.setCallback(this);
- if (d.isStateful()) {
- d.setState(getDrawableState());
- }
- d.setLayoutDirection(getLayoutDirection());
- configureBounds();
- }
- if (d != null) {
- mBitmap = null;
- }
- configureBounds();
- invalidate();
+ mDrawable.setIconDrawable(d);
+ mDrawable.setBadge(null);
}
- @Override
- public void invalidateDrawable(Drawable dr) {
- if (dr == mDrawable) {
- invalidate();
- } else {
- super.invalidateDrawable(dr);
+ public void setDrawableWithBadge(Drawable d, int userId) {
+ if (d instanceof UserIconDrawable) {
+ throw new RuntimeException("Recursively adding UserIconDrawable");
}
- }
-
- @Override
- protected boolean verifyDrawable(Drawable who) {
- return who == mDrawable || super.verifyDrawable(who);
- }
-
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
- if (mDrawable != null && mDrawable.isStateful()) {
- mDrawable.setState(getDrawableState());
- }
- }
-
- public void setDisabled(boolean disabled) {
- if (mIsDisabled == disabled) {
- return;
- }
- mIsDisabled = disabled;
- invalidate();
- }
-
- private void updateDrawableIfDisabled() {
- int disabledColor = getContext().getColor(R.color.qs_tile_disabled_color);
- PorterDuffColorFilter filter = new PorterDuffColorFilter(disabledColor,
- PorterDuff.Mode.SRC_ATOP);
- if (mBitmap != null) {
- if (mIsDisabled) {
- mBitmapPaint.setColorFilter(filter);
- } else {
- mBitmapPaint.setColorFilter(null);
- }
- } else if (mDrawable != null) {
- if (mIsDisabled) {
- mDrawable.setColorFilter(filter);
- } else {
- mDrawable.setColorFilter(null);
- }
- }
+ mDrawable.setIconDrawable(d);
+ mDrawable.setBadgeIfManagedUser(getContext(), userId);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index bb3e116..ea64fd8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -16,158 +16,33 @@
package com.android.systemui.statusbar.policy;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.BatteryManager;
-import android.os.Handler;
-import android.os.PowerManager;
-import android.util.Log;
-
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.ArrayList;
-public class BatteryController extends BroadcastReceiver {
- private static final String TAG = "BatteryController";
+public interface BatteryController {
+ /**
+ * Prints the current state of the {@link BatteryController} to the given {@link PrintWriter}.
+ */
+ void dump(FileDescriptor fd, PrintWriter pw, String[] args);
- public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
+ /**
+ * Sets if the current device is in power save mode.
+ */
+ void setPowerSaveMode(boolean powerSave);
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ /**
+ * Returns {@code true} if the device is currently in power save mode.
+ */
+ boolean isPowerSave();
- private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
- private final PowerManager mPowerManager;
- private final Handler mHandler;
+ void addStateChangedCallback(BatteryStateChangeCallback cb);
+ void removeStateChangedCallback(BatteryStateChangeCallback cb);
- private int mLevel;
- private boolean mPluggedIn;
- private boolean mCharging;
- private boolean mCharged;
- private boolean mPowerSave;
- private boolean mTestmode = false;
-
- public BatteryController(Context context) {
- mHandler = new Handler();
- mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
- filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
- filter.addAction(ACTION_LEVEL_TEST);
- context.registerReceiver(this, filter);
-
- updatePowerSave();
- }
-
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("BatteryController state:");
- pw.print(" mLevel="); pw.println(mLevel);
- pw.print(" mPluggedIn="); pw.println(mPluggedIn);
- pw.print(" mCharging="); pw.println(mCharging);
- pw.print(" mCharged="); pw.println(mCharged);
- pw.print(" mPowerSave="); pw.println(mPowerSave);
- }
-
- public void setPowerSaveMode(boolean powerSave) {
- mPowerManager.setPowerSaveMode(powerSave);
- }
-
- public void addStateChangedCallback(BatteryStateChangeCallback cb) {
- mChangeCallbacks.add(cb);
- cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
- cb.onPowerSaveChanged(mPowerSave);
- }
-
- public void removeStateChangedCallback(BatteryStateChangeCallback cb) {
- mChangeCallbacks.remove(cb);
- }
-
- public void onReceive(final Context context, Intent intent) {
- final String action = intent.getAction();
- if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
- if (mTestmode && !intent.getBooleanExtra("testmode", false)) return;
- mLevel = (int)(100f
- * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
- / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
- mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
-
- final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
- BatteryManager.BATTERY_STATUS_UNKNOWN);
- mCharged = status == BatteryManager.BATTERY_STATUS_FULL;
- mCharging = mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING;
-
- fireBatteryLevelChanged();
- } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
- updatePowerSave();
- } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)) {
- setPowerSave(intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false));
- } else if (action.equals(ACTION_LEVEL_TEST)) {
- mTestmode = true;
- mHandler.post(new Runnable() {
- int curLevel = 0;
- int incr = 1;
- int saveLevel = mLevel;
- boolean savePlugged = mPluggedIn;
- Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
- @Override
- public void run() {
- if (curLevel < 0) {
- mTestmode = false;
- dummy.putExtra("level", saveLevel);
- dummy.putExtra("plugged", savePlugged);
- dummy.putExtra("testmode", false);
- } else {
- dummy.putExtra("level", curLevel);
- dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC
- : 0);
- dummy.putExtra("testmode", true);
- }
- context.sendBroadcast(dummy);
-
- if (!mTestmode) return;
-
- curLevel += incr;
- if (curLevel == 100) {
- incr *= -1;
- }
- mHandler.postDelayed(this, 200);
- }
- });
- }
- }
-
- public boolean isPowerSave() {
- return mPowerSave;
- }
-
- private void updatePowerSave() {
- setPowerSave(mPowerManager.isPowerSaveMode());
- }
-
- private void setPowerSave(boolean powerSave) {
- if (powerSave == mPowerSave) return;
- mPowerSave = powerSave;
- if (DEBUG) Log.d(TAG, "Power save is " + (mPowerSave ? "on" : "off"));
- firePowerSaveChanged();
- }
-
- private void fireBatteryLevelChanged() {
- final int N = mChangeCallbacks.size();
- for (int i = 0; i < N; i++) {
- mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
- }
- }
-
- private void firePowerSaveChanged() {
- final int N = mChangeCallbacks.size();
- for (int i = 0; i < N; i++) {
- mChangeCallbacks.get(i).onPowerSaveChanged(mPowerSave);
- }
- }
-
- public interface BatteryStateChangeCallback {
+ /**
+ * A listener that will be notified whenever a change in battery level or power save mode
+ * has occurred.
+ */
+ interface BatteryStateChangeCallback {
void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging);
void onPowerSaveChanged(boolean isPowerSave);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
new file mode 100644
index 0000000..24207f3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -0,0 +1,179 @@
+/*
+ * 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.os.BatteryManager;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Default implementation of a {@link BatteryController}. This controller monitors for battery
+ * level change events that are broadcasted by the system.
+ */
+public class BatteryControllerImpl extends BroadcastReceiver implements BatteryController {
+ private static final String TAG = "BatteryController";
+
+ public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
+
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private final ArrayList<BatteryController.BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
+ private final PowerManager mPowerManager;
+ private final Handler mHandler;
+
+ protected int mLevel;
+ protected boolean mPluggedIn;
+ protected boolean mCharging;
+ protected boolean mCharged;
+ protected boolean mPowerSave;
+ private boolean mTestmode = false;
+
+ public BatteryControllerImpl(Context context) {
+ mHandler = new Handler();
+ mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
+ filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
+ filter.addAction(ACTION_LEVEL_TEST);
+ context.registerReceiver(this, filter);
+
+ updatePowerSave();
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("BatteryController state:");
+ pw.print(" mLevel="); pw.println(mLevel);
+ pw.print(" mPluggedIn="); pw.println(mPluggedIn);
+ pw.print(" mCharging="); pw.println(mCharging);
+ pw.print(" mCharged="); pw.println(mCharged);
+ pw.print(" mPowerSave="); pw.println(mPowerSave);
+ }
+
+ @Override
+ public void setPowerSaveMode(boolean powerSave) {
+ mPowerManager.setPowerSaveMode(powerSave);
+ }
+
+ @Override
+ public void addStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
+ mChangeCallbacks.add(cb);
+ cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
+ cb.onPowerSaveChanged(mPowerSave);
+ }
+
+ @Override
+ public void removeStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
+ mChangeCallbacks.remove(cb);
+ }
+
+ @Override
+ public void onReceive(final Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
+ if (mTestmode && !intent.getBooleanExtra("testmode", false)) return;
+ mLevel = (int)(100f
+ * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
+ / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
+ mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
+
+ final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
+ BatteryManager.BATTERY_STATUS_UNKNOWN);
+ mCharged = status == BatteryManager.BATTERY_STATUS_FULL;
+ mCharging = mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING;
+
+ fireBatteryLevelChanged();
+ } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
+ updatePowerSave();
+ } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)) {
+ setPowerSave(intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false));
+ } else if (action.equals(ACTION_LEVEL_TEST)) {
+ mTestmode = true;
+ mHandler.post(new Runnable() {
+ int curLevel = 0;
+ int incr = 1;
+ int saveLevel = mLevel;
+ boolean savePlugged = mPluggedIn;
+ Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
+ @Override
+ public void run() {
+ if (curLevel < 0) {
+ mTestmode = false;
+ dummy.putExtra("level", saveLevel);
+ dummy.putExtra("plugged", savePlugged);
+ dummy.putExtra("testmode", false);
+ } else {
+ dummy.putExtra("level", curLevel);
+ dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC
+ : 0);
+ dummy.putExtra("testmode", true);
+ }
+ context.sendBroadcast(dummy);
+
+ if (!mTestmode) return;
+
+ curLevel += incr;
+ if (curLevel == 100) {
+ incr *= -1;
+ }
+ mHandler.postDelayed(this, 200);
+ }
+ });
+ }
+ }
+
+ @Override
+ public boolean isPowerSave() {
+ return mPowerSave;
+ }
+
+ private void updatePowerSave() {
+ setPowerSave(mPowerManager.isPowerSaveMode());
+ }
+
+ private void setPowerSave(boolean powerSave) {
+ if (powerSave == mPowerSave) return;
+ mPowerSave = powerSave;
+ if (DEBUG) Log.d(TAG, "Power save is " + (mPowerSave ? "on" : "off"));
+ firePowerSaveChanged();
+ }
+
+ protected void fireBatteryLevelChanged() {
+ final int N = mChangeCallbacks.size();
+ for (int i = 0; i < N; i++) {
+ mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
+ }
+ }
+
+ private void firePowerSaveChanged() {
+ final int N = mChangeCallbacks.size();
+ for (int i = 0; i < N; i++) {
+ mChangeCallbacks.get(i).onPowerSaveChanged(mPowerSave);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index ab81712..ebefdde 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -185,6 +185,11 @@
if (alert) {
HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(headsUp.key);
+ if (headsUpEntry == null) {
+ // the entry was released before this update (i.e by a listener) This can happen
+ // with the groupmanager
+ return;
+ }
headsUpEntry.updateEntry();
setEntryPinned(headsUpEntry, shouldHeadsUpBecomePinned(headsUp));
}
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 fb310a6..c39d718 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
@@ -253,17 +253,13 @@
UserDetailItemView v = (UserDetailItemView) convertView;
String name = getName(mContext, item);
- Drawable drawable;
if (item.picture == null) {
- drawable = getDrawable(mContext, item).mutate();
+ v.bind(name, getDrawable(mContext, item).mutate(), item.resolveId());
} else {
- drawable = new BitmapDrawable(mContext.getResources(), item.picture);
+ v.bind(name, item.picture, item.info.id);
}
// Disable the icon if switching is disabled
- if (!item.isSwitchToEnabled) {
- drawable.setTint(mContext.getColor(R.color.qs_tile_disabled_color));
- }
- v.bind(name, drawable);
+ v.setAvatarEnabled(item.isSwitchToEnabled);
convertView.setActivated(item.isCurrent);
convertView.setTag(item);
return convertView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index a85fe0d..5046456 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -114,8 +114,8 @@
@Override
public String getProfileOwnerName() {
- for (UserInfo profile : mUserManager.getProfiles(mCurrentUserId)) {
- String name = mDevicePolicyManager.getProfileOwnerNameAsUser(profile.id);
+ for (int profileId : mUserManager.getProfileIdsWithDisabled(mCurrentUserId)) {
+ String name = mDevicePolicyManager.getProfileOwnerNameAsUser(profileId);
if (name != null) {
return name;
}
@@ -135,13 +135,13 @@
@Override
public String getProfileVpnName() {
- for (UserInfo profile : mUserManager.getProfiles(mVpnUserId)) {
- if (profile.id == mVpnUserId) {
+ for (int profileId : mUserManager.getProfileIdsWithDisabled(mVpnUserId)) {
+ if (profileId == mVpnUserId) {
continue;
}
- VpnConfig cfg = mCurrentVpns.get(profile.id);
+ VpnConfig cfg = mCurrentVpns.get(profileId);
if (cfg != null) {
- return getNameForVpnConfig(cfg, profile.getUserHandle());
+ return getNameForVpnConfig(cfg, UserHandle.of(profileId));
}
}
return null;
@@ -149,8 +149,8 @@
@Override
public boolean isVpnEnabled() {
- for (UserInfo profile : mUserManager.getProfiles(mVpnUserId)) {
- if (mCurrentVpns.get(profile.id) != null) {
+ for (int profileId : mUserManager.getProfileIdsWithDisabled(mVpnUserId)) {
+ if (mCurrentVpns.get(profileId) != null) {
return true;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
index 85ac755..bae5bda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
@@ -26,7 +26,6 @@
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.RemoteException;
@@ -37,7 +36,7 @@
import android.util.Pair;
import com.android.internal.util.UserIcons;
-import com.android.systemui.BitmapHelper;
+import com.android.settingslib.drawable.UserIconDrawable;
import com.android.systemui.R;
import java.util.ArrayList;
@@ -155,8 +154,8 @@
Drawable avatar = null;
Bitmap rawAvatar = um.getUserIcon(userId);
if (rawAvatar != null) {
- avatar = new BitmapDrawable(mContext.getResources(),
- BitmapHelper.createCircularClip(rawAvatar, avatarSize, avatarSize));
+ avatar = new UserIconDrawable(avatarSize)
+ .setIcon(rawAvatar).setBadgeIfManagedUser(mContext, userId).bake();
} else {
avatar = UserIcons.getDefaultUserIcon(isGuest? UserHandle.USER_NULL : userId,
/* light= */ true);
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 ea0bdf2..c82ba3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -50,7 +50,6 @@
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.util.UserIcons;
import com.android.settingslib.RestrictedLockUtils;
-import com.android.systemui.BitmapHelper;
import com.android.systemui.GuestResumeSessionReceiver;
import com.android.systemui.R;
import com.android.systemui.SystemUISecondaryUserService;
@@ -197,8 +196,6 @@
boolean canSwitchUsers = mUserManager.canSwitchUsers();
UserInfo currentUserInfo = null;
UserRecord guestRecord = null;
- int avatarSize = mContext.getResources()
- .getDimensionPixelSize(R.dimen.max_avatar_size);
for (UserInfo info : infos) {
boolean isCurrent = currentId == info.id;
@@ -219,8 +216,10 @@
picture = mUserManager.getUserIcon(info.id);
if (picture != null) {
- picture = BitmapHelper.createCircularClip(
- picture, avatarSize, avatarSize);
+ int avatarSize = mContext.getResources()
+ .getDimensionPixelSize(R.dimen.max_avatar_size);
+ picture = Bitmap.createScaledBitmap(
+ picture, avatarSize, avatarSize, true);
}
}
int index = isCurrent ? 0 : records.size();
@@ -664,8 +663,7 @@
if (item.isAddUser) {
return context.getDrawable(R.drawable.ic_add_circle_qs);
}
- return UserIcons.getDefaultUserIcon(item.isGuest ? UserHandle.USER_NULL : item.info.id,
- /* light= */ true);
+ return UserIcons.getDefaultUserIcon(item.resolveId(), /* light= */ true);
}
public void refresh() {
@@ -718,6 +716,13 @@
isSwitchToEnabled);
}
+ public int resolveId() {
+ if (isGuest || info == null) {
+ return UserHandle.USER_NULL;
+ }
+ return info.id;
+ }
+
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("UserRecord(");
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 6bb60f7..7c5cdfb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -299,7 +299,7 @@
setDimAmount((Float) animation.getAnimatedValue());
}
};
- private ViewGroup mQsContainer;
+ protected ViewGroup mQsContainer;
private boolean mContinuousShadowUpdate;
private ViewTreeObserver.OnPreDrawListener mShadowUpdater
= new ViewTreeObserver.OnPreDrawListener() {
@@ -986,7 +986,8 @@
}
public void dismissViewAnimated(View child, Runnable endRunnable, int delay, long duration) {
- mSwipeHelper.dismissChild(child, 0, endRunnable, delay, true, duration);
+ mSwipeHelper.dismissChild(child, 0, endRunnable, delay, true, duration,
+ true /* isDismissAll */);
}
public void snapViewIfNeeded(View child) {
@@ -3194,9 +3195,6 @@
disableClipOptimization();
}
handleDismissAllClipping();
- if (mCurrIconRow != null && mCurrIconRow.isVisible()) {
- mCurrIconRow.getNotificationParent().animateTranslateNotification(0 /* left target */);
- }
}
private void handleDismissAllClipping() {
@@ -3456,8 +3454,10 @@
}
private class NotificationSwipeHelper extends SwipeHelper {
- private static final long GEAR_SHOW_DELAY = 60;
+ private static final long SHOW_GEAR_DELAY = 60;
+ private static final long COVER_GEAR_DELAY = 4000;
private CheckForDrag mCheckForDrag;
+ private Runnable mFalsingCheck;
private Handler mHandler;
private boolean mGearSnappedTo;
private boolean mGearSnappedOnLeft;
@@ -3465,6 +3465,12 @@
public NotificationSwipeHelper(int swipeDirection, Callback callback, Context context) {
super(swipeDirection, callback, context);
mHandler = new Handler();
+ mFalsingCheck = new Runnable() {
+ @Override
+ public void run() {
+ resetExposedGearView(true /* animate */, true /* force */);
+ }
+ };
}
@Override
@@ -3479,6 +3485,7 @@
}
mCheckForDrag = null;
mCurrIconRow = null;
+ mHandler.removeCallbacks(mFalsingCheck);
// Slide back any notifications that might be showing a gear
resetExposedGearView(true /* animate */, false /* force */);
@@ -3492,6 +3499,8 @@
@Override
public void onMoveUpdate(View view, float translation, float delta) {
+ mHandler.removeCallbacks(mFalsingCheck);
+
if (mCurrIconRow != null) {
mCurrIconRow.setSnapping(false); // If we're moving, we're not snapping.
@@ -3617,6 +3626,12 @@
setSnappedToGear(true);
}
onDragCancelled(animView);
+
+ // If we're on the lockscreen we want to false this.
+ if (mPhoneStatusBar.getBarState() == StatusBarState.KEYGUARD) {
+ mHandler.removeCallbacks(mFalsingCheck);
+ mHandler.postDelayed(mFalsingCheck, COVER_GEAR_DELAY);
+ }
super.snapChild(animView, target, velocity);
}
@@ -3624,25 +3639,24 @@
if (mTranslatingParentView == null) {
return false;
}
- final float snapBackThreshold = getSpaceForGear(animView);
+ // If the notification can't be dismissed then how far it can move is
+ // restricted -- reduce the distance it needs to move in this case.
+ final float multiplier = canChildBeDismissed(animView) ? 0.4f : 0.2f;
+ final float snapBackThreshold = getSpaceForGear(animView) * multiplier;
final float translation = getTranslation(animView);
final boolean fromLeft = translation > 0;
final float absTrans = Math.abs(translation);
final float notiThreshold = getSize(mTranslatingParentView) * 0.4f;
- // If the notification can't be dismissed then how far it can move is
- // restricted -- reduce the distance it needs to move in this case.
- final float multiplier = canChildBeDismissed(animView) ? 0.4f : 0.2f;
- return absTrans >= snapBackThreshold * 0.4f && absTrans <= notiThreshold;
+ return mCurrIconRow.isVisible() && (mCurrIconRow.isIconOnLeft()
+ ? (translation > snapBackThreshold && translation <= notiThreshold)
+ : (translation < -snapBackThreshold && translation >= -notiThreshold));
}
@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) {
+ if (v instanceof ExpandableNotificationRow) {
return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener);
} else {
return super.getViewTranslationAnimator(v, target, listener);
@@ -3651,22 +3665,12 @@
@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);
- }
+ ((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();
- }
+ return ((ExpandableView) v).getTranslation();
}
public void closeControlsIfOutsideTouch(MotionEvent ev) {
@@ -3733,7 +3737,7 @@
private void checkForDrag() {
if (mCheckForDrag == null || !mHandler.hasCallbacks(mCheckForDrag)) {
mCheckForDrag = new CheckForDrag();
- mHandler.postDelayed(mCheckForDrag, GEAR_SHOW_DELAY);
+ mHandler.postDelayed(mCheckForDrag, SHOW_GEAR_DELAY);
}
}
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 f9bb5e3..450001f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -19,6 +19,7 @@
import android.content.ComponentName;
import android.graphics.Rect;
import android.os.IBinder;
+import android.os.RemoteException;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.view.View;
@@ -29,12 +30,22 @@
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.tv.pip.PipManager;
-/*
+/**
* Status bar implementation for "large screen" products that mostly present no on-screen nav
*/
public class TvStatusBar extends BaseStatusBar {
+ /**
+ * Tracking calls to View.setSystemUiVisibility().
+ */
+ int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
+
+ /**
+ * Last value sent to window manager.
+ */
+ private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE;
+
@Override
public void setIcon(String slot, StatusBarIcon icon) {
}
@@ -207,4 +218,30 @@
@Override
public void clickTile(ComponentName tile) {
}
+
+ @Override
+ public void start() {
+ super.start();
+ putComponent(TvStatusBar.class, this);
+ }
+
+ public void updateRecentsVisibility(boolean visible) {
+ // Update the recents visibility flag
+ if (visible) {
+ mSystemUiVisibility |= View.RECENT_APPS_VISIBLE;
+ } else {
+ mSystemUiVisibility &= ~View.RECENT_APPS_VISIBLE;
+ }
+ notifyUiVisibilityChanged(mSystemUiVisibility);
+ }
+
+ private void notifyUiVisibilityChanged(int vis) {
+ try {
+ if (mLastDispatchedSystemUiVisibility != vis) {
+ mWindowManagerService.statusBarVisibilityChanged(vis);
+ mLastDispatchedSystemUiVisibility = vis;
+ }
+ } catch (RemoteException ex) {
+ }
+ }
}
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 fe54090..a445e77 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -36,6 +36,7 @@
import android.os.RemoteException;
import android.os.SystemProperties;
import android.util.Log;
+import android.util.Pair;
import com.android.systemui.Prefs;
import com.android.systemui.R;
@@ -63,6 +64,20 @@
private static final int MAX_RUNNING_TASKS_COUNT = 10;
/**
+ * List of package and class name which are considered as Settings,
+ * so PIP location should be adjusted to the left of the side panel.
+ */
+ private static final List<Pair<String, String>> sSettingsPackageAndClassNamePairList;
+ static {
+ sSettingsPackageAndClassNamePairList = new ArrayList<>();
+ sSettingsPackageAndClassNamePairList.add(new Pair<String, String>(
+ "com.android.tv.settings", null));
+ sSettingsPackageAndClassNamePairList.add(new Pair<String, String>(
+ "com.google.android.leanbacklauncher",
+ "com.google.android.leanbacklauncher.settings.HomeScreenSettingsActivity"));
+ }
+
+ /**
* State when there's no PIP.
*/
public static final int STATE_NO_PIP = 0;
@@ -108,6 +123,7 @@
private int mSuspendPipResizingReason;
private Context mContext;
+ private SystemServicesProxy mSystemServiceProxy;
private PipRecentsOverlayManager mPipRecentsOverlayManager;
private IActivityManager mActivityManager;
private MediaSessionManager mMediaSessionManager;
@@ -117,6 +133,8 @@
private List<MediaListener> mMediaListeners = new ArrayList<>();
private Rect mCurrentPipBounds;
private Rect mPipBounds;
+ private Rect mDefaultPipBounds;
+ private Rect mSettingsPipBounds;
private Rect mMenuModePipBounds;
private Rect mRecentsPipBounds;
private Rect mRecentsFocusedPipBounds;
@@ -176,8 +194,10 @@
mInitialized = true;
mContext = context;
Resources res = context.getResources();
- mPipBounds = Rect.unflattenFromString(res.getString(
+ mDefaultPipBounds = Rect.unflattenFromString(res.getString(
com.android.internal.R.string.config_defaultPictureInPictureBounds));
+ mSettingsPipBounds = Rect.unflattenFromString(res.getString(
+ R.string.pip_settings_bounds));
mMenuModePipBounds = Rect.unflattenFromString(res.getString(
R.string.pip_menu_bounds));
mRecentsPipBounds = Rect.unflattenFromString(res.getString(
@@ -186,9 +206,11 @@
R.string.pip_recents_focused_bounds));
mRecentsFocusChangedAnimationDurationMs = res.getInteger(
R.integer.recents_tv_pip_focus_anim_duration);
+ mPipBounds = mDefaultPipBounds;
mActivityManager = ActivityManagerNative.getDefault();
- SystemServicesProxy.getInstance(context).registerTaskStackListener(mTaskStackListener);
+ mSystemServiceProxy = SystemServicesProxy.getInstance(context);
+ mSystemServiceProxy.registerTaskStackListener(mTaskStackListener);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_MEDIA_RESOURCE_GRANTED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter);
@@ -522,10 +544,25 @@
return PLAYBACK_STATE_UNAVAILABLE;
}
+ private static boolean isSettingsShown(ComponentName topActivity) {
+ for (Pair<String, String> componentName : sSettingsPackageAndClassNamePairList) {
+ String packageName = componentName.first;
+ if (topActivity.getPackageName().equals(componentName.first)) {
+ String className = componentName.second;
+ if (className == null || topActivity.getClassName().equals(className)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
private TaskStackListener mTaskStackListener = new TaskStackListener() {
@Override
public void onTaskStackChanged() {
if (mState != STATE_NO_PIP) {
+ boolean hasPip = false;
+
StackInfo stackInfo = null;
try {
stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
@@ -541,11 +578,32 @@
for (int i = stackInfo.taskIds.length - 1; i >= 0; --i) {
if (stackInfo.taskIds[i] == mPipTaskId) {
// PIP task is still alive.
- return;
+ hasPip = true;
+ break;
}
}
- // PIP task doesn't exist anymore in PINNED_STACK.
- closePipInternal(true);
+ if (!hasPip) {
+ // PIP task doesn't exist anymore in PINNED_STACK.
+ closePipInternal(true);
+ return;
+ }
+ }
+ if (mState == STATE_PIP_OVERLAY) {
+ try {
+ List<RunningTaskInfo> runningTasks = mActivityManager.getTasks(1, 0);
+ if (runningTasks == null || runningTasks.size() == 0) {
+ return;
+ }
+ RunningTaskInfo topTask = runningTasks.get(0);
+ Rect bounds = isSettingsShown(topTask.topActivity)
+ ? mSettingsPipBounds : mDefaultPipBounds;
+ if (mPipBounds != bounds) {
+ mPipBounds = bounds;
+ resizePinnedStack(STATE_PIP_OVERLAY);
+ }
+ } catch (RemoteException e) {
+ Log.d(TAG, "Failed to detect top activity", e);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
index 04640a2..d7c4bbf 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
@@ -47,6 +47,7 @@
mAudioManager = audioManager;
getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+ setShowForAllUsers(true);
setMessage(mContext.getString(com.android.internal.R.string.safe_media_volume_warning));
setButton(DialogInterface.BUTTON_POSITIVE,
mContext.getString(com.android.internal.R.string.yes), this);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index 1d5ca04..91a8493 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -761,7 +761,37 @@
: (iconRes == R.drawable.ic_volume_media_bt || iconRes == row.iconRes)
? Events.ICON_STATE_UNMUTE
: Events.ICON_STATE_UNKNOWN;
- row.icon.setContentDescription(ss.name);
+ if (iconEnabled) {
+ if (isRingStream) {
+ if (isRingVibrate) {
+ row.icon.setContentDescription(mContext.getString(
+ R.string.volume_stream_content_description_unmute,
+ ss.name));
+ } else {
+ if (mController.hasVibrator()) {
+ row.icon.setContentDescription(mContext.getString(
+ R.string.volume_stream_content_description_vibrate,
+ ss.name));
+ } else {
+ row.icon.setContentDescription(mContext.getString(
+ R.string.volume_stream_content_description_mute,
+ ss.name));
+ }
+ }
+ } else {
+ if (ss.muted || mAutomute && ss.level == 0) {
+ row.icon.setContentDescription(mContext.getString(
+ R.string.volume_stream_content_description_unmute,
+ ss.name));
+ } else {
+ row.icon.setContentDescription(mContext.getString(
+ R.string.volume_stream_content_description_mute,
+ ss.name));
+ }
+ }
+ } else {
+ row.icon.setContentDescription(ss.name);
+ }
// update slider
final boolean enableSlider = !zenMuted;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTests.java
index f24b541..1e27603 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTests.java
@@ -18,7 +18,6 @@
import android.content.ComponentName;
import android.os.Handler;
import android.os.HandlerThread;
-import android.service.quicksettings.TileService;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.systemui.SysuiTestCase;
import org.mockito.ArgumentCaptor;
@@ -42,11 +41,10 @@
mTileServices = Mockito.mock(TileServices.class);
Mockito.when(mTileServices.getContext()).thenReturn(mContext);
mTileLifecycle = Mockito.mock(TileLifecycleManager.class);
+ Mockito.when(mTileLifecycle.isActiveTile()).thenReturn(false);
ComponentName componentName = new ComponentName(mContext,
TileServiceManagerTests.class);
Mockito.when(mTileLifecycle.getComponent()).thenReturn(componentName);
- mContext.getSharedPreferences(TileServiceManager.PREFS_FILE, 0).edit()
- .putInt(componentName.flattenToString(), TileService.TILE_MODE_PASSIVE).commit();
mTileServiceManager = new TileServiceManager(mTileServices, mHandler, mTileLifecycle);
}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index b3613df..ea3cffe 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2135,6 +2135,9 @@
// Suggestion -> Overflow -> Remove.
ACTION_SETTINGS_DISMISS_SUGGESTION = 387;
+ // Settings > Apps > Gear > Special Access > Premium SMS access
+ PREMIUM_SMS_ACCESS = 388;
+
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 3e7466f..613f890 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -363,12 +363,6 @@
private void enableFeatures() {
resetStreamState();
- if ((mEnabledFeatures & FLAG_FEATURE_INJECT_MOTION_EVENTS) != 0) {
- mMotionEventInjector = new MotionEventInjector(mContext.getMainLooper());
- addFirstEventHandler(mMotionEventInjector);
- mAms.setMotionEventInjector(mMotionEventInjector);
- }
-
if ((mEnabledFeatures & FLAG_FEATURE_AUTOCLICK) != 0) {
mAutoclickController = new AutoclickController(mContext, mUserId);
addFirstEventHandler(mAutoclickController);
@@ -384,6 +378,12 @@
addFirstEventHandler(mMagnificationGestureHandler);
}
+ if ((mEnabledFeatures & FLAG_FEATURE_INJECT_MOTION_EVENTS) != 0) {
+ mMotionEventInjector = new MotionEventInjector(mContext.getMainLooper());
+ addFirstEventHandler(mMotionEventInjector);
+ mAms.setMotionEventInjector(mMotionEventInjector);
+ }
+
if ((mEnabledFeatures & FLAG_FEATURE_FILTER_KEY_EVENTS) != 0) {
mKeyboardInterceptor = new KeyboardInterceptor(mAms);
addFirstEventHandler(mKeyboardInterceptor);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 2741733..ca17c43 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -439,7 +439,7 @@
}
if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) {
mSecurityPolicy.updateActiveAndAccessibilityFocusedWindowLocked(event.getWindowId(),
- event.getSourceNodeId(), event.getEventType());
+ event.getSourceNodeId(), event.getEventType(), event.getAction());
mSecurityPolicy.updateEventSourceLocked(event);
notifyAccessibilityServicesDelayedLocked(event, false);
notifyAccessibilityServicesDelayedLocked(event, true);
@@ -1795,9 +1795,8 @@
}
userState.mSoftKeyboardShowMode = 0;
userState.mServiceChangingSoftKeyboardMode = null;
+ notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode);
}
-
- notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode);
}
}
@@ -3829,7 +3828,7 @@
}
public void updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId,
- int eventType) {
+ int eventType, int eventAction) {
// The active window is either the window that has input focus or
// the window that the user is currently touching. If the user is
// touching a window that does not have input focus as soon as the
@@ -3882,8 +3881,12 @@
if (mAccessibilityFocusNodeId == nodeId) {
mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
}
- if (mAccessibilityFocusNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID
- && mAccessibilityFocusedWindowId == windowId) {
+ // Clear the window with focus if it no longer has focus and we aren't
+ // just moving focus from one view to the other in the same window
+ if ((mAccessibilityFocusNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID)
+ && (mAccessibilityFocusedWindowId == windowId)
+ && (eventAction != AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS)
+ ) {
mAccessibilityFocusedWindowId = INVALID_WINDOW_ID;
}
}
@@ -4355,6 +4358,7 @@
}
} else if (mAccessibilitySoftKeyboardModeUri.equals(uri)) {
if (readSoftKeyboardShowModeChangedLocked(userState)) {
+ notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode);
onUserStateChangedLocked(userState);
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
index b2196bf..fb1ef37 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
@@ -156,10 +156,10 @@
final float offsetY = sentSpec.offsetY;
// Compute the new center and update spec as needed.
- final float centerX = (mMagnifiedBounds.width() / 2.0f
- + mMagnifiedBounds.left - offsetX) / scale;
- final float centerY = (mMagnifiedBounds.height() / 2.0f
- + mMagnifiedBounds.top - offsetY) / scale;
+ final float centerX = (mMagnifiedBounds.width() / 2.0f - offsetX) / scale
+ + mMagnifiedBounds.left;
+ final float centerY = (mMagnifiedBounds.height() / 2.0f - offsetY) / scale
+ + mMagnifiedBounds.top;
if (updateSpec) {
setScaleAndCenter(scale, centerX, centerY, false);
} else {
@@ -256,7 +256,7 @@
public float getCenterX() {
synchronized (mLock) {
return (mMagnifiedBounds.width() / 2.0f
- + mMagnifiedBounds.left - getOffsetX()) / getScale();
+ - getOffsetX()) / getScale() + mMagnifiedBounds.left;
}
}
@@ -279,7 +279,7 @@
public float getCenterY() {
synchronized (mLock) {
return (mMagnifiedBounds.height() / 2.0f
- + mMagnifiedBounds.top - getOffsetY()) / getScale();
+ - getOffsetY()) / getScale() + mMagnifiedBounds.top;
}
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index f93fb1b..6ca3af8 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -460,12 +460,9 @@
}
synchronized (mLock) {
reloadWidgetsMaskedState(userId);
- List<UserInfo> profiles = mUserManager.getEnabledProfiles(userId);
- if (profiles != null) {
- for (int i = 0; i < profiles.size(); i++) {
- UserInfo user = profiles.get(i);
- reloadWidgetsMaskedState(user.id);
- }
+ int[] profileIds = mUserManager.getEnabledProfileIds(userId);
+ for (int profileId : profileIds) {
+ reloadWidgetsMaskedState(profileId);
}
}
}
@@ -3458,33 +3455,12 @@
public int[] getEnabledGroupProfileIds(int userId) {
final int parentId = getGroupParent(userId);
- final List<UserInfo> profiles;
final long identity = Binder.clearCallingIdentity();
try {
- profiles = mUserManager.getProfiles(parentId);
+ return mUserManager.getEnabledProfileIds(parentId);
} finally {
Binder.restoreCallingIdentity(identity);
}
-
- int enabledProfileCount = 0;
- final int profileCount = profiles.size();
- for (int i = 0; i < profileCount; i++) {
- if (profiles.get(i).isEnabled()) {
- enabledProfileCount++;
- }
- }
-
- int enabledProfileIndex = 0;
- final int[] profileIds = new int[enabledProfileCount];
- for (int i = 0; i < profileCount; i++) {
- UserInfo profile = profiles.get(i);
- if (profile.isEnabled()) {
- profileIds[enabledProfileIndex] = profile.getUserHandle().getIdentifier();
- enabledProfileIndex++;
- }
- }
-
- return profileIds;
}
public void enforceServiceExistsAndRequiresBindRemoteViewsPermission(
diff --git a/services/core/java/com/android/server/AnyMotionDetector.java b/services/core/java/com/android/server/AnyMotionDetector.java
index a0b5c15..e98b4aa 100644
--- a/services/core/java/com/android/server/AnyMotionDetector.java
+++ b/services/core/java/com/android/server/AnyMotionDetector.java
@@ -108,63 +108,71 @@
public AnyMotionDetector(PowerManager pm, Handler handler, SensorManager sm,
DeviceIdleCallback callback, float thresholdAngle) {
if (DEBUG) Slog.d(TAG, "AnyMotionDetector instantiated.");
- mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
- mWakeLock.setReferenceCounted(false);
- mHandler = handler;
- mSensorManager = sm;
- mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- mMeasurementInProgress = false;
- mState = STATE_INACTIVE;
- mCallback = callback;
- mThresholdAngle = thresholdAngle;
- mRunningStats = new RunningSignalStats();
- mNumSufficientSamples = (int) Math.ceil(
- ((double)ORIENTATION_MEASUREMENT_DURATION_MILLIS / SAMPLING_INTERVAL_MILLIS));
- if (DEBUG) Slog.d(TAG, "mNumSufficientSamples = " + mNumSufficientSamples);
+ synchronized (mLock) {
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+ mWakeLock.setReferenceCounted(false);
+ mHandler = handler;
+ mSensorManager = sm;
+ mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ mMeasurementInProgress = false;
+ mState = STATE_INACTIVE;
+ mCallback = callback;
+ mThresholdAngle = thresholdAngle;
+ mRunningStats = new RunningSignalStats();
+ mNumSufficientSamples = (int) Math.ceil(
+ ((double)ORIENTATION_MEASUREMENT_DURATION_MILLIS / SAMPLING_INTERVAL_MILLIS));
+ if (DEBUG) Slog.d(TAG, "mNumSufficientSamples = " + mNumSufficientSamples);
+ }
}
/*
* Acquire accel data until we determine AnyMotion status.
*/
public void checkForAnyMotion() {
- if (DEBUG) Slog.d(TAG, "checkForAnyMotion(). mState = " + mState);
+ if (DEBUG) {
+ Slog.d(TAG, "checkForAnyMotion(). mState = " + mState);
+ }
if (mState != STATE_ACTIVE) {
- mState = STATE_ACTIVE;
- if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_ACTIVE.");
- mCurrentGravityVector = null;
- mPreviousGravityVector = null;
- startOrientationMeasurement();
+ synchronized (mLock) {
+ mState = STATE_ACTIVE;
+ if (DEBUG) {
+ Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_ACTIVE.");
+ }
+ mCurrentGravityVector = null;
+ mPreviousGravityVector = null;
+ mWakeLock.acquire();
+ startOrientationMeasurementLocked();
+ }
}
}
public void stop() {
if (mState == STATE_ACTIVE) {
- mState = STATE_INACTIVE;
- if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE.");
- if (mMeasurementInProgress) {
- mMeasurementInProgress = false;
- mSensorManager.unregisterListener(mListener);
+ synchronized (mLock) {
+ mState = STATE_INACTIVE;
+ if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE.");
+ if (mMeasurementInProgress) {
+ mMeasurementInProgress = false;
+ mSensorManager.unregisterListener(mListener);
+ }
+ mHandler.removeCallbacks(mMeasurementTimeout);
+ mHandler.removeCallbacks(mSensorRestart);
+ mCurrentGravityVector = null;
+ mPreviousGravityVector = null;
+ mWakeLock.release();
}
- mHandler.removeCallbacks(mMeasurementTimeout);
- mHandler.removeCallbacks(mSensorRestart);
- mWakeLock.release();
- mCurrentGravityVector = null;
- mPreviousGravityVector = null;
}
}
- private void startOrientationMeasurement() {
- if (DEBUG) Slog.d(TAG, "startOrientationMeasurement: mMeasurementInProgress=" +
+ private void startOrientationMeasurementLocked() {
+ if (DEBUG) Slog.d(TAG, "startOrientationMeasurementLocked: mMeasurementInProgress=" +
mMeasurementInProgress + ", (mAccelSensor != null)=" + (mAccelSensor != null));
-
if (!mMeasurementInProgress && mAccelSensor != null) {
if (mSensorManager.registerListener(mListener, mAccelSensor,
SAMPLING_INTERVAL_MILLIS * 1000)) {
- mWakeLock.acquire();
mMeasurementInProgress = true;
mRunningStats.reset();
}
-
Message msg = Message.obtain(mHandler, mMeasurementTimeout);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg, ACCELEROMETER_DATA_TIMEOUT_MILLIS);
@@ -178,7 +186,6 @@
if (mMeasurementInProgress) {
mSensorManager.unregisterListener(mListener);
mHandler.removeCallbacks(mMeasurementTimeout);
- mWakeLock.release();
long detectionEndTime = SystemClock.elapsedRealtime();
mMeasurementInProgress = false;
mPreviousGravityVector = mCurrentGravityVector;
@@ -196,8 +203,10 @@
status = getStationaryStatus();
if (DEBUG) Slog.d(TAG, "getStationaryStatus() returned " + status);
if (status != RESULT_UNKNOWN) {
- if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE. status = " +
- status);
+ mWakeLock.release();
+ if (DEBUG) {
+ Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE. status = " + status);
+ }
mState = STATE_INACTIVE;
} else {
/*
@@ -275,7 +284,7 @@
@Override
public void run() {
synchronized (mLock) {
- startOrientationMeasurement();
+ startOrientationMeasurementLocked();
}
}
};
@@ -442,4 +451,4 @@
return msg;
}
}
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 48e96aa..8753992 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -124,6 +124,7 @@
private boolean mLastBatteryLevelCritical;
private int mLastMaxChargingCurrent;
private int mLastMaxChargingVoltage;
+ private int mLastChargeCounter;
private int mInvalidCharger;
private int mLastInvalidCharger;
@@ -341,6 +342,7 @@
+ ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline
+ ", maxChargingCurrent" + mBatteryProps.maxChargingCurrent
+ ", maxChargingVoltage" + mBatteryProps.maxChargingVoltage
+ + ", chargeCounter" + mBatteryProps.batteryChargeCounter
+ ", batteryStatus=" + mBatteryProps.batteryStatus
+ ", batteryHealth=" + mBatteryProps.batteryHealth
+ ", batteryPresent=" + mBatteryProps.batteryPresent
@@ -373,6 +375,7 @@
mBatteryProps.batteryTemperature != mLastBatteryTemperature ||
mBatteryProps.maxChargingCurrent != mLastMaxChargingCurrent ||
mBatteryProps.maxChargingVoltage != mLastMaxChargingVoltage ||
+ mBatteryProps.batteryChargeCounter != mLastChargeCounter ||
mInvalidCharger != mLastInvalidCharger)) {
if (mPlugType != mLastPlugType) {
@@ -501,6 +504,7 @@
mLastBatteryTemperature = mBatteryProps.batteryTemperature;
mLastMaxChargingCurrent = mBatteryProps.maxChargingCurrent;
mLastMaxChargingVoltage = mBatteryProps.maxChargingVoltage;
+ mLastChargeCounter = mBatteryProps.batteryChargeCounter;
mLastBatteryLevelCritical = mBatteryLevelCritical;
mLastInvalidCharger = mInvalidCharger;
}
@@ -527,6 +531,7 @@
intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger);
intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_CURRENT, mBatteryProps.maxChargingCurrent);
intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE, mBatteryProps.maxChargingVoltage);
+ intent.putExtra(BatteryManager.EXTRA_CHARGE_COUNTER, mBatteryProps.batteryChargeCounter);
if (DEBUG) {
Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryProps.batteryLevel +
", scale:" + BATTERY_SCALE + ", status:" + mBatteryProps.batteryStatus +
@@ -540,7 +545,8 @@
", Wireless powered:" + mBatteryProps.chargerWirelessOnline +
", icon:" + icon + ", invalid charger:" + mInvalidCharger +
", maxChargingCurrent:" + mBatteryProps.maxChargingCurrent +
- ", maxChargingVoltage:" + mBatteryProps.maxChargingVoltage);
+ ", maxChargingVoltage:" + mBatteryProps.maxChargingVoltage +
+ ", chargeCounter:" + mBatteryProps.batteryChargeCounter);
}
mHandler.post(new Runnable() {
@@ -772,6 +778,7 @@
pw.println(" Wireless powered: " + mBatteryProps.chargerWirelessOnline);
pw.println(" Max charging current: " + mBatteryProps.maxChargingCurrent);
pw.println(" Max charging voltage: " + mBatteryProps.maxChargingVoltage);
+ pw.println(" Charge counter: " + mBatteryProps.batteryChargeCounter);
pw.println(" status: " + mBatteryProps.batteryStatus);
pw.println(" health: " + mBatteryProps.batteryHealth);
pw.println(" present: " + mBatteryProps.batteryPresent);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 82a36b4..428e192 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -116,6 +116,7 @@
import com.android.internal.net.VpnProfile;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.MessageUtils;
import com.android.internal.util.XmlUtils;
import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.DataConnectionStats;
@@ -164,7 +165,7 @@
implements PendingIntent.OnFinished {
private static final String TAG = "ConnectivityService";
- private static final boolean DBG = false;
+ private static final boolean DBG = true;
private static final boolean VDBG = false;
private static final boolean LOGD_RULES = false;
@@ -224,6 +225,9 @@
private static final int ENABLED = 1;
private static final int DISABLED = 0;
+ private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
+ new Class[] { AsyncChannel.class, ConnectivityService.class, NetworkAgent.class });
+
private enum ReapUnvalidatedNetworks {
// Tear down networks that have no chance (e.g. even if validated) of becoming
// the highest scoring network satisfying a NetworkRequest. This should be passed when
@@ -446,9 +450,8 @@
*/
private class LegacyTypeTracker {
- private static final boolean DBG = false;
+ private static final boolean DBG = true;
private static final boolean VDBG = false;
- private static final String TAG = "CSLegacyTypeTracker";
/**
* Array of lists, one per legacy network type (e.g., TYPE_MOBILE_MMS).
@@ -601,12 +604,6 @@
pw.decreaseIndent();
pw.println();
}
-
- // This class needs its own log method because it has a different TAG.
- private void log(String s) {
- Slog.d(TAG, s);
- }
-
}
private LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker();
@@ -991,7 +988,16 @@
@Override
public Network getActiveNetwork() {
enforceAccessPermission();
- final int uid = Binder.getCallingUid();
+ return getActiveNetworkForUidInternal(Binder.getCallingUid());
+ }
+
+ @Override
+ public Network getActiveNetworkForUid(int uid) {
+ enforceConnectivityInternalPermission();
+ return getActiveNetworkForUidInternal(uid);
+ }
+
+ private Network getActiveNetworkForUidInternal(final int uid) {
final int user = UserHandle.getUserId(uid);
int vpnNetId = NETID_UNSET;
synchronized (mVpns) {
@@ -1519,7 +1525,7 @@
mInitialBroadcast = new Intent(intent);
}
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- if (DBG) {
+ if (VDBG) {
log("sendStickyBroadcast: action=" + intent.getAction());
}
@@ -1647,7 +1653,7 @@
}
if (LinkProperties.isValidMtu(mtu, newLp.hasGlobalIPv6Address()) == false) {
- loge("Unexpected mtu value: " + mtu + ", " + iface);
+ if (mtu != 0) loge("Unexpected mtu value: " + mtu + ", " + iface);
return;
}
@@ -1658,7 +1664,7 @@
}
try {
- if (DBG) log("Setting MTU size: " + iface + ", " + mtu);
+ if (VDBG) log("Setting MTU size: " + iface + ", " + mtu);
mNetd.setMtu(iface, mtu);
} catch (Exception e) {
Slog.e(TAG, "exception in setMtu()" + e);
@@ -1694,7 +1700,7 @@
if (tcpBufferSizes.equals(mCurrentTcpBufferSizes)) return;
try {
- if (DBG) Slog.d(TAG, "Setting tx/rx TCP buffers to " + tcpBufferSizes);
+ if (VDBG) Slog.d(TAG, "Setting tx/rx TCP buffers to " + tcpBufferSizes);
final String prefix = "/sys/kernel/ipv4/tcp_";
FileUtils.stringToFile(prefix + "rmem_min", values[0]);
@@ -1891,11 +1897,12 @@
}
}
- private boolean isLiveNetworkAgent(NetworkAgentInfo nai, String msg) {
+ private boolean isLiveNetworkAgent(NetworkAgentInfo nai, int what) {
if (nai.network == null) return false;
final NetworkAgentInfo officialNai = getNetworkAgentInfoForNetwork(nai.network);
if (officialNai != null && officialNai.equals(nai)) return true;
if (officialNai != null || VDBG) {
+ final String msg = sMagicDecoderRing.get(what, Integer.toString(what));
loge(msg + " - isLiveNetworkAgent found mismatched netId: " + officialNai +
" - " + nai);
}
@@ -1912,10 +1919,10 @@
super(looper);
}
- @Override
- public void handleMessage(Message msg) {
- NetworkInfo info;
+ private boolean maybeHandleAsyncChannelMessage(Message msg) {
switch (msg.what) {
+ default:
+ return false;
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
handleAsyncChannelHalfConnect(msg);
break;
@@ -1929,69 +1936,58 @@
handleAsyncChannelDisconnected(msg);
break;
}
+ }
+ return true;
+ }
+
+ private void maybeHandleNetworkAgentMessage(Message msg) {
+ NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
+ if (nai == null) {
+ if (VDBG) {
+ final String what = sMagicDecoderRing.get(msg.what, Integer.toString(msg.what));
+ log(String.format("%s from unknown NetworkAgent", what));
+ }
+ return;
+ }
+
+ switch (msg.what) {
case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
- NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
- if (nai == null) {
- loge("EVENT_NETWORK_CAPABILITIES_CHANGED from unknown NetworkAgent");
- } else {
- final NetworkCapabilities networkCapabilities =
- (NetworkCapabilities)msg.obj;
- if (networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL) ||
- networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
- Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability.");
- }
- if (nai.created && !nai.networkCapabilities.equalImmutableCapabilities(
- networkCapabilities)) {
- Slog.wtf(TAG, "BUG: " + nai + " changed immutable capabilities: "
- + nai.networkCapabilities + " -> " + networkCapabilities);
- }
- updateCapabilities(nai, networkCapabilities);
+ final NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj;
+ if (networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL) ||
+ networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
+ Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability.");
}
+ if (nai.created && !nai.networkCapabilities.equalImmutableCapabilities(
+ networkCapabilities)) {
+ Slog.wtf(TAG, "BUG: " + nai + " changed immutable capabilities: "
+ + nai.networkCapabilities + " -> " + networkCapabilities);
+ }
+ updateCapabilities(nai, networkCapabilities);
break;
}
case NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED: {
- NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
- if (nai == null) {
- loge("NetworkAgent not found for EVENT_NETWORK_PROPERTIES_CHANGED");
- } else {
- if (VDBG) {
- log("Update of LinkProperties for " + nai.name() +
- "; created=" + nai.created);
- }
- LinkProperties oldLp = nai.linkProperties;
- synchronized (nai) {
- nai.linkProperties = (LinkProperties)msg.obj;
- }
- if (nai.created) updateLinkProperties(nai, oldLp);
+ if (VDBG) {
+ log("Update of LinkProperties for " + nai.name() +
+ "; created=" + nai.created);
}
+ LinkProperties oldLp = nai.linkProperties;
+ synchronized (nai) {
+ nai.linkProperties = (LinkProperties)msg.obj;
+ }
+ if (nai.created) updateLinkProperties(nai, oldLp);
break;
}
case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {
- NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
- if (nai == null) {
- loge("EVENT_NETWORK_INFO_CHANGED from unknown NetworkAgent");
- break;
- }
- info = (NetworkInfo) msg.obj;
+ NetworkInfo info = (NetworkInfo) msg.obj;
updateNetworkInfo(nai, info);
break;
}
case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
- NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
- if (nai == null) {
- loge("EVENT_NETWORK_SCORE_CHANGED from unknown NetworkAgent");
- break;
- }
Integer score = (Integer) msg.obj;
if (score != null) updateNetworkScore(nai, score.intValue());
break;
}
case NetworkAgent.EVENT_UID_RANGES_ADDED: {
- NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
- if (nai == null) {
- loge("EVENT_UID_RANGES_ADDED from unknown NetworkAgent");
- break;
- }
try {
mNetd.addVpnUidRanges(nai.network.netId, (UidRange[])msg.obj);
} catch (Exception e) {
@@ -2001,11 +1997,6 @@
break;
}
case NetworkAgent.EVENT_UID_RANGES_REMOVED: {
- NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
- if (nai == null) {
- loge("EVENT_UID_RANGES_REMOVED from unknown NetworkAgent");
- break;
- }
try {
mNetd.removeVpnUidRanges(nai.network.netId, (UidRange[])msg.obj);
} catch (Exception e) {
@@ -2015,11 +2006,6 @@
break;
}
case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: {
- NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
- if (nai == null) {
- loge("EVENT_SET_EXPLICITLY_SELECTED from unknown NetworkAgent");
- break;
- }
if (nai.created && !nai.networkMisc.explicitlySelected) {
loge("ERROR: created network explicitly selected.");
}
@@ -2028,17 +2014,19 @@
break;
}
case NetworkAgent.EVENT_PACKET_KEEPALIVE: {
- NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
- if (nai == null) {
- loge("EVENT_PACKET_KEEPALIVE from unknown NetworkAgent");
- break;
- }
mKeepaliveTracker.handleEventPacketKeepalive(nai, msg);
break;
}
+ }
+ }
+
+ private boolean maybeHandleNetworkMonitorMessage(Message msg) {
+ switch (msg.what) {
+ default:
+ return false;
case NetworkMonitor.EVENT_NETWORK_TESTED: {
NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj;
- if (isLiveNetworkAgent(nai, "EVENT_NETWORK_TESTED")) {
+ if (isLiveNetworkAgent(nai, msg.what)) {
final boolean valid =
(msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
if (DBG) log(nai.name() + " validation " + (valid ? " passed" : "failed"));
@@ -2061,7 +2049,7 @@
}
case NetworkMonitor.EVENT_NETWORK_LINGER_COMPLETE: {
NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj;
- if (isLiveNetworkAgent(nai, "EVENT_NETWORK_LINGER_COMPLETE")) {
+ if (isLiveNetworkAgent(nai, msg.what)) {
handleLingerComplete(nai);
}
break;
@@ -2093,6 +2081,14 @@
break;
}
}
+ return true;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (!maybeHandleAsyncChannelMessage(msg) && !maybeHandleNetworkMonitorMessage(msg)) {
+ maybeHandleNetworkAgentMessage(msg);
+ }
}
}
@@ -2312,7 +2308,7 @@
if (DBG) log("Attempt to release unowned NetworkRequest " + request);
return;
}
- if (DBG) log("releasing NetworkRequest " + request);
+ if (VDBG || (DBG && nri.isRequest())) log("releasing NetworkRequest " + request);
nri.unlinkDeathRecipient();
mNetworkRequests.remove(request);
mNetworkRequestInfoLogs.log("RELEASE " + nri);
@@ -2325,7 +2321,7 @@
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
if (nai.networkRequests.get(nri.request.requestId) != null) {
nai.networkRequests.remove(nri.request.requestId);
- if (DBG) {
+ if (VDBG) {
log(" Removing from current network " + nai.name() +
", leaving " + nai.networkRequests.size() +
" requests.");
@@ -2436,14 +2432,14 @@
}
private void scheduleUnvalidatedPrompt(NetworkAgentInfo nai) {
- if (DBG) log("scheduleUnvalidatedPrompt " + nai.network);
+ if (VDBG) log("scheduleUnvalidatedPrompt " + nai.network);
mHandler.sendMessageDelayed(
mHandler.obtainMessage(EVENT_PROMPT_UNVALIDATED, nai.network),
PROMPT_UNVALIDATED_DELAY_MS);
}
private void handlePromptUnvalidated(Network network) {
- if (DBG) log("handlePromptUnvalidated " + network);
+ if (VDBG) log("handlePromptUnvalidated " + network);
NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
// Only prompt if the network is unvalidated and was explicitly selected by the user, and if
@@ -2486,11 +2482,14 @@
break;
}
}
- if (msg.what == EVENT_EXPIRE_NET_TRANSITION_WAKELOCK) {
- log("Failed to find a new network - expiring NetTransition Wakelock");
- } else {
- log("NetTransition Wakelock (" + (causedBy == null ? "unknown" : causedBy) +
- " cleared because we found a replacement network");
+ if (VDBG) {
+ if (msg.what == EVENT_EXPIRE_NET_TRANSITION_WAKELOCK) {
+ log("Failed to find a new network - expiring NetTransition Wakelock");
+ } else {
+ log("NetTransition Wakelock (" +
+ (causedBy == null ? "unknown" : causedBy) +
+ " cleared because we found a replacement network");
+ }
}
break;
}
@@ -3344,10 +3343,6 @@
private static enum NotificationType { SIGN_IN, NO_INTERNET; };
private void setProvNotificationVisible(boolean visible, int networkType, String action) {
- if (DBG) {
- log("setProvNotificationVisible: E visible=" + visible + " networkType=" + networkType
- + " action=" + action);
- }
Intent intent = new Intent(action);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
// Concatenate the range of types onto the range of NetIDs.
@@ -3374,7 +3369,7 @@
private void setProvNotificationVisibleIntent(boolean visible, int id,
NotificationType notifyType, int networkType, String extraInfo, PendingIntent intent,
boolean highPriority) {
- if (DBG) {
+ if (VDBG || (DBG && visible)) {
log("setProvNotificationVisibleIntent " + notifyType + " visible=" + visible
+ " networkType=" + getNetworkTypeName(networkType)
+ " extraInfo=" + extraInfo + " highPriority=" + highPriority);
@@ -3817,8 +3812,7 @@
Bundle thresholds = new Bundle();
thresholds.putIntegerArrayList("thresholds", thresholdsArray);
- // TODO: Switch to VDBG.
- if (DBG) {
+ if (VDBG || (DBG && !"CONNECT".equals(reason))) {
String detail;
if (request != null && request.networkCapabilities.hasSignalStrength()) {
detail = reason + " " + request.networkCapabilities.getSignalStrength();
@@ -3983,7 +3977,7 @@
new NetworkCapabilities(networkCapabilities), TYPE_NONE, nextNetworkRequestId());
NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
NetworkRequestType.LISTEN);
- if (DBG) log("listenForNetwork for " + nri);
+ if (VDBG) log("listenForNetwork for " + nri);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
return networkRequest;
@@ -4001,7 +3995,7 @@
new NetworkCapabilities(networkCapabilities), TYPE_NONE, nextNetworkRequestId());
NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation,
NetworkRequestType.LISTEN);
- if (DBG) log("pendingListenForNetwork for " + nri);
+ if (VDBG) log("pendingListenForNetwork for " + nri);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
}
@@ -4206,7 +4200,7 @@
// do this twice, adding non-nexthop routes first, then routes they are dependent on
for (RouteInfo route : routeDiff.added) {
if (route.hasGateway()) continue;
- if (DBG) log("Adding Route [" + route + "] to network " + netId);
+ if (VDBG) log("Adding Route [" + route + "] to network " + netId);
try {
mNetd.addRoute(netId, route);
} catch (Exception e) {
@@ -4217,7 +4211,7 @@
}
for (RouteInfo route : routeDiff.added) {
if (route.hasGateway() == false) continue;
- if (DBG) log("Adding Route [" + route + "] to network " + netId);
+ if (VDBG) log("Adding Route [" + route + "] to network " + netId);
try {
mNetd.addRoute(netId, route);
} catch (Exception e) {
@@ -4228,7 +4222,7 @@
}
for (RouteInfo route : routeDiff.removed) {
- if (DBG) log("Removing Route [" + route + "] from network " + netId);
+ if (VDBG) log("Removing Route [" + route + "] from network " + netId);
try {
mNetd.removeRoute(netId, route);
} catch (Exception e) {
@@ -4244,7 +4238,7 @@
}
Collection<InetAddress> dnses = newLp.getDnsServers();
- if (DBG) log("Setting Dns servers for network " + netId + " to " + dnses);
+ if (DBG) log("Setting DNS servers for network " + netId + " to " + dnses);
try {
mNetd.setDnsServersForNetwork(
netId, NetworkUtils.makeStrings(dnses), newLp.getDomains());
@@ -4512,14 +4506,14 @@
}
if (currentNetwork == null ||
currentNetwork.getCurrentScore() < newNetwork.getCurrentScore()) {
- if (DBG) log("rematch for " + newNetwork.name());
+ if (VDBG) log("rematch for " + newNetwork.name());
if (currentNetwork != null) {
- if (DBG) log(" accepting network in place of " + currentNetwork.name());
+ if (VDBG) log(" accepting network in place of " + currentNetwork.name());
currentNetwork.networkRequests.remove(nri.request.requestId);
currentNetwork.networkLingered.add(nri.request);
affectedNetworks.add(currentNetwork);
} else {
- if (DBG) log(" accepting network in place of null");
+ if (VDBG) log(" accepting network in place of null");
}
unlinger(newNetwork);
mNetworkForRequestId.put(nri.request.requestId, newNetwork);
@@ -4849,7 +4843,7 @@
}
private void updateNetworkScore(NetworkAgentInfo nai, int score) {
- if (DBG) log("updateNetworkScore for " + nai.name() + " to " + score);
+ if (VDBG) log("updateNetworkScore for " + nai.name() + " to " + score);
if (score < 0) {
loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score +
"). Bumping score to min of 0");
@@ -4927,7 +4921,7 @@
}
protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) {
- if (DBG) log("notifyType " + notifyTypeToName(notifyType) + " for " + networkAgent.name());
+ if (VDBG) log("notifyType " + notifyTypeToName(notifyType) + " for " + networkAgent.name());
for (int i = 0; i < networkAgent.networkRequests.size(); i++) {
NetworkRequest nr = networkAgent.networkRequests.valueAt(i);
NetworkRequestInfo nri = mNetworkRequests.get(nr);
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 423f945..6a08191 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -39,7 +39,9 @@
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
+import android.net.ConnectivityManager;
import android.net.INetworkPolicyManager;
+import android.net.NetworkInfo;
import android.net.Uri;
import android.os.BatteryStats;
import android.os.Binder;
@@ -114,6 +116,7 @@
private IBatteryStats mBatteryStats;
private PowerManagerInternal mLocalPowerManager;
private PowerManager mPowerManager;
+ private ConnectivityService mConnectivityService;
private AlarmManagerService.LocalService mLocalAlarmManager;
private INetworkPolicyManager mNetworkPolicyManager;
private DisplayManager mDisplayManager;
@@ -128,6 +131,7 @@
private boolean mLightEnabled;
private boolean mDeepEnabled;
private boolean mForceIdle;
+ private boolean mNetworkConnected;
private boolean mScreenOn;
private boolean mCharging;
private boolean mNotMoving;
@@ -173,16 +177,20 @@
private static final int LIGHT_STATE_PRE_IDLE = 3;
/** Device is in the light idle state, trying to stay asleep as much as possible. */
private static final int LIGHT_STATE_IDLE = 4;
+ /** Device is in the light idle state, we want to go in to idle maintenance but are
+ * waiting for network connectivity before doing so. */
+ private static final int LIGHT_STATE_WAITING_FOR_NETWORK = 5;
/** Device is in the light idle state, but temporarily out of idle to do regular maintenance. */
- private static final int LIGHT_STATE_IDLE_MAINTENANCE = 5;
+ private static final int LIGHT_STATE_IDLE_MAINTENANCE = 6;
/** Device light idle state is overriden, now applying deep doze state. */
- private static final int LIGHT_STATE_OVERRIDE = 6;
+ private static final int LIGHT_STATE_OVERRIDE = 7;
private static String lightStateToString(int state) {
switch (state) {
case LIGHT_STATE_ACTIVE: return "ACTIVE";
case LIGHT_STATE_INACTIVE: return "INACTIVE";
case LIGHT_STATE_PRE_IDLE: return "PRE_IDLE";
case LIGHT_STATE_IDLE: return "IDLE";
+ case LIGHT_STATE_WAITING_FOR_NETWORK: return "WAITING_FOR_NETWORK";
case LIGHT_STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
case LIGHT_STATE_OVERRIDE: return "OVERRIDE";
default: return Integer.toString(state);
@@ -198,6 +206,7 @@
private long mNextIdleDelay;
private long mNextLightIdleDelay;
private long mNextLightAlarmTime;
+ private long mNextSensingTimeoutAlarmTime;
private long mCurIdleBudget;
private long mMaintenanceStartTime;
@@ -314,17 +323,27 @@
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
- if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
- int plugged = intent.getIntExtra("plugged", 0);
- updateChargingLocked(plugged != 0);
- } else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
- if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
- Uri data = intent.getData();
- String ssp;
- if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
- removePowerSaveWhitelistAppInternal(ssp);
+ switch (intent.getAction()) {
+ case ConnectivityManager.CONNECTIVITY_ACTION: {
+ synchronized (DeviceIdleController.this) {
+ updateConnectivityStateLocked(intent);
}
- }
+ } break;
+ case Intent.ACTION_BATTERY_CHANGED: {
+ synchronized (DeviceIdleController.this) {
+ int plugged = intent.getIntExtra("plugged", 0);
+ updateChargingLocked(plugged != 0);
+ }
+ } break;
+ case Intent.ACTION_PACKAGE_REMOVED: {
+ if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+ Uri data = intent.getData();
+ String ssp;
+ if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
+ removePowerSaveWhitelistAppInternal(ssp);
+ }
+ }
+ } break;
}
}
};
@@ -339,6 +358,18 @@
}
};
+ private final AlarmManager.OnAlarmListener mSensingTimeoutAlarmListener
+ = new AlarmManager.OnAlarmListener() {
+ @Override
+ public void onAlarm() {
+ if (mState == STATE_SENSING) {
+ synchronized (DeviceIdleController.this) {
+ becomeInactiveIfAppropriateLocked();
+ }
+ }
+ }
+ };
+
private final AlarmManager.OnAlarmListener mDeepAlarmListener
= new AlarmManager.OnAlarmListener() {
@Override
@@ -924,6 +955,11 @@
@Override
public void onAnyMotionResult(int result) {
if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
+ if (result != AnyMotionDetector.RESULT_UNKNOWN) {
+ synchronized (this) {
+ cancelSensingTimeoutAlarmLocked();
+ }
+ }
if (result == AnyMotionDetector.RESULT_MOVED) {
if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
synchronized (this) {
@@ -1300,6 +1336,7 @@
readConfigFileLocked();
updateWhitelistAppIdsLocked();
+ mNetworkConnected = true;
mScreenOn = true;
// Start out assuming we are charging. If we aren't, we will at least get
// a battery update the next time the level drops.
@@ -1325,6 +1362,8 @@
mActiveIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"deviceidle_maint");
mActiveIdleWakeLock.setReferenceCounted(false);
+ mConnectivityService = (ConnectivityService)ServiceManager.getService(
+ Context.CONNECTIVITY_SERVICE);
mLocalAlarmManager = getLocalService(AlarmManagerService.LocalService.class);
mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
@@ -1377,11 +1416,14 @@
filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
+ filter = new IntentFilter();
+ filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
getContext().registerReceiver(mReceiver, filter);
mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray);
mDisplayManager.registerDisplayListener(mDisplayListener, null);
+ updateConnectivityStateLocked(null);
updateDisplayLocked();
}
}
@@ -1662,6 +1704,35 @@
}
}
+ void updateConnectivityStateLocked(Intent connIntent) {
+ if (mConnectivityService != null) {
+ NetworkInfo ni = mConnectivityService.getActiveNetworkInfo();
+ boolean conn;
+ if (ni == null) {
+ conn = false;
+ } else {
+ if (connIntent == null) {
+ conn = ni.isConnected();
+ } else {
+ final int networkType =
+ connIntent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,
+ ConnectivityManager.TYPE_NONE);
+ if (ni.getType() != networkType) {
+ return;
+ }
+ conn = !connIntent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,
+ false);
+ }
+ }
+ if (conn != mNetworkConnected) {
+ mNetworkConnected = conn;
+ if (conn && mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {
+ stepLightIdleStateLocked("network");
+ }
+ }
+ }
+ }
+
void updateDisplayLocked() {
mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
// We consider any situation where the display is showing something to be it on,
@@ -1746,6 +1817,7 @@
mNextIdleDelay = 0;
mNextLightIdleDelay = 0;
cancelAlarmLocked();
+ cancelSensingTimeoutAlarmLocked();
cancelLocatingLocked();
stopMonitoringMotionLocked();
mAnyMotionDetector.stop();
@@ -1759,7 +1831,7 @@
if (mForceIdle) {
mForceIdle = false;
if (mScreenOn || mCharging) {
- becomeActiveLocked("exit-force-idle", Process.myUid());
+ becomeActiveLocked("exit-force", Process.myUid());
}
}
}
@@ -1815,22 +1887,33 @@
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);
break;
case LIGHT_STATE_IDLE:
- // We have been idling long enough, now it is time to do some work.
- mActiveIdleOpCount = 1;
- mActiveIdleWakeLock.acquire();
- mMaintenanceStartTime = SystemClock.elapsedRealtime();
- if (mCurIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
- mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
- } else if (mCurIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) {
- mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
+ case LIGHT_STATE_WAITING_FOR_NETWORK:
+ if (mNetworkConnected || mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {
+ // We have been idling long enough, now it is time to do some work.
+ mActiveIdleOpCount = 1;
+ mActiveIdleWakeLock.acquire();
+ mMaintenanceStartTime = SystemClock.elapsedRealtime();
+ if (mCurIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
+ mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
+ } else if (mCurIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) {
+ mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
+ }
+ scheduleLightAlarmLocked(mCurIdleBudget);
+ if (DEBUG) Slog.d(TAG,
+ "Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE.");
+ mLightState = LIGHT_STATE_IDLE_MAINTENANCE;
+ EventLogTags.writeDeviceIdleLight(mLightState, reason);
+ addEvent(EVENT_LIGHT_MAINTENANCE);
+ mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
+ } else {
+ // We'd like to do maintenance, but currently don't have network
+ // connectivity... let's try to wait until the network comes back.
+ // We'll only wait for another full idle period, however, and then give up.
+ scheduleLightAlarmLocked(mNextLightIdleDelay);
+ if (DEBUG) Slog.d(TAG, "Moved to LIGHT_WAITING_FOR_NETWORK.");
+ mLightState = LIGHT_STATE_WAITING_FOR_NETWORK;
+ EventLogTags.writeDeviceIdleLight(mLightState, reason);
}
- scheduleLightAlarmLocked(mCurIdleBudget);
- if (DEBUG) Slog.d(TAG,
- "Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE.");
- mLightState = LIGHT_STATE_IDLE_MAINTENANCE;
- EventLogTags.writeDeviceIdleLight(mLightState, reason);
- addEvent(EVENT_LIGHT_MAINTENANCE);
- mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
break;
}
}
@@ -1866,15 +1949,16 @@
mState = STATE_SENSING;
if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
EventLogTags.writeDeviceIdle(mState, reason);
- scheduleAlarmLocked(mConstants.SENSING_TIMEOUT, false);
+ scheduleSensingTimeoutAlarmLocked(mConstants.SENSING_TIMEOUT);
cancelLocatingLocked();
- mAnyMotionDetector.checkForAnyMotion();
mNotMoving = false;
mLocated = false;
mLastGenericLocation = null;
mLastGpsLocation = null;
+ mAnyMotionDetector.checkForAnyMotion();
break;
case STATE_SENSING:
+ cancelSensingTimeoutAlarmLocked();
mState = STATE_LOCATING;
if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
EventLogTags.writeDeviceIdle(mState, reason);
@@ -2161,6 +2245,13 @@
}
}
+ void cancelSensingTimeoutAlarmLocked() {
+ if (mNextSensingTimeoutAlarmTime != 0) {
+ mNextSensingTimeoutAlarmTime = 0;
+ mAlarmManager.cancel(mSensingTimeoutAlarmListener);
+ }
+ }
+
void scheduleAlarmLocked(long delay, boolean idleUntil) {
if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
if (mMotionSensor == null) {
@@ -2182,18 +2273,18 @@
void scheduleLightAlarmLocked(long delay) {
if (DEBUG) Slog.d(TAG, "scheduleLightAlarmLocked(" + delay + ")");
- if (mMotionSensor == null) {
- // If there is no motion sensor on this device, then we won't schedule
- // alarms, because we can't determine if the device is not moving. This effectively
- // turns off normal execution of device idling, although it is still possible to
- // manually poke it by pretending like the alarm is going off.
- return;
- }
mNextLightAlarmTime = SystemClock.elapsedRealtime() + delay;
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
mNextLightAlarmTime, "DeviceIdleController.light", mLightAlarmListener, mHandler);
}
+ void scheduleSensingTimeoutAlarmLocked(long delay) {
+ if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
+ mNextSensingTimeoutAlarmTime = SystemClock.elapsedRealtime() + delay;
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mNextSensingTimeoutAlarmTime,
+ "DeviceIdleController.sensing", mSensingTimeoutAlarmListener, mHandler);
+ }
+
private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
outAppIds.clear();
@@ -2396,9 +2487,14 @@
pw.println(" Print this help text.");
pw.println(" step [light|deep]");
pw.println(" Immediately step to next state, without waiting for alarm.");
- pw.println(" force-idle");
+ pw.println(" force-idle [light|deep]");
pw.println(" Force directly into idle mode, regardless of other device state.");
- pw.println(" Use \"step\" to get out.");
+ pw.println(" force-inactive");
+ pw.println(" Force to be inactive, ready to freely step idle states.");
+ pw.println(" unforce");
+ pw.println(" Resume normal functioning after force-idle or force-inactive.");
+ pw.println(" get [light|deep|force|screen|charging|network]");
+ pw.println(" Retrieve the current given state.");
pw.println(" disable [light|deep|all]");
pw.println(" Completely disable device idle mode.");
pw.println(" enable [light|deep|all]");
@@ -2438,12 +2534,10 @@
String arg = shell.getNextArg();
try {
if (arg == null || "deep".equals(arg)) {
- exitForceIdleLocked();
stepIdleStateLocked("s:shell");
pw.print("Stepped to deep: ");
pw.println(stateToString(mState));
} else if ("light".equals(arg)) {
- exitForceIdleLocked();
stepLightIdleStateLocked("s:shell");
pw.print("Stepped to light: "); pw.println(lightStateToString(mLightState));
} else {
@@ -2458,29 +2552,104 @@
null);
synchronized (this) {
long token = Binder.clearCallingIdentity();
+ String arg = shell.getNextArg();
try {
- if (!mDeepEnabled) {
- pw.println("Unable to go idle; not enabled");
- return -1;
- }
- mForceIdle = true;
- becomeInactiveIfAppropriateLocked();
- int curState = mState;
- while (curState != STATE_IDLE) {
- stepIdleStateLocked("s:shell");
- if (curState == mState) {
- pw.print("Unable to go idle; stopped at ");
- pw.println(stateToString(mState));
- exitForceIdleLocked();
+ if (arg == null || "deep".equals(arg)) {
+ if (!mDeepEnabled) {
+ pw.println("Unable to go deep idle; not enabled");
return -1;
}
- curState = mState;
+ mForceIdle = true;
+ becomeInactiveIfAppropriateLocked();
+ int curState = mState;
+ while (curState != STATE_IDLE) {
+ stepIdleStateLocked("s:shell");
+ if (curState == mState) {
+ pw.print("Unable to go deep idle; stopped at ");
+ pw.println(stateToString(mState));
+ exitForceIdleLocked();
+ return -1;
+ }
+ curState = mState;
+ }
+ pw.println("Now forced in to deep idle mode");
+ } else if ("light".equals(arg)) {
+ mForceIdle = true;
+ becomeInactiveIfAppropriateLocked();
+ int curLightState = mLightState;
+ while (curLightState != LIGHT_STATE_IDLE) {
+ stepIdleStateLocked("s:shell");
+ if (curLightState == mLightState) {
+ pw.print("Unable to go light idle; stopped at ");
+ pw.println(lightStateToString(mLightState));
+ exitForceIdleLocked();
+ return -1;
+ }
+ curLightState = mLightState;
+ }
+ pw.println("Now forced in to light idle mode");
+ } else {
+ pw.println("Unknown idle mode: " + arg);
}
- pw.println("Now forced in to idle mode");
} finally {
Binder.restoreCallingIdentity(token);
}
}
+ } else if ("force-inactive".equals(cmd)) {
+ getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
+ null);
+ synchronized (this) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mForceIdle = true;
+ becomeInactiveIfAppropriateLocked();
+ pw.print("Light state: ");
+ pw.print(lightStateToString(mLightState));
+ pw.print(", deep state: ");
+ pw.println(stateToString(mState));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ } else if ("unforce".equals(cmd)) {
+ getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
+ null);
+ synchronized (this) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ exitForceIdleLocked();
+ pw.print("Light state: ");
+ pw.print(lightStateToString(mLightState));
+ pw.print(", deep state: ");
+ pw.println(stateToString(mState));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ } else if ("get".equals(cmd)) {
+ getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
+ null);
+ synchronized (this) {
+ String arg = shell.getNextArg();
+ if (arg != null) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ switch (arg) {
+ case "light": pw.println(lightStateToString(mLightState)); break;
+ case "deep": pw.println(stateToString(mState)); break;
+ case "force": pw.println(mForceIdle); break;
+ case "screen": pw.println(mScreenOn); break;
+ case "charging": pw.println(mCharging); break;
+ case "network": pw.println(mNetworkConnected); break;
+ default: pw.println("Unknown get option: " + arg); break;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ } else {
+ pw.println("Argument required");
+ }
+ }
} else if ("disable".equals(cmd)) {
getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
null);
@@ -2795,6 +2964,7 @@
pw.print(" mMotionSensor="); pw.println(mMotionSensor);
pw.print(" mCurDisplay="); pw.println(mCurDisplay);
pw.print(" mScreenOn="); pw.println(mScreenOn);
+ pw.print(" mNetworkConnected="); pw.println(mNetworkConnected);
pw.print(" mCharging="); pw.println(mCharging);
pw.print(" mMotionActive="); pw.println(mMotionListener.active);
pw.print(" mNotMoving="); pw.println(mNotMoving);
diff --git a/services/core/java/com/android/server/DisplayThread.java b/services/core/java/com/android/server/DisplayThread.java
index aa0a805..9ef0259 100644
--- a/services/core/java/com/android/server/DisplayThread.java
+++ b/services/core/java/com/android/server/DisplayThread.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.os.Handler;
+import android.os.Trace;
/**
* Shared singleton foreground thread for the system. This is a thread for
@@ -36,6 +37,7 @@
if (sInstance == null) {
sInstance = new DisplayThread();
sInstance.start();
+ sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
sHandler = new Handler(sInstance.getLooper());
}
}
diff --git a/services/core/java/com/android/server/FgThread.java b/services/core/java/com/android/server/FgThread.java
index 03765db..5f85cba 100644
--- a/services/core/java/com/android/server/FgThread.java
+++ b/services/core/java/com/android/server/FgThread.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.os.Handler;
+import android.os.Trace;
/**
* Shared singleton foreground thread for the system. This is a thread for regular
@@ -38,6 +39,7 @@
if (sInstance == null) {
sInstance = new FgThread();
sInstance.start();
+ sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
sHandler = new Handler(sInstance.getLooper());
}
}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index ac7872a..22cc066 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -66,7 +66,6 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -1050,12 +1049,8 @@
}
void updateCurrentProfileIds() {
- 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;
- }
- mSettings.setCurrentProfileIds(currentProfileIds);
+ mSettings.setCurrentProfileIds(
+ mUserManager.getProfileIdsWithDisabled(mSettings.getCurrentUserId()));
}
@Override
@@ -2546,7 +2541,8 @@
return false;
}
final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
- onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype);
+ onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype,
+ true /* forward */);
if (nextSubtype == null) {
return false;
}
@@ -2569,7 +2565,8 @@
return false;
}
final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
- false /* onlyCurrentIme */, mMethodMap.get(mCurMethodId), mCurrentSubtype);
+ false /* onlyCurrentIme */, mMethodMap.get(mCurMethodId), mCurrentSubtype,
+ true /* forward */);
if (nextSubtype == null) {
return false;
}
@@ -2963,9 +2960,8 @@
private void handleSwitchInputMethod(final boolean forwardDirection) {
synchronized (mMethodMap) {
- // TODO: Support forwardDirection.
final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
- false, mMethodMap.get(mCurMethodId), mCurrentSubtype);
+ false, mMethodMap.get(mCurMethodId), mCurrentSubtype, forwardDirection);
if (nextSubtype == null) {
return;
}
@@ -3648,6 +3644,7 @@
private static final String ATTR_ID = "id";
private static final String ATTR_LABEL = "label";
private static final String ATTR_ICON = "icon";
+ private static final String ATTR_IME_SUBTYPE_ID = "subtypeId";
private static final String ATTR_IME_SUBTYPE_LOCALE = "imeSubtypeLocale";
private static final String ATTR_IME_SUBTYPE_LANGUAGE_TAG = "languageTag";
private static final String ATTR_IME_SUBTYPE_MODE = "imeSubtypeMode";
@@ -3741,6 +3738,10 @@
for (int i = 0; i < N; ++i) {
final InputMethodSubtype subtype = subtypesList.get(i);
out.startTag(null, NODE_SUBTYPE);
+ if (subtype.hasSubtypeId()) {
+ out.attribute(null, ATTR_IME_SUBTYPE_ID,
+ String.valueOf(subtype.getSubtypeId()));
+ }
out.attribute(null, ATTR_ICON, String.valueOf(subtype.getIconResId()));
out.attribute(null, ATTR_LABEL, String.valueOf(subtype.getNameResId()));
out.attribute(null, ATTR_IME_SUBTYPE_LOCALE, subtype.getLocale());
@@ -3819,7 +3820,7 @@
parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
final boolean isAsciiCapable = "1".equals(String.valueOf(
parser.getAttributeValue(null, ATTR_IS_ASCII_CAPABLE)));
- final InputMethodSubtype subtype = new InputMethodSubtypeBuilder()
+ final InputMethodSubtypeBuilder builder = new InputMethodSubtypeBuilder()
.setSubtypeNameResId(label)
.setSubtypeIconResId(icon)
.setSubtypeLocale(imeSubtypeLocale)
@@ -3827,9 +3828,13 @@
.setSubtypeMode(imeSubtypeMode)
.setSubtypeExtraValue(imeSubtypeExtraValue)
.setIsAuxiliary(isAuxiliary)
- .setIsAsciiCapable(isAsciiCapable)
- .build();
- tempSubtypesArray.add(subtype);
+ .setIsAsciiCapable(isAsciiCapable);
+ final String subtypeIdString =
+ parser.getAttributeValue(null, ATTR_IME_SUBTYPE_ID);
+ if (subtypeIdString != null) {
+ builder.setSubtypeId(Integer.valueOf(subtypeIdString));
+ }
+ tempSubtypesArray.add(builder.build());
}
}
} catch (XmlPullParserException | IOException | NumberFormatException e) {
diff --git a/services/core/java/com/android/server/IoThread.java b/services/core/java/com/android/server/IoThread.java
index 0f29857..ad4c194 100644
--- a/services/core/java/com/android/server/IoThread.java
+++ b/services/core/java/com/android/server/IoThread.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.os.Handler;
+import android.os.Trace;
/**
* Shared singleton I/O thread for the system. This is a thread for non-background
@@ -35,6 +36,7 @@
if (sInstance == null) {
sInstance = new IoThread();
sInstance.start();
+ sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
sHandler = new Handler(sInstance.getLooper());
}
}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 9884a70..7c48634 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -21,6 +21,7 @@
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.ArrayUtils;
import com.android.server.location.ActivityRecognitionProxy;
import com.android.server.location.FlpHardwareProvider;
import com.android.server.location.FusedProxy;
@@ -53,7 +54,6 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
-import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.location.ActivityRecognitionHardware;
@@ -359,12 +359,9 @@
* @param currentUserId the current user, who might have an alter-ego.
*/
void updateUserProfiles(int currentUserId) {
- List<UserInfo> profiles = mUserManager.getProfiles(currentUserId);
+ int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId);
synchronized (mLock) {
- mCurrentUserProfiles = new int[profiles.size()];
- for (int i = 0; i < mCurrentUserProfiles.length; i++) {
- mCurrentUserProfiles[i] = profiles.get(i).id;
- }
+ mCurrentUserProfiles = profileIds;
}
}
@@ -374,12 +371,7 @@
*/
private boolean isCurrentProfile(int userId) {
synchronized (mLock) {
- for (int i = 0; i < mCurrentUserProfiles.length; i++) {
- if (mCurrentUserProfiles[i] == userId) {
- return true;
- }
- }
- return false;
+ return ArrayUtils.contains(mCurrentUserProfiles, userId);
}
}
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index ab0f55e..4ac75ca 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -56,6 +56,9 @@
import android.provider.Settings.Secure;
import android.provider.Settings.SettingNotFoundException;
import android.security.KeyStore;
+import android.security.keystore.AndroidKeyStoreProvider;
+import android.security.keystore.KeyProperties;
+import android.security.keystore.KeyProtection;
import android.service.gatekeeper.GateKeeperResponse;
import android.service.gatekeeper.IGateKeeperService;
import android.text.TextUtils;
@@ -68,15 +71,33 @@
import com.android.internal.widget.VerifyCredentialResponse;
import com.android.server.LockSettingsStorage.CredentialHash;
+import libcore.util.HexEncoding;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+
/**
* Keeps the lock pattern/password data and related settings for each user.
* Used by LockPatternUtils. Needs to be a service because Settings app also needs
@@ -90,6 +111,12 @@
private static final int FBE_ENCRYPTED_NOTIFICATION = 0;
private static final boolean DEBUG = false;
+ private static final String PROFILE_KEY_NAME_ENCRYPT = "profile_key_name_encrypt_";
+ private static final String PROFILE_KEY_NAME_DECRYPT = "profile_key_name_decrypt_";
+ private static final int PROFILE_KEY_IV_SIZE = 12;
+ private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
+ private final Object mSeparateChallengeLock = new Object();
+
private final Context mContext;
private final LockSettingsStorage mStorage;
private final LockSettingsStrongAuth mStrongAuth;
@@ -125,6 +152,7 @@
@Override
public void onStart() {
+ AndroidKeyStoreProvider.install();
mLockSettingsService = new LockSettingsService(getContext());
publishBinderService("lock_settings", mLockSettingsService);
}
@@ -149,6 +177,46 @@
}
}
+ /**
+ * Tie managed profile to primary profile if it is in unified mode and not tied before.
+ *
+ * @param managedUserId Managed profile user Id
+ * @param managedUserPassword Managed profile original password (when it has separated lock).
+ * NULL when it does not have a separated lock before.
+ */
+ public void tieManagedProfileLockIfNecessary(int managedUserId, String managedUserPassword) {
+ if (DEBUG) Slog.v(TAG, "Check child profile lock for user: " + managedUserId);
+ // Only for managed profile
+ if (!UserManager.get(mContext).getUserInfo(managedUserId).isManagedProfile()) {
+ return;
+ }
+ // Do not tie managed profile when work challenge is enabled
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
+ return;
+ }
+ // Do not tie managed profile to parent when it's done already
+ if (mStorage.hasChildProfileLock(managedUserId)) {
+ return;
+ }
+ // Do not tie it to parent when parent does not have a screen lock
+ final int parentId = mUserManager.getProfileParent(managedUserId).id;
+ if (!mStorage.hasPassword(parentId) && !mStorage.hasPattern(parentId)) {
+ if (DEBUG) Slog.v(TAG, "Parent does not have a screen lock");
+ return;
+ }
+ if (DEBUG) Slog.v(TAG, "Tie managed profile to parent now!");
+ byte[] randomLockSeed = new byte[] {};
+ try {
+ randomLockSeed = SecureRandom.getInstance("SHA1PRNG").generateSeed(40);
+ String newPassword = String.valueOf(HexEncoding.encode(randomLockSeed));
+ setLockPasswordInternal(newPassword, managedUserPassword, managedUserId);
+ tieProfileLockToParent(managedUserId, newPassword);
+ } catch (NoSuchAlgorithmException | RemoteException e) {
+ Slog.e(TAG, "Fail to tie managed profile", e);
+ // Nothing client can do to fix this issue, so we do not throw exception out
+ }
+ }
+
public LockSettingsService(Context context) {
mContext = context;
mStrongAuth = new LockSettingsStrongAuth(context);
@@ -271,6 +339,7 @@
}
public void onUnlockUser(int userId) {
+ tieManagedProfileLockIfNecessary(userId, null);
hideEncryptionNotification(new UserHandle(userId));
// Now we have unlocked the parent user we should show notifications
@@ -294,8 +363,7 @@
// Notify keystore that a new user was added.
final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
final KeyStore ks = KeyStore.getInstance();
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
- final UserInfo parentInfo = um.getProfileParent(userHandle);
+ final UserInfo parentInfo = mUserManager.getProfileParent(userHandle);
final int parentHandle = parentInfo != null ? parentInfo.id : -1;
ks.onUserAdded(userHandle, parentHandle);
} else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
@@ -343,9 +411,8 @@
// These Settings changed after multi-user was enabled, hence need to be moved per user.
if (getString("migrated_user_specific", null, 0) == null) {
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
final ContentResolver cr = mContext.getContentResolver();
- List<UserInfo> users = um.getUsers();
+ List<UserInfo> users = mUserManager.getUsers();
for (int user = 0; user < users.size(); user++) {
// Migrate owner info
final int userId = users.get(user).id;
@@ -380,8 +447,7 @@
// Migrates biometric weak such that the fallback mechanism becomes the primary.
if (getString("migrated_biometric_weak", null, 0) == null) {
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
- List<UserInfo> users = um.getUsers();
+ List<UserInfo> users = mUserManager.getUsers();
for (int i = 0; i < users.size(); i++) {
int userId = users.get(i).id;
long type = getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
@@ -407,9 +473,7 @@
// user was present on the system, so if we're upgrading to M and there is more than one
// user we disable the flag to remain consistent.
if (getString("migrated_lockscreen_disabled", null, 0) == null) {
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
-
- final List<UserInfo> users = um.getUsers();
+ final List<UserInfo> users = mUserManager.getUsers();
final int userCount = users.size();
int switchableUsers = 0;
for (int i = 0; i < userCount; i++) {
@@ -469,6 +533,27 @@
}
@Override
+ public boolean getSeparateProfileChallengeEnabled(int userId) throws RemoteException {
+ synchronized (mSeparateChallengeLock) {
+ return getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userId);
+ }
+ }
+
+ @Override
+ public void setSeparateProfileChallengeEnabled(int userId, boolean enabled,
+ String managedUserPassword) throws RemoteException {
+ synchronized (mSeparateChallengeLock) {
+ setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userId);
+ if (enabled) {
+ mStorage.removeChildProfileLock(userId);
+ removeKeystoreProfileKey(userId);
+ } else {
+ tieManagedProfileLockIfNecessary(userId, managedUserPassword);
+ }
+ }
+ }
+
+ @Override
public void setBoolean(String key, boolean value, int userId) throws RemoteException {
checkWritePermission(userId);
setStringUnchecked(key, userId, value ? "1" : "0");
@@ -536,61 +621,65 @@
@Override
public boolean havePassword(int userId) throws RemoteException {
// Do we need a permissions check here?
-
return mStorage.hasPassword(userId);
}
@Override
public boolean havePattern(int userId) throws RemoteException {
// Do we need a permissions check here?
-
return mStorage.hasPattern(userId);
}
private void setKeystorePassword(String password, int userHandle) {
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
final KeyStore ks = KeyStore.getInstance();
-
- 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);
- }
- }
- }
+ ks.onUserPasswordChanged(userHandle, password);
}
private void unlockKeystore(String password, int userHandle) {
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
+ if (DEBUG) Slog.v(TAG, "Unlock keystore for user: " + userHandle);
final KeyStore ks = KeyStore.getInstance();
+ ks.unlock(userHandle, password);
+ }
- if (um.getUserInfo(userHandle).isManagedProfile()) {
- if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) {
- ks.unlock(userHandle, password);
+ private String getDecryptedPasswordForTiedProfile(int userId)
+ throws KeyStoreException, UnrecoverableKeyException,
+ NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
+ InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException,
+ CertificateException, IOException {
+ if (DEBUG) Slog.v(TAG, "Unlock keystore for child profile");
+ byte[] storedData = mStorage.readChildProfileLock(userId);
+ if (storedData == null) {
+ throw new FileNotFoundException("Child profile lock file not found");
+ }
+ byte[] iv = Arrays.copyOfRange(storedData, 0, PROFILE_KEY_IV_SIZE);
+ byte[] encryptedPassword = Arrays.copyOfRange(storedData, PROFILE_KEY_IV_SIZE,
+ storedData.length);
+ byte[] decryptionResult;
+ java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
+ keyStore.load(null);
+ SecretKey decryptionKey = (SecretKey) keyStore.getKey(
+ PROFILE_KEY_NAME_DECRYPT + userId, null);
+
+ Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
+ + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE);
+
+ cipher.init(Cipher.DECRYPT_MODE, decryptionKey, new GCMParameterSpec(128, iv));
+ decryptionResult = cipher.doFinal(encryptedPassword);
+ return new String(decryptionResult, StandardCharsets.UTF_8);
+ }
+
+ private void unlockChildProfile(int profileHandle) throws RemoteException {
+ try {
+ doVerifyPassword(getDecryptedPasswordForTiedProfile(profileHandle), false,
+ 0 /* no challenge */, profileHandle);
+ } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
+ | NoSuchAlgorithmException | NoSuchPaddingException
+ | InvalidAlgorithmParameterException | IllegalBlockSizeException
+ | BadPaddingException | CertificateException | IOException e) {
+ if (e instanceof FileNotFoundException) {
+ Slog.i(TAG, "Child profile key not found");
} 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);
- }
+ Slog.e(TAG, "Failed to decrypt child profile key", e);
}
}
}
@@ -627,6 +716,21 @@
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
+ try {
+ if (!mUserManager.getUserInfo(userId).isManagedProfile()) {
+ final List<UserInfo> profiles = mUserManager.getProfiles(userId);
+ for (UserInfo pi : profiles) {
+ // Unlock managed profile with unified lock
+ if (pi.isManagedProfile()
+ && !mLockPatternUtils.isSeparateProfileChallengeEnabled(pi.id)
+ && mStorage.hasChildProfileLock(pi.id)) {
+ unlockChildProfile(pi.id);
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ Log.d(TAG, "Failed to unlock child profile", e);
+ }
}
private byte[] getCurrentHandle(int userId) {
@@ -661,10 +765,57 @@
return currentHandle;
}
+ private void onUserLockChanged(int userId) throws RemoteException {
+ if (mUserManager.getUserInfo(userId).isManagedProfile()) {
+ return;
+ }
+ final boolean isSecure = mStorage.hasPassword(userId) || mStorage.hasPattern(userId);
+ final List<UserInfo> profiles = mUserManager.getProfiles(userId);
+ final int size = profiles.size();
+ for (int i = 0; i < size; i++) {
+ final UserInfo profile = profiles.get(i);
+ if (profile.isManagedProfile()) {
+ final int managedUserId = profile.id;
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(managedUserId)) {
+ continue;
+ }
+ if (isSecure) {
+ tieManagedProfileLockIfNecessary(managedUserId, null);
+ } else {
+ getGateKeeperService().clearSecureUserId(managedUserId);
+ mStorage.writePatternHash(null, managedUserId);
+ setKeystorePassword(null, managedUserId);
+ clearUserKeyProtection(managedUserId);
+ mStorage.removeChildProfileLock(managedUserId);
+ removeKeystoreProfileKey(managedUserId);
+ }
+ }
+ }
+ }
+ private boolean isManagedProfileWithUnifiedLock(int userId) {
+ return mUserManager.getUserInfo(userId).isManagedProfile()
+ && !mLockPatternUtils.isSeparateProfileChallengeEnabled(userId);
+ }
+
+ private boolean isManagedProfileWithSeparatedLock(int userId) {
+ return mUserManager.getUserInfo(userId).isManagedProfile()
+ && mLockPatternUtils.isSeparateProfileChallengeEnabled(userId);
+ }
+
+ // This method should be called by LockPatternUtil only, all internal methods in this class
+ // should call setLockPatternInternal.
@Override
public void setLockPattern(String pattern, String savedCredential, int userId)
throws RemoteException {
+ synchronized (mSeparateChallengeLock) {
+ setLockPatternInternal(pattern, savedCredential, userId);
+ setSeparateProfileChallengeEnabled(userId, true, null);
+ }
+ }
+
+ public void setLockPatternInternal(String pattern, String savedCredential, int userId)
+ throws RemoteException {
byte[] currentHandle = getCurrentHandle(userId);
if (pattern == null) {
@@ -672,55 +823,157 @@
mStorage.writePatternHash(null, userId);
setKeystorePassword(null, userId);
clearUserKeyProtection(userId);
+ onUserLockChanged(userId);
return;
}
- if (currentHandle == null) {
- if (savedCredential != null) {
- Slog.w(TAG, "Saved credential provided, but none stored");
+ if (isManagedProfileWithUnifiedLock(userId)) {
+ // get credential from keystore when managed profile has unified lock
+ try {
+ savedCredential = getDecryptedPasswordForTiedProfile(userId);
+ } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
+ | NoSuchAlgorithmException | NoSuchPaddingException
+ | InvalidAlgorithmParameterException | IllegalBlockSizeException
+ | BadPaddingException | CertificateException | IOException e) {
+ if (e instanceof FileNotFoundException) {
+ Slog.i(TAG, "Child profile key not found");
+ } else {
+ Slog.e(TAG, "Failed to decrypt child profile key", e);
+ }
}
- savedCredential = null;
+ } else {
+ if (currentHandle == null) {
+ if (savedCredential != null) {
+ Slog.w(TAG, "Saved credential provided, but none stored");
+ }
+ savedCredential = null;
+ }
}
byte[] enrolledHandle = enrollCredential(currentHandle, savedCredential, pattern, userId);
if (enrolledHandle != null) {
mStorage.writePatternHash(enrolledHandle, userId);
setUserKeyProtection(userId, pattern, verifyPattern(pattern, 0, userId));
+ onUserLockChanged(userId);
} else {
throw new RemoteException("Failed to enroll pattern");
}
}
-
+ // This method should be called by LockPatternUtil only, all internal methods in this class
+ // should call setLockPasswordInternal.
@Override
public void setLockPassword(String password, String savedCredential, int userId)
throws RemoteException {
- byte[] currentHandle = getCurrentHandle(userId);
+ synchronized (mSeparateChallengeLock) {
+ setLockPasswordInternal(password, savedCredential, userId);
+ setSeparateProfileChallengeEnabled(userId, true, null);
+ }
+ }
+ public void setLockPasswordInternal(String password, String savedCredential, int userId)
+ throws RemoteException {
+ byte[] currentHandle = getCurrentHandle(userId);
if (password == null) {
getGateKeeperService().clearSecureUserId(userId);
mStorage.writePasswordHash(null, userId);
setKeystorePassword(null, userId);
clearUserKeyProtection(userId);
+ onUserLockChanged(userId);
return;
}
- if (currentHandle == null) {
- if (savedCredential != null) {
- Slog.w(TAG, "Saved credential provided, but none stored");
+ if (isManagedProfileWithUnifiedLock(userId)) {
+ // get credential from keystore when managed profile has unified lock
+ try {
+ savedCredential = getDecryptedPasswordForTiedProfile(userId);
+ } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
+ | NoSuchAlgorithmException | NoSuchPaddingException
+ | InvalidAlgorithmParameterException | IllegalBlockSizeException
+ | BadPaddingException | CertificateException | IOException e) {
+ if (e instanceof FileNotFoundException) {
+ Slog.i(TAG, "Child profile key not found");
+ } else {
+ Slog.e(TAG, "Failed to decrypt child profile key", e);
+ }
}
- savedCredential = null;
+ } else {
+ if (currentHandle == null) {
+ if (savedCredential != null) {
+ Slog.w(TAG, "Saved credential provided, but none stored");
+ }
+ savedCredential = null;
+ }
}
byte[] enrolledHandle = enrollCredential(currentHandle, savedCredential, password, userId);
if (enrolledHandle != null) {
mStorage.writePasswordHash(enrolledHandle, userId);
setUserKeyProtection(userId, password, verifyPassword(password, 0, userId));
+ onUserLockChanged(userId);
} else {
throw new RemoteException("Failed to enroll password");
}
}
+ private void tieProfileLockToParent(int userId, String password) {
+ if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId);
+ byte[] randomLockSeed = password.getBytes(StandardCharsets.UTF_8);
+ byte[] encryptionResult;
+ byte[] iv;
+ try {
+ KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
+ keyGenerator.init(new SecureRandom());
+ SecretKey secretKey = keyGenerator.generateKey();
+
+ java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
+ keyStore.load(null);
+ keyStore.setEntry(
+ PROFILE_KEY_NAME_ENCRYPT + userId,
+ new java.security.KeyStore.SecretKeyEntry(secretKey),
+ new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
+ .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+ .build());
+ keyStore.setEntry(
+ PROFILE_KEY_NAME_DECRYPT + userId,
+ new java.security.KeyStore.SecretKeyEntry(secretKey),
+ new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
+ .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+ .setUserAuthenticationRequired(true)
+ .setUserAuthenticationValidityDurationSeconds(30)
+ .build());
+
+ // Key imported, obtain a reference to it.
+ SecretKey keyStoreEncryptionKey = (SecretKey) keyStore.getKey(
+ PROFILE_KEY_NAME_ENCRYPT + userId, null);
+ // The original key can now be discarded.
+
+ Cipher cipher = Cipher.getInstance(
+ KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/"
+ + KeyProperties.ENCRYPTION_PADDING_NONE);
+ cipher.init(Cipher.ENCRYPT_MODE, keyStoreEncryptionKey);
+ encryptionResult = cipher.doFinal(randomLockSeed);
+ iv = cipher.getIV();
+ } catch (CertificateException | UnrecoverableKeyException
+ | IOException | BadPaddingException | IllegalBlockSizeException | KeyStoreException
+ | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
+ throw new RuntimeException("Failed to encrypt key", e);
+ }
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ try {
+ if (iv.length != PROFILE_KEY_IV_SIZE) {
+ throw new RuntimeException("Invalid iv length: " + iv.length);
+ }
+ outputStream.write(iv);
+ outputStream.write(encryptionResult);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to concatenate byte arrays", e);
+ }
+ mStorage.writeChildProfileLock(userId, outputStream.toByteArray());
+ }
+
private byte[] enrollCredential(byte[] enrolledHandle,
String enrolledCredential, String toEnroll, int userId)
throws RemoteException {
@@ -820,7 +1073,7 @@
@Override
public void setCredential(String pattern, String oldPattern, int userId)
throws RemoteException {
- setLockPattern(pattern, oldPattern, userId);
+ setLockPatternInternal(pattern, oldPattern, userId);
}
@Override
@@ -838,7 +1091,7 @@
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK
&& shouldReEnrollBaseZero) {
- setLockPattern(pattern, patternToVerify, userId);
+ setLockPatternInternal(pattern, patternToVerify, userId);
}
return response;
@@ -857,6 +1110,37 @@
return doVerifyPassword(password, true, challenge, userId);
}
+ @Override
+ public VerifyCredentialResponse verifyTiedProfileChallenge(String password, boolean isPattern,
+ long challenge, int userId) throws RemoteException {
+ checkPasswordReadPermission(userId);
+ if (!isManagedProfileWithUnifiedLock(userId)) {
+ throw new RemoteException("User id must be managed profile with unified lock");
+ }
+ final int parentProfileId = mUserManager.getProfileParent(userId).id;
+ // Unlock parent by using parent's challenge
+ final VerifyCredentialResponse parentResponse = isPattern
+ ? doVerifyPattern(password, true, challenge, parentProfileId)
+ : doVerifyPassword(password, true, challenge, parentProfileId);
+ if (parentResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
+ // Failed, just return parent's response
+ return parentResponse;
+ }
+
+ try {
+ // Unlock work profile, and work profile with unified lock must use password only
+ return doVerifyPassword(getDecryptedPasswordForTiedProfile(userId), true,
+ challenge,
+ userId);
+ } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
+ | NoSuchAlgorithmException | NoSuchPaddingException
+ | InvalidAlgorithmParameterException | IllegalBlockSizeException
+ | BadPaddingException | CertificateException | IOException e) {
+ Slog.e(TAG, "Failed to decrypt child profile key", e);
+ throw new RemoteException("Unable to get tied profile token");
+ }
+ }
+
private VerifyCredentialResponse doVerifyPassword(String password, boolean hasChallenge,
long challenge, int userId) throws RemoteException {
checkPasswordReadPermission(userId);
@@ -866,7 +1150,7 @@
@Override
public void setCredential(String password, String oldPassword, int userId)
throws RemoteException {
- setLockPassword(password, oldPassword, userId);
+ setLockPasswordInternal(password, oldPassword, userId);
}
@Override
@@ -947,8 +1231,7 @@
" with token length " + response.getPayload().length);
unlockUser(userId, response.getPayload(), secretFromCredential(credential));
- UserInfo info = UserManager.get(mContext).getUserInfo(userId);
- if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
+ if (isManagedProfileWithSeparatedLock(userId)) {
TrustManager trustManager =
(TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
trustManager.setDeviceLockedForUser(userId, false);
@@ -1027,6 +1310,23 @@
} catch (RemoteException ex) {
Slog.w(TAG, "unable to clear GK secure user id");
}
+ if (mUserManager.getUserInfo(userId).isManagedProfile()) {
+ removeKeystoreProfileKey(userId);
+ }
+ }
+
+ private void removeKeystoreProfileKey(int targetUserId) {
+ if (DEBUG) Slog.v(TAG, "Remove keystore profile key for user: " + targetUserId);
+ try {
+ java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
+ keyStore.load(null);
+ keyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + targetUserId);
+ keyStore.deleteEntry(PROFILE_KEY_NAME_DECRYPT + targetUserId);
+ } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException
+ | IOException e) {
+ // We have tried our best to remove all keys
+ Slog.e(TAG, "Unable to remove keystore profile key for user:" + targetUserId, e);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
index 816c791..d136f1a 100644
--- a/services/core/java/com/android/server/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -17,7 +17,6 @@
package com.android.server;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.widget.LockPatternUtils;
import android.content.ContentValues;
import android.content.Context;
@@ -30,6 +29,7 @@
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import java.io.File;
import java.io.IOException;
@@ -44,6 +44,7 @@
private static final String TAG = "LockSettingsStorage";
private static final String TABLE = "locksettings";
+ private static final boolean DEBUG = false;
private static final String COLUMN_KEY = "name";
private static final String COLUMN_USERID = "user";
@@ -62,6 +63,7 @@
private static final String LEGACY_LOCK_PATTERN_FILE = "gesture.key";
private static final String LOCK_PASSWORD_FILE = "gatekeeper.password.key";
private static final String LEGACY_LOCK_PASSWORD_FILE = "password.key";
+ private static final String CHILD_PROFILE_LOCK_FILE = "gatekeeper.profile.key";
private static final Object DEFAULT = new Object();
@@ -70,8 +72,7 @@
private final Cache mCache = new Cache();
private final Object mFileWriteLock = new Object();
- private int mStoredCredentialType;
- private LockPatternUtils mLockPatternUtils;
+ private SparseArray<Integer> mStoredCredentialType;
class CredentialHash {
static final int TYPE_NONE = -1;
@@ -101,7 +102,7 @@
public LockSettingsStorage(Context context, Callback callback) {
mContext = context;
mOpenHelper = new DatabaseHelper(context, callback);
- mLockPatternUtils = new LockPatternUtils(context);
+ mStoredCredentialType = new SparseArray<Integer>();
}
public void writeKeyValue(String key, String value, int userId) {
@@ -182,32 +183,34 @@
}
public int getStoredCredentialType(int userId) {
- if (mStoredCredentialType != 0) {
- return mStoredCredentialType;
+ final Integer cachedStoredCredentialType = mStoredCredentialType.get(userId);
+ if (cachedStoredCredentialType != null) {
+ return cachedStoredCredentialType.intValue();
}
+ int storedCredentialType;
CredentialHash pattern = readPatternHash(userId);
if (pattern == null) {
if (readPasswordHash(userId) != null) {
- mStoredCredentialType = CredentialHash.TYPE_PASSWORD;
+ storedCredentialType = CredentialHash.TYPE_PASSWORD;
} else {
- mStoredCredentialType = CredentialHash.TYPE_NONE;
+ storedCredentialType = CredentialHash.TYPE_NONE;
}
} else {
CredentialHash password = readPasswordHash(userId);
if (password != null) {
// Both will never be GateKeeper
if (password.version == CredentialHash.VERSION_GATEKEEPER) {
- mStoredCredentialType = CredentialHash.TYPE_PASSWORD;
+ storedCredentialType = CredentialHash.TYPE_PASSWORD;
} else {
- mStoredCredentialType = CredentialHash.TYPE_PATTERN;
+ storedCredentialType = CredentialHash.TYPE_PATTERN;
}
} else {
- mStoredCredentialType = CredentialHash.TYPE_PATTERN;
+ storedCredentialType = CredentialHash.TYPE_PATTERN;
}
}
-
- return mStoredCredentialType;
+ mStoredCredentialType.put(userId, storedCredentialType);
+ return storedCredentialType;
}
@@ -244,6 +247,27 @@
return null;
}
+ public void removeChildProfileLock(int userId) {
+ if (DEBUG)
+ Slog.e(TAG, "Remove child profile lock for user: " + userId);
+ try {
+ deleteFile(getChildProfileLockFile(userId));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void writeChildProfileLock(int userId, byte[] lock) {
+ writeFile(getChildProfileLockFile(userId), lock);
+ }
+
+ public byte[] readChildProfileLock(int userId) {
+ return readFile(getChildProfileLockFile(userId));
+ }
+
+ public boolean hasChildProfileLock(int userId) {
+ return hasFile(getChildProfileLockFile(userId));
+ }
public boolean hasPassword(int userId) {
return hasFile(getLockPasswordFilename(userId)) ||
@@ -321,16 +345,19 @@
}
private void deleteFile(String name) {
- File f = new File(name);
- if (f != null) {
- f.delete();
+ if (DEBUG) Slog.e(TAG, "Delete file " + name);
+ synchronized (mFileWriteLock) {
+ File file = new File(name);
+ if (file.exists()) {
+ file.delete();
+ mCache.putFile(name, null);
+ }
}
}
public void writePatternHash(byte[] hash, int userId) {
- mStoredCredentialType = hash == null
- ? CredentialHash.TYPE_NONE
- : CredentialHash.TYPE_PATTERN;
+ mStoredCredentialType.put(userId, hash == null ? CredentialHash.TYPE_NONE
+ : CredentialHash.TYPE_PATTERN);
writeFile(getLockPatternFilename(userId), hash);
clearPasswordHash(userId);
}
@@ -340,9 +367,8 @@
}
public void writePasswordHash(byte[] hash, int userId) {
- mStoredCredentialType = hash == null
- ? CredentialHash.TYPE_NONE
- : CredentialHash.TYPE_PASSWORD;
+ mStoredCredentialType.put(userId, hash == null ? CredentialHash.TYPE_NONE
+ : CredentialHash.TYPE_PASSWORD);
writeFile(getLockPasswordFilename(userId), hash);
clearPatternHash(userId);
}
@@ -375,8 +401,11 @@
return getLockCredentialFilePathForUser(userId, BASE_ZERO_LOCK_PATTERN_FILE);
}
+ private String getChildProfileLockFile(int userId) {
+ return getLockCredentialFilePathForUser(userId, CHILD_PROFILE_LOCK_FILE);
+ }
+
private String getLockCredentialFilePathForUser(int userId, String basename) {
- userId = getUserParentOrSelfId(userId);
String dataSystemDirectory =
android.os.Environment.getDataDirectory().getAbsolutePath() +
SYSTEM_DIRECTORY;
@@ -388,23 +417,6 @@
}
}
- private int getUserParentOrSelfId(int userId) {
- // Device supports per user encryption, so lock is applied to the given user.
- if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
- return userId;
- }
- // Device uses Block Based Encryption, and the parent user's lock is used for the whole
- // device.
- if (userId != 0) {
- final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
- final UserInfo pi = um.getProfileParent(userId);
- if (pi != null) {
- return pi.id;
- }
- }
- return userId;
- }
-
public void removeUser(int userId) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
@@ -427,6 +439,9 @@
mCache.putFile(name, null);
}
}
+ } else {
+ // Manged profile
+ removeChildProfileLock(userId);
}
try {
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 440d8b7..fd9a94d 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -1984,6 +1984,28 @@
mHandler.obtainMessage(H_RESET).sendToTarget();
}
}
+
+ if ((mask & (StorageManager.DEBUG_SDCARDFS_FORCE_ON
+ | StorageManager.DEBUG_SDCARDFS_FORCE_OFF)) != 0) {
+ final String value;
+ if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_ON) != 0) {
+ value = "force_on";
+ } else if ((flags & StorageManager.DEBUG_SDCARDFS_FORCE_OFF) != 0) {
+ value = "force_off";
+ } else {
+ value = "";
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ SystemProperties.set(StorageManager.PROP_SDCARDFS, value);
+
+ // Reset storage to kick new setting into place
+ mHandler.obtainMessage(H_RESET).sendToTarget();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
}
@Override
diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java
index d6dbad8..7db9be2 100644
--- a/services/core/java/com/android/server/NativeDaemonConnector.java
+++ b/services/core/java/com/android/server/NativeDaemonConnector.java
@@ -110,6 +110,14 @@
}
/**
+ * Like SystemClock.uptimeMillis, except truncated to an int so it will fit in a message arg.
+ * Inaccurate across 49.7 days of uptime, but only used for debugging.
+ */
+ private int uptimeMillisInt() {
+ return (int) SystemClock.uptimeMillis() & Integer.MAX_VALUE;
+ }
+
+ /**
* Yell loudly if someone tries making future {@link #execute(Command)}
* calls while holding a lock on the given object.
*/
@@ -134,7 +142,9 @@
@Override
public boolean handleMessage(Message msg) {
- String event = (String) msg.obj;
+ final String event = (String) msg.obj;
+ final int start = uptimeMillisInt();
+ final int sent = msg.arg1;
try {
if (!mCallbacks.onEvent(msg.what, event, NativeDaemonEvent.unescapeArgs(event))) {
log(String.format("Unhandled event '%s'", event));
@@ -145,6 +155,13 @@
if (mCallbacks.onCheckHoldWakeLock(msg.what) && mWakeLock != null) {
mWakeLock.release();
}
+ final int end = uptimeMillisInt();
+ if (start > sent && start - sent > WARN_EXECUTE_DELAY_MS) {
+ loge(String.format("NDC event {%s} processed too late: %dms", event, start - sent));
+ }
+ if (end > start && end - start > WARN_EXECUTE_DELAY_MS) {
+ loge(String.format("NDC event {%s} took too long: %dms", event, end - start));
+ }
}
return true;
}
@@ -214,8 +231,9 @@
mWakeLock.acquire();
releaseWl = true;
}
- if (mCallbackHandler.sendMessage(mCallbackHandler.obtainMessage(
- event.getCode(), event.getRawEvent()))) {
+ Message msg = mCallbackHandler.obtainMessage(
+ event.getCode(), uptimeMillisInt(), 0, event.getRawEvent());
+ if (mCallbackHandler.sendMessage(msg)) {
releaseWl = false;
}
} else {
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index 3eb20a0..801d6e0 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -43,7 +43,6 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -195,12 +194,8 @@
}
void updateCurrentProfileIds() {
- final 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;
- }
- mSettings.setCurrentProfileIds(currentProfileIds);
+ mSettings.setCurrentProfileIds(
+ mUserManager.getProfileIdsWithDisabled(mSettings.getCurrentUserId()));
}
private class TextServicesMonitor extends PackageMonitor {
diff --git a/services/core/java/com/android/server/UiThread.java b/services/core/java/com/android/server/UiThread.java
index 0beb77f..c06afc2 100644
--- a/services/core/java/com/android/server/UiThread.java
+++ b/services/core/java/com/android/server/UiThread.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.os.Handler;
+import android.os.Trace;
/**
* Shared singleton thread for showing UI. This is a foreground thread, and in
@@ -35,6 +36,7 @@
if (sInstance == null) {
sInstance = new UiThread();
sInstance.start();
+ sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_ACTIVITY_MANAGER);
sHandler = new Handler(sInstance.getLooper());
}
}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 8a0a62a..810270d 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2884,7 +2884,6 @@
}
if (response == null) throw new IllegalArgumentException("response is null");
if (account == null) throw new IllegalArgumentException("account is null");
- if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1587516..0f48d21 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1467,6 +1467,7 @@
static final int NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG = 65;
static final int NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG = 66;
static final int NOTIFY_FORCED_RESIZABLE_MSG = 67;
+ static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 68;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -2056,6 +2057,21 @@
}
break;
}
+ case NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG: {
+ synchronized (ActivityManagerService.this) {
+ for (int i = mTaskStackListeners.beginBroadcast() - 1; i >= 0; i--) {
+ try {
+ // Make a one-way callback to the listener
+ mTaskStackListeners.getBroadcastItem(i)
+ .onActivityDismissingDockedStack();
+ } catch (RemoteException e){
+ // Handled by the RemoteCallbackList
+ }
+ }
+ mTaskStackListeners.finishBroadcast();
+ }
+ break;
+ }
case NOTIFY_CLEARTEXT_NETWORK_MSG: {
final int uid = msg.arg1;
final byte[] firstPacket = (byte[]) msg.obj;
@@ -10590,14 +10606,14 @@
private boolean requestTargetProviderPermissionsReviewIfNeededLocked(ProviderInfo cpi,
ProcessRecord r, final int userId) {
if (getPackageManagerInternalLocked().isPermissionsReviewRequired(
- cpi.packageName, r.userId)) {
+ cpi.packageName, userId)) {
- final boolean callerForeground = r != null ? r.setSchedGroup
- != ProcessList.SCHED_GROUP_BACKGROUND : true;
+ final boolean callerForeground = r == null || r.setSchedGroup
+ != ProcessList.SCHED_GROUP_BACKGROUND;
// Show a permission review UI only for starting from a foreground app
if (!callerForeground) {
- Slog.w(TAG, "u" + r.userId + " Instantiating a provider in package"
+ Slog.w(TAG, "u" + userId + " Instantiating a provider in package"
+ cpi.packageName + " requires a permissions review");
return false;
}
@@ -10608,7 +10624,7 @@
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, cpi.packageName);
if (DEBUG_PERMISSIONS_REVIEW) {
- Slog.i(TAG, "u" + r.userId + " Launching permission review "
+ Slog.i(TAG, "u" + userId + " Launching permission review "
+ "for package " + cpi.packageName);
}
@@ -15641,8 +15657,8 @@
pw.println(totalPss - cachedPss);
}
}
- long lostRAM = memInfo.getTotalSizeKb()
- - totalPss - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
+ long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
+ - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- memInfo.getKernelUsedSizeKb() - memInfo.getZramTotalSizeKb();
if (!isCompact) {
pw.print(" Used RAM: "); pw.print(stringifyKBSize(totalPss - cachedPss
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 4ec1f61..2e9947a 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -28,47 +28,78 @@
import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
-
import static android.content.res.Configuration.SCREENLAYOUT_UNDEFINED;
-import static com.android.server.am.ActivityManagerDebugConfig.*;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_APP;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CLEANUP;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONTAINERS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKSCREEN;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PAUSE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RELEASE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SCREENSHOTS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TRANSITION;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_APP;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONTAINERS;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PAUSE;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RELEASE;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SCREENSHOTS;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TRANSITION;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
+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.LOCK_SCREEN_SHOWN;
-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.HOME_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;
-
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.util.ArraySet;
-
-import com.android.internal.app.IVoiceInteractor;
-import com.android.internal.content.ReferrerIntent;
-import com.android.internal.os.BatteryStatsImpl;
-import com.android.server.Watchdog;
-import com.android.server.am.ActivityManagerService.ItemMatcher;
-import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
-import com.android.server.wm.AppTransition;
-import com.android.server.wm.TaskGroup;
-import com.android.server.wm.WindowManagerService;
+import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_CLOSE;
+import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
+import static com.android.server.wm.AppTransition.TRANSIT_NONE;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_CLOSE;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN_BEHIND;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_BACK;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_FRONT;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.StackId;
import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.IActivityController;
import android.app.ResultInfo;
-import android.app.ActivityManager.RunningTaskInfo;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -83,10 +114,20 @@
import android.os.Trace;
import android.os.UserHandle;
import android.service.voice.IVoiceInteractionSession;
+import android.util.ArraySet;
import android.util.EventLog;
import android.util.Slog;
import android.view.Display;
+import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.content.ReferrerIntent;
+import com.android.internal.os.BatteryStatsImpl;
+import com.android.server.Watchdog;
+import com.android.server.am.ActivityManagerService.ItemMatcher;
+import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
+import com.android.server.wm.TaskGroup;
+import com.android.server.wm.WindowManagerService;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -1650,6 +1691,13 @@
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = activities.get(activityNdx);
if (r.finishing) {
+ // Normally the screenshot will be taken in makeInvisible(). When an activity
+ // is finishing, we no longer change its visibility, but we still need to take
+ // the screenshots if startPausingLocked decided it should be taken.
+ if (r.mUpdateTaskThumbnailWhenHidden) {
+ r.updateThumbnailLocked(screenshotActivitiesLocked(r), null);
+ r.mUpdateTaskThumbnailWhenHidden = false;
+ }
continue;
}
final boolean isTop = r == top;
@@ -2225,11 +2273,11 @@
"Prepare close transition: prev=" + prev);
if (mNoAnimActivities.contains(prev)) {
anim = false;
- mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
+ mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
mWindowManager.prepareAppTransition(prev.task == next.task
- ? AppTransition.TRANSIT_ACTIVITY_CLOSE
- : AppTransition.TRANSIT_TASK_CLOSE, false);
+ ? TRANSIT_ACTIVITY_CLOSE
+ : TRANSIT_TASK_CLOSE, false);
}
mWindowManager.setAppVisibility(prev.appToken, false);
} else {
@@ -2237,22 +2285,22 @@
"Prepare open transition: prev=" + prev);
if (mNoAnimActivities.contains(next)) {
anim = false;
- mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
+ mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
mWindowManager.prepareAppTransition(prev.task == next.task
- ? AppTransition.TRANSIT_ACTIVITY_OPEN
+ ? TRANSIT_ACTIVITY_OPEN
: next.mLaunchTaskBehind
- ? AppTransition.TRANSIT_TASK_OPEN_BEHIND
- : AppTransition.TRANSIT_TASK_OPEN, false);
+ ? TRANSIT_TASK_OPEN_BEHIND
+ : TRANSIT_TASK_OPEN, false);
}
}
} else {
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
if (mNoAnimActivities.contains(next)) {
anim = false;
- mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
+ mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
- mWindowManager.prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_OPEN, false);
+ mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false);
}
}
@@ -2595,14 +2643,14 @@
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare open transition: starting " + r);
if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
- mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, keepCurTransition);
+ mWindowManager.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
mNoAnimActivities.add(r);
} else {
mWindowManager.prepareAppTransition(newTask
? r.mLaunchTaskBehind
- ? AppTransition.TRANSIT_TASK_OPEN_BEHIND
- : AppTransition.TRANSIT_TASK_OPEN
- : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
+ ? TRANSIT_TASK_OPEN_BEHIND
+ : TRANSIT_TASK_OPEN
+ : TRANSIT_ACTIVITY_OPEN, keepCurTransition);
mNoAnimActivities.remove(r);
}
addConfigOverride(r, task);
@@ -3354,13 +3402,13 @@
finishActivityResultsLocked(r, resultCode, resultData);
+ final boolean endTask = index <= 0;
+ final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
if (mResumedActivity == r) {
- boolean endTask = index <= 0;
+
if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare close transition: finishing " + r);
- mWindowManager.prepareAppTransition(endTask
- ? AppTransition.TRANSIT_TASK_CLOSE
- : AppTransition.TRANSIT_ACTIVITY_CLOSE, false);
+ mWindowManager.prepareAppTransition(transit, false);
// Tell window manager to prepare for this one to be removed.
mWindowManager.setAppVisibility(r.appToken, false);
@@ -3380,7 +3428,9 @@
// it is done pausing; else we can just directly finish it here.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r);
if (r.visible) {
+ mWindowManager.prepareAppTransition(transit, false);
mWindowManager.setAppVisibility(r.appToken, false);
+ mWindowManager.executeAppTransition();
}
return finishCurrentActivityLocked(r, FINISH_AFTER_PAUSE, oomAdj) == null;
} else {
@@ -4122,7 +4172,7 @@
if (noAnimation) {
ActivityOptions.abort(options);
} else {
- updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
+ updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
}
return;
}
@@ -4152,13 +4202,13 @@
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
if (noAnimation) {
- mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
+ mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
if (r != null) {
mNoAnimActivities.add(r);
}
ActivityOptions.abort(options);
} else {
- updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
+ updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
}
mStackSupervisor.resumeFocusedStackTopActivityLocked();
@@ -4261,7 +4311,7 @@
}
}
- mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_TO_BACK, false);
+ mWindowManager.prepareAppTransition(TRANSIT_TASK_TO_BACK, false);
mWindowManager.moveTaskToBottom(taskId);
if (VALIDATE_TOKENS) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index f659bde..d34e8fc 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -152,6 +152,7 @@
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityManagerService.ANIMATE;
import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
+import static com.android.server.am.ActivityManagerService.NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG;
import static com.android.server.am.ActivityManagerService.NOTIFY_FORCED_RESIZABLE_MSG;
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
@@ -1810,7 +1811,7 @@
if (DEBUG_STACK) Slog.d(TAG_STACK,
"findTaskToMoveToFront: moved to front of stack=" + task.stack);
- showNonResizeableDockToastIfNeeded(task, INVALID_STACK_ID, task.stack.mStackId);
+ handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, task.stack.mStackId);
}
boolean canUseActivityOptionsLaunchBounds(ActivityOptions options, int launchStackId) {
@@ -2043,8 +2044,10 @@
resizeStackUncheckedLocked(stack, dockedBounds, tempDockedTaskBounds,
tempDockedTaskInsetBounds);
- if (stack.mFullscreen) {
- // The dock stack went fullscreen which is kinda like dismissing it.
+ // TODO: Checking for isAttached might not be needed as if the user passes in null
+ // dockedBounds then they want the docked stack to be dismissed.
+ if (stack.mFullscreen || (dockedBounds == null && !stack.isAttached())) {
+ // The dock stack either was dismissed or went fullscreen, which is kinda the same.
// In this case we make all other static stacks fullscreen and move all
// docked stack tasks to the fullscreen stack.
for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
@@ -2069,18 +2072,13 @@
// static stacks need to be adjusted so they don't overlap with the docked stack.
// We get the bounds to use from window manager which has been adjusted for any
// screen controls and is also the same for all stacks.
- if (dockedBounds != null) {
- mWindowManager.getStackDockedModeBounds(
- HOME_STACK_ID, tempRect, true /* ignoreVisibility */);
- }
+ mWindowManager.getStackDockedModeBounds(
+ HOME_STACK_ID, tempRect, true /* ignoreVisibility */);
for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
- if (StackId.isResizeableByDockedStack(i)) {
- ActivityStack otherStack = getStack(i);
- if (otherStack != null) {
- resizeStackLocked(i, dockedBounds != null ? tempRect : null,
- tempOtherTaskBounds, tempOtherTaskInsetBounds, preserveWindows,
- true /* allowResizeInDockedMode */);
- }
+ if (StackId.isResizeableByDockedStack(i) && getStack(i) != null) {
+ resizeStackLocked(i, tempRect, tempOtherTaskBounds,
+ tempOtherTaskInsetBounds, preserveWindows,
+ true /* allowResizeInDockedMode */);
}
}
}
@@ -2395,7 +2393,7 @@
resumeFocusedStackTopActivityLocked();
}
- showNonResizeableDockToastIfNeeded(task, preferredLaunchStackId, stackId);
+ handleNonResizableTaskIfNeeded(task, preferredLaunchStackId, stackId);
return (preferredLaunchStackId == stackId);
}
@@ -3251,13 +3249,9 @@
}
private void calculateDefaultMinimalSizeOfResizeableTasks(ActivityDisplay display) {
- if (display.mDisplayId != Display.DEFAULT_DISPLAY) {
- return;
- }
- final float fraction = mService.mContext.getResources().getFraction(com.android.internal.R.
- fraction.config_displayFractionForDefaultMinimalSizeOfResizeableTask, 1, 1);
- mDefaultMinimalSizeOfResizeableTask = (int) (fraction * Math.min(
- display.mDisplayInfo.logicalWidth, display.mDisplayInfo.logicalHeight));
+ mDefaultMinimalSizeOfResizeableTask =
+ mService.mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.default_minimal_size_resizable_task);
}
private void handleDisplayRemoved(int displayId) {
@@ -3366,15 +3360,19 @@
}
}
- void showNonResizeableDockToastIfNeeded(
+ void handleNonResizableTaskIfNeeded(
TaskRecord task, int preferredStackId, int actualStackId) {
- if (!isStackDockedInEffect(actualStackId) && preferredStackId != DOCKED_STACK_ID) {
+ if ((!isStackDockedInEffect(actualStackId) && preferredStackId != DOCKED_STACK_ID)
+ || task.isHomeTask()) {
return;
}
if (!task.canGoInDockedStack()) {
// Display a warning toast that we tried to put a non-dockable task in the docked stack.
- mWindowManager.scheduleShowNonResizeableDockToast(task.taskId);
+ mService.mHandler.sendEmptyMessage(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
+
+ // Dismiss docked stack.
+ mService.moveTasksToFullscreenStack(DOCKED_STACK_ID, false);
} else if (task.mResizeMode == RESIZE_MODE_FORCE_RESIZEABLE) {
String packageName = task.getTopActivity() != null
? task.getTopActivity().appInfo.packageName : null;
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index 76dfd01..785dd47 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -119,7 +119,13 @@
if (!mUserManager.isQuietModeEnabled(UserHandle.of(mUserId))) {
return false;
}
- mIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent(mUserId);
+ IIntentSender target = mService.getIntentSenderLocked(
+ INTENT_SENDER_ACTIVITY, mCallingPackage, mCallingUid, mUserId, null, null, 0,
+ new Intent[] {mIntent}, new String[] {mResolvedType},
+ FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT, null);
+
+ mIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent(mUserId,
+ new IntentSender(target));
mCallingPid = mRealCallingPid;
mCallingUid = mRealCallingUid;
mResolvedType = null;
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 3bbc4521..6fba8c8 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -986,8 +986,12 @@
}
top.deliverNewIntentLocked(
mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
- mSupervisor.showNonResizeableDockToastIfNeeded(mStartActivity.task,
- preferredLaunchStackId, topStack.mStackId);
+
+ // Don't use mStartActivity.task to show the toast. We're not starting a new activity
+ // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
+ mSupervisor.handleNonResizableTaskIfNeeded(
+ top.task, preferredLaunchStackId, topStack.mStackId);
+
return START_DELIVERED_TO_TOP;
}
@@ -1074,7 +1078,7 @@
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
- mSupervisor.showNonResizeableDockToastIfNeeded(
+ mSupervisor.handleNonResizableTaskIfNeeded(
mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
return START_SUCCESS;
@@ -1382,6 +1386,9 @@
mTargetStack.moveToFront("intentActivityFound");
}
+ mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
+ mTargetStack.mStackId);
+
// If the caller has requested that the target task be reset, then do so.
if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index e32d1d1..e69c662 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -1447,7 +1447,8 @@
if (stack == null || StackId.persistTaskBounds(stack.mStackId)) {
mLastNonFullscreenBounds = mBounds;
}
- mOverrideConfig = calculateOverrideConfig(mTmpRect, insetBounds);
+ mOverrideConfig = calculateOverrideConfig(mTmpRect, insetBounds,
+ mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
}
if (mFullscreen != oldFullscreen) {
@@ -1457,33 +1458,38 @@
return !mOverrideConfig.equals(oldConfig) ? mOverrideConfig : null;
}
- private void subtractNonDecorInsets(Rect inOutBounds, Rect inInsetBounds) {
+ private void subtractNonDecorInsets(Rect inOutBounds, Rect inInsetBounds,
+ boolean overrideWidth, boolean overrideHeight) {
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;
+ int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect2.right;
+ int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect2.bottom;
inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
}
- private void subtractStableInsets(Rect inOutBounds, Rect inInsetBounds) {
+ private void subtractStableInsets(Rect inOutBounds, Rect inInsetBounds,
+ boolean overrideWidth, boolean overrideHeight) {
mTmpRect2.set(inInsetBounds);
mService.mWindowManager.subtractStableInsets(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;
+ int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect2.right;
+ int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect2.bottom;
inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
}
- private Configuration calculateOverrideConfig(Rect bounds, Rect insetBounds) {
+ private Configuration calculateOverrideConfig(Rect bounds, Rect insetBounds,
+ boolean overrideWidth, boolean overrideHeight) {
mTmpNonDecorBounds.set(bounds);
mTmpStableBounds.set(bounds);
subtractNonDecorInsets(
- mTmpNonDecorBounds, insetBounds != null ? insetBounds : bounds);
+ mTmpNonDecorBounds, insetBounds != null ? insetBounds : bounds,
+ overrideWidth, overrideHeight);
subtractStableInsets(
- mTmpStableBounds, insetBounds != null ? insetBounds : bounds);
+ mTmpStableBounds, insetBounds != null ? insetBounds : bounds,
+ overrideWidth, overrideHeight);
// For calculating screenWidthDp, screenWidthDp, we use the stable inset screen area,
// i.e. the screen area without the system bars.
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 6e890d5..bea26c7 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -237,7 +237,22 @@
AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
}
- maybeUnlockUser(userId);
+ // We need to delay unlocking managed profiles until the parent user
+ // is also unlocked.
+ if (getUserManager().isManagedProfile(userId)) {
+ final UserInfo parent = getUserManager().getProfileParent(userId);
+ if (parent != null
+ && isUserRunningLocked(parent.id, ActivityManager.FLAG_AND_UNLOCKED)) {
+ Slog.d(TAG, "User " + userId + " (parent " + parent.id
+ + "): attempting unlock because parent is unlocked");
+ maybeUnlockUser(userId);
+ } else {
+ Slog.d(TAG, "User " + userId + " (parent " + parent.id
+ + "): delaying unlock because parent is locked");
+ }
+ } else {
+ maybeUnlockUser(userId);
+ }
}
}
@@ -903,6 +918,18 @@
synchronized (mService) {
final UserState uss = mStartedUsers.get(userId);
finishUserUnlocking(uss, progress);
+
+ // We just unlocked a user, so let's now attempt to unlock any
+ // managed profiles under that user.
+ for (int i = 0; i < mStartedUsers.size(); i++) {
+ final int testUserId = mStartedUsers.keyAt(i);
+ final UserInfo parent = getUserManager().getProfileParent(testUserId);
+ if (parent != null && parent.id == userId && testUserId != userId) {
+ Slog.d(TAG, "User " + testUserId + " (parent " + parent.id
+ + "): attempting unlock because parent was just unlocked");
+ maybeUnlockUser(testUserId);
+ }
+ }
}
return true;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index f471af6..a6dfab0 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1290,7 +1290,7 @@
// Check if the ringer mode handles this adjustment. If it does we don't
// need to adjust the volume further.
final int result = checkForRingerModeChange(aliasIndex, direction, step,
- streamState.mIsMuted);
+ streamState.mIsMuted, callingPackage, flags);
adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
// If suppressing a volume adjustment in silent mode, display the UI hint
if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
@@ -1302,8 +1302,7 @@
}
}
// If the ringermode is suppressing media, prevent changes
- if (streamTypeAlias == AudioSystem.STREAM_MUSIC
- && (mRingerModeMutedStreams & (1 << AudioSystem.STREAM_MUSIC)) != 0) {
+ if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
adjustVolume = false;
}
int oldIndex = mStreamStates[streamType].getIndex(device);
@@ -1551,6 +1550,10 @@
throw new SecurityException("Not allowed to change Do Not Disturb state");
}
+ if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
+ return;
+ }
+
synchronized (mSafeMediaVolumeState) {
// reset any pending volume command
mPendingVolumeCommand = null;
@@ -1601,6 +1604,19 @@
sendVolumeUpdate(streamType, oldIndex, index, flags);
}
+ // No ringer affected streams can be changed in total silence mode except those that
+ // will cause the device to exit total silence mode.
+ private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) {
+ if (mNm.getZenMode() == Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
+ && isStreamMutedByRingerMode(streamTypeAlias)) {
+ if (!(((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
+ (streamTypeAlias == getUiSoundsStreamType()))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
/** @see AudioManager#forceVolumeControlStream(int) */
public void forceVolumeControlStream(int streamType, IBinder cb) {
synchronized(mForceControlStreamLock) {
@@ -3366,7 +3382,8 @@
* adjusting volume. If so, this will set the proper ringer mode and volume
* indices on the stream states.
*/
- private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted) {
+ private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
+ String caller, int flags) {
final boolean isTv = mPlatformType == AudioSystem.PLATFORM_TELEVISION;
int result = FLAG_ADJUST_VOLUME;
int ringerMode = getRingerModeInternal();
@@ -3455,6 +3472,12 @@
break;
}
+ if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
+ && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)
+ && (flags & AudioManager.FLAG_FROM_KEY) == 0) {
+ throw new SecurityException("Not allowed to change Do Not Disturb state");
+ }
+
setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
mPrevVolDirection = direction;
@@ -3954,25 +3977,16 @@
public void applyAllVolumes() {
synchronized (VolumeStreamState.class) {
- // apply default volume first: by convention this will reset all
- // devices volumes in audio policy manager to the supplied value
+ // apply device specific volumes first
int index;
- if (mIsMuted) {
- index = 0;
- } else {
- index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
- }
- AudioSystem.setStreamVolumeIndex(mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
- // then apply device specific volumes
for (int i = 0; i < mIndexMap.size(); i++) {
- int device = mIndexMap.keyAt(i);
+ final int device = mIndexMap.keyAt(i);
if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
if (mIsMuted) {
index = 0;
} else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
mAvrcpAbsVolSupported)
- || ((device & mFullVolumeDevices) != 0))
- {
+ || ((device & mFullVolumeDevices) != 0)) {
index = (mIndexMax + 5)/10;
} else {
index = (mIndexMap.valueAt(i) + 5)/10;
@@ -3980,6 +3994,15 @@
AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
}
}
+ // apply default volume last: by convention , default device volume will be used
+ // by audio policy manager if no explicit volume is present for a given device type
+ if (mIsMuted) {
+ index = 0;
+ } else {
+ index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
+ }
+ AudioSystem.setStreamVolumeIndex(
+ mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
}
}
diff --git a/services/core/java/com/android/server/camera/CameraService.java b/services/core/java/com/android/server/camera/CameraService.java
index cd8eb4e..7d9adf2 100644
--- a/services/core/java/com/android/server/camera/CameraService.java
+++ b/services/core/java/com/android/server/camera/CameraService.java
@@ -15,32 +15,28 @@
*/
package com.android.server.camera;
-import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.UserInfo;
import android.hardware.ICameraService;
import android.hardware.ICameraServiceProxy;
import android.nfc.INfcAdapter;
+import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Binder;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
-import android.os.UserManager;
import android.os.SystemProperties;
-import android.util.Slog;
+import android.os.UserManager;
import android.util.ArraySet;
+import android.util.Slog;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
import java.util.Set;
/**
@@ -225,11 +221,11 @@
}
private Set<Integer> getEnabledUserHandles(int currentUserHandle) {
- List<UserInfo> userProfiles = mUserManager.getEnabledProfiles(currentUserHandle);
- Set<Integer> handles = new HashSet<>(userProfiles.size());
+ int[] userProfiles = mUserManager.getEnabledProfileIds(currentUserHandle);
+ Set<Integer> handles = new ArraySet<>(userProfiles.length);
- for (UserInfo i : userProfiles) {
- handles.add(i.id);
+ for (int id : userProfiles) {
+ handles.add(id);
}
return handles;
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 2cba93fd..79b5978 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -57,12 +57,16 @@
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.IState;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.MessageUtils;
+import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.server.IoThread;
@@ -95,6 +99,12 @@
private final static boolean DBG = false;
private final static boolean VDBG = false;
+ private static final Class[] messageClasses = {
+ Tethering.class, TetherMasterSM.class, TetherInterfaceSM.class
+ };
+ private static final SparseArray<String> sMagicDecoderRing =
+ MessageUtils.findMessageNames(messageClasses);
+
// TODO - remove both of these - should be part of interface inspection/selection stuff
private String[] mTetherableUsbRegexs;
private String[] mTetherableWifiRegexs;
@@ -235,6 +245,8 @@
@Override
public void interfaceStatusChanged(String iface, boolean up) {
+ // Never called directly: only called from interfaceLinkStateChanged.
+ // See NetlinkHandler.cpp:71.
if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
boolean found = false;
boolean usb = false;
@@ -274,7 +286,6 @@
@Override
public void interfaceLinkStateChanged(String iface, boolean up) {
- if (VDBG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up);
interfaceStatusChanged(iface, up);
}
@@ -660,8 +671,11 @@
erroredList);
mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
if (DBG) {
- Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " +
- activeList.size() + ", " + erroredList.size());
+ Log.d(TAG, String.format(
+ "sendTetherStateChangedBroadcast avail=[%s] active=[%s] error=[%s]",
+ TextUtils.join(",", availableList),
+ TextUtils.join(",", activeList),
+ TextUtils.join(",", erroredList)));
}
if (usbTethered) {
@@ -989,31 +1003,39 @@
return retVal;
}
+ private void maybeLogMessage(State state, int what) {
+ if (DBG) {
+ Log.d(TAG, state.getName() + " got " +
+ sMagicDecoderRing.get(what, Integer.toString(what)));
+ }
+ }
+
class TetherInterfaceSM extends StateMachine {
+ private static final int BASE_IFACE = Protocol.BASE_TETHERING + 100;
// notification from the master SM that it's not in tether mode
- static final int CMD_TETHER_MODE_DEAD = 1;
+ static final int CMD_TETHER_MODE_DEAD = BASE_IFACE + 1;
// request from the user that it wants to tether
- static final int CMD_TETHER_REQUESTED = 2;
+ static final int CMD_TETHER_REQUESTED = BASE_IFACE + 2;
// request from the user that it wants to untether
- static final int CMD_TETHER_UNREQUESTED = 3;
+ static final int CMD_TETHER_UNREQUESTED = BASE_IFACE + 3;
// notification that this interface is down
- static final int CMD_INTERFACE_DOWN = 4;
+ static final int CMD_INTERFACE_DOWN = BASE_IFACE + 4;
// notification that this interface is up
- static final int CMD_INTERFACE_UP = 5;
+ static final int CMD_INTERFACE_UP = BASE_IFACE + 5;
// notification from the master SM that it had an error turning on cellular dun
- static final int CMD_CELL_DUN_ERROR = 6;
+ static final int CMD_CELL_DUN_ERROR = BASE_IFACE + 6;
// notification from the master SM that it had trouble enabling IP Forwarding
- static final int CMD_IP_FORWARDING_ENABLE_ERROR = 7;
+ static final int CMD_IP_FORWARDING_ENABLE_ERROR = BASE_IFACE + 7;
// notification from the master SM that it had trouble disabling IP Forwarding
- static final int CMD_IP_FORWARDING_DISABLE_ERROR = 8;
+ static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IFACE + 8;
// notification from the master SM that it had trouble starting tethering
- static final int CMD_START_TETHERING_ERROR = 9;
+ static final int CMD_START_TETHERING_ERROR = BASE_IFACE + 9;
// notification from the master SM that it had trouble stopping tethering
- static final int CMD_STOP_TETHERING_ERROR = 10;
+ static final int CMD_STOP_TETHERING_ERROR = BASE_IFACE + 10;
// notification from the master SM that it had trouble setting the DNS forwarders
- static final int CMD_SET_DNS_FORWARDERS_ERROR = 11;
+ static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IFACE + 11;
// the upstream connection has changed
- static final int CMD_TETHER_CONNECTION_CHANGED = 12;
+ static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IFACE + 12;
private State mDefaultState;
@@ -1124,7 +1146,7 @@
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, "InitialState.processMessage what=" + message.what);
+ maybeLogMessage(this, message.what);
boolean retValue = true;
switch (message.what) {
case CMD_TETHER_REQUESTED:
@@ -1165,7 +1187,7 @@
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, "StartingState.processMessage what=" + message.what);
+ maybeLogMessage(this, message.what);
boolean retValue = true;
switch (message.what) {
// maybe a parent class?
@@ -1255,7 +1277,7 @@
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, "TetheredState.processMessage what=" + message.what);
+ maybeLogMessage(this, message.what);
boolean retValue = true;
boolean error = false;
switch (message.what) {
@@ -1480,18 +1502,19 @@
}
class TetherMasterSM extends StateMachine {
+ private static final int BASE_MASTER = Protocol.BASE_TETHERING;
// an interface SM has requested Tethering
- static final int CMD_TETHER_MODE_REQUESTED = 1;
+ static final int CMD_TETHER_MODE_REQUESTED = BASE_MASTER + 1;
// an interface SM has unrequested Tethering
- static final int CMD_TETHER_MODE_UNREQUESTED = 2;
+ static final int CMD_TETHER_MODE_UNREQUESTED = BASE_MASTER + 2;
// upstream connection change - do the right thing
- static final int CMD_UPSTREAM_CHANGED = 3;
+ static final int CMD_UPSTREAM_CHANGED = BASE_MASTER + 3;
// we don't have a valid upstream conn, check again after a delay
- static final int CMD_RETRY_UPSTREAM = 4;
+ static final int CMD_RETRY_UPSTREAM = BASE_MASTER + 4;
// Events from NetworkCallbacks that we process on the master state
// machine thread on behalf of the UpstreamNetworkMonitor.
- static final int EVENT_UPSTREAM_LINKPROPERTIES_CHANGED = 5;
- static final int EVENT_UPSTREAM_LOST = 6;
+ static final int EVENT_UPSTREAM_LINKPROPERTIES_CHANGED = BASE_MASTER + 5;
+ static final int EVENT_UPSTREAM_LOST = BASE_MASTER + 6;
// This indicates what a timeout event relates to. A state that
// sends itself a delayed timeout event and handles incoming timeout events
@@ -1748,7 +1771,7 @@
}
protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
- if (DBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
+ if (DBG) Log.d(TAG, "Notifying tethered with upstream=" + ifaceName);
mCurrentUpstreamIface = ifaceName;
for (TetherInterfaceSM sm : mNotifyList) {
sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
@@ -1862,7 +1885,7 @@
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what);
+ maybeLogMessage(this, message.what);
boolean retValue = true;
switch (message.what) {
case CMD_TETHER_MODE_REQUESTED:
@@ -1910,7 +1933,7 @@
}
@Override
public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what);
+ maybeLogMessage(this, message.what);
boolean retValue = true;
switch (message.what) {
case CMD_TETHER_MODE_REQUESTED:
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index e5342ce..db41a54 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1402,12 +1402,24 @@
}
}
+ private void restoreLostPeriodicSyncsIfNeeded(int userId) {
+ List<SyncOperation> periodicSyncs = new ArrayList<SyncOperation>();
+ for (SyncOperation sync : getAllPendingSyncs()) {
+ if (sync.isPeriodic && sync.target.userId == userId) {
+ periodicSyncs.add(sync);
+ }
+ }
+ mSyncStorageEngine.restorePeriodicSyncsIfNeededForUser(userId, periodicSyncs);
+ }
+
private void onUserUnlocked(int userId) {
// Make sure that accounts we're about to use are valid.
AccountManagerService.getSingleton().validateAccounts(userId);
mSyncAdapters.invalidateCache(userId);
+ restoreLostPeriodicSyncsIfNeeded(userId);
+
EndPoint target = new EndPoint(null, null, userId);
updateRunningAccounts(target);
@@ -2578,9 +2590,11 @@
}
}
+ // Cancel all jobs from non-existent accounts.
+ AccountAndUser[] allAccounts = AccountManagerService.getSingleton().getAllAccounts();
List<SyncOperation> ops = getAllPendingSyncs();
for (SyncOperation op: ops) {
- if (!containsAccountAndUser(accounts, op.target.account, op.target.userId)) {
+ if (!containsAccountAndUser(allAccounts, op.target.account, op.target.userId)) {
getJobScheduler().cancel(op.jobId);
}
}
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index bc3fc6a..fb23265 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -826,6 +826,35 @@
return true;
}
+ /**
+ * STOPSHIP This is a temporary workaround and should be removed before shipping: b/28052438
+ */
+ void restorePeriodicSyncsIfNeededForUser(int userHandle, List<SyncOperation> periodicSyncs) {
+ if (mPeriodicSyncAddedListener == null) {
+ return;
+ }
+ synchronized (mAuthorities) {
+ for (int i = 0; i < mAuthorities.size(); i++) {
+ AuthorityInfo authority = mAuthorities.valueAt(i);
+ if (authority.target.userId == userHandle && authority.enabled) {
+ boolean periodicSyncAlreadyExists = false;
+ for (SyncOperation sync : periodicSyncs) {
+ if (authority.target.matchesSpec(sync.target)) {
+ periodicSyncAlreadyExists = true;
+ break;
+ }
+ }
+ // The periodic sync must have been lost due to previous bug.
+ if (!periodicSyncAlreadyExists) {
+ mPeriodicSyncAddedListener.onPeriodicSyncAdded(authority.target,
+ new Bundle(), DEFAULT_POLL_FREQUENCY_SECONDS,
+ calculateDefaultFlexTime(DEFAULT_POLL_FREQUENCY_SECONDS));
+ }
+ }
+ }
+ }
+ }
+
public void setMasterSyncAutomatically(boolean flag, int userId) {
synchronized (mAuthorities) {
Boolean auto = mMasterSyncAutomatically.get(userId);
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 7ba030f..e3f3849 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -541,10 +541,8 @@
UserManager um = UserManager.get(mContext);
// Allow current user or profiles of the current user...
- List<UserInfo> profiles = um.getEnabledProfiles(userId);
- final int n = profiles.size();
- for (int i = 0; i < n; i++) {
- if (profiles.get(i).id == userId) {
+ for (int profileId : um.getEnabledProfileIds(userId)) {
+ if (profileId == userId) {
return true;
}
}
@@ -947,10 +945,6 @@
if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
return;
}
-
- // Group ID is arbitrarily set to parent profile user ID. It just represents
- // the default fingerprints for the user.
- final int effectiveGroupId = getEffectiveUserId(groupId);
final int realUserId = Binder.getCallingUid();
final boolean restricted = isRestricted();
@@ -958,7 +952,7 @@
@Override
public void run() {
MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);
- startAuthentication(token, opId, realUserId, effectiveGroupId, receiver,
+ startAuthentication(token, opId, realUserId, groupId, receiver,
flags, restricted, opPackageName);
}
});
@@ -993,14 +987,10 @@
final IFingerprintServiceReceiver receiver) {
checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
final boolean restricted = isRestricted();
-
- // Group ID is arbitrarily set to parent profile user ID. It just represents
- // the default fingerprints for the user.
- final int effectiveGroupId = getEffectiveUserId(groupId);
mHandler.post(new Runnable() {
@Override
public void run() {
- startRemove(token, fingerId, effectiveGroupId, receiver, restricted);
+ startRemove(token, fingerId, groupId, receiver, restricted);
}
});
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index e73beaa..c7c765bb 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -200,6 +200,7 @@
private static native int nativeInjectInputEvent(long ptr, InputEvent event, int displayId,
int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
int policyFlags);
+ private static native void nativeToggleCapsLock(long ptr, int deviceId);
private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen);
private static native void nativeSetSystemUiVisibility(long ptr, int visibility);
@@ -2279,5 +2280,10 @@
mHandler.obtainMessage(MSG_INPUT_METHOD_SUBTYPE_CHANGED, userId, 0, someArgs)
.sendToTarget();
}
+
+ @Override
+ public void toggleCapsLock(int deviceId) {
+ nativeToggleCapsLock(mPtr, deviceId);
+ }
}
}
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 5ad8189..be9d800 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -77,8 +77,10 @@
if (cs != null) {
if (cs.getActiveNetworkInfo() != null) {
mNetworkConnected = cs.getActiveNetworkInfo().isConnected();
+ mNetworkUnmetered = mNetworkConnected && !cs.isActiveNetworkMetered();
+ } else {
+ mNetworkConnected = mNetworkUnmetered = false;
}
- mNetworkUnmetered = mNetworkConnected && !cs.isActiveNetworkMetered();
}
}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index e08fad4..d80dc3b 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -39,6 +39,7 @@
import android.location.IGnssStatusListener;
import android.location.IGnssStatusProvider;
import android.location.GnssMeasurementsEvent;
+import android.location.GnssNavigationMessage;
import android.location.GnssNavigationMessageEvent;
import android.location.IGpsGeofenceHardware;
import android.location.ILocationManager;
@@ -1662,11 +1663,21 @@
/**
* called from native code - GPS navigation message callback
*/
- private void reportNavigationMessage(GnssNavigationMessageEvent event) {
+ private void reportNavigationMessage(GnssNavigationMessage event) {
mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
}
/**
+ * called from native code - GPS navigation message callback
+ */
+ private void reportNavigationMessage(GnssNavigationMessageEvent event) {
+ if (event != null) {
+ mGnssNavigationMessageProvider
+ .onNavigationMessageAvailable(event.getNavigationMessage());
+ }
+ }
+
+ /**
* called from native code to inform us what the GPS engine capabilities are
*/
private void setEngineCapabilities(int capabilities) {
diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
index 734a8d4..caf1d6c 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
@@ -64,15 +64,15 @@
int status;
switch (result) {
case RESULT_SUCCESS:
- status = GnssMeasurementsEvent.STATUS_READY;
+ status = GnssMeasurementsEvent.Callback.STATUS_READY;
break;
case RESULT_NOT_AVAILABLE:
case RESULT_NOT_SUPPORTED:
case RESULT_INTERNAL_ERROR:
- status = GnssMeasurementsEvent.STATUS_NOT_SUPPORTED;
+ status = GnssMeasurementsEvent.Callback.STATUS_NOT_SUPPORTED;
break;
case RESULT_GPS_LOCATION_DISABLED:
- status = GnssMeasurementsEvent.STATUS_GNSS_LOCATION_DISABLED;
+ status = GnssMeasurementsEvent.Callback.STATUS_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 fdef31f..8d21928 100644
--- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
@@ -16,7 +16,7 @@
package com.android.server.location;
-import android.location.GnssNavigationMessageEvent;
+import android.location.GnssNavigationMessage;
import android.location.IGnssNavigationMessageListener;
import android.os.Handler;
import android.os.RemoteException;
@@ -37,7 +37,7 @@
super(handler, TAG);
}
- public void onNavigationMessageAvailable(final GnssNavigationMessageEvent event) {
+ public void onNavigationMessageAvailable(final GnssNavigationMessage event) {
ListenerOperation<IGnssNavigationMessageListener> operation =
new ListenerOperation<IGnssNavigationMessageListener>() {
@Override
@@ -65,16 +65,15 @@
int status;
switch (result) {
case RESULT_SUCCESS:
- status = GnssNavigationMessageEvent.STATUS_READY;
+ status = GnssNavigationMessage.Callback.STATUS_READY;
break;
case RESULT_NOT_AVAILABLE:
case RESULT_NOT_SUPPORTED:
case RESULT_INTERNAL_ERROR:
- status = GnssNavigationMessageEvent.STATUS_NOT_SUPPORTED;
+ status = GnssNavigationMessage.Callback.STATUS_NOT_SUPPORTED;
break;
case RESULT_GPS_LOCATION_DISABLED:
- status = GnssNavigationMessageEvent
- .STATUS_GNSS_LOCATION_DISABLED;
+ status = GnssNavigationMessage.Callback.STATUS_LOCATION_DISABLED;
break;
case RESULT_UNKNOWN:
return null;
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index e3c540a5..a4d2cd2 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -962,6 +962,7 @@
mKeyEventReceiver.aquireWakeLockLocked();
}
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+ mediaButtonIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
try {
if (user.mLastMediaButtonReceiver != null) {
@@ -986,6 +987,7 @@
}
// Fallback to legacy behavior
Intent keyIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
+ keyIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
keyIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
if (needWakeLock) {
keyIntent.putExtra(EXTRA_WAKELOCK_ACQUIRED,
diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java
index 68dc715..959a823 100644
--- a/services/core/java/com/android/server/net/NetworkIdentitySet.java
+++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java
@@ -23,6 +23,8 @@
import java.io.IOException;
import java.util.HashSet;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+
/**
* Identity of a {@code iface}, defined by the set of {@link NetworkIdentity}
* active on that interface.
@@ -34,6 +36,7 @@
private static final int VERSION_INIT = 1;
private static final int VERSION_ADD_ROAMING = 2;
private static final int VERSION_ADD_NETWORK_ID = 3;
+ private static final int VERSION_ADD_METERED = 4;
public NetworkIdentitySet() {
}
@@ -61,12 +64,22 @@
roaming = false;
}
- add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming));
+ final boolean metered;
+ if (version >= VERSION_ADD_METERED) {
+ metered = in.readBoolean();
+ } else {
+ // If this is the old data and the type is mobile, treat it as metered. (Note that
+ // if this is a mobile network, TYPE_MOBILE is the only possible type that could be
+ // used.)
+ metered = (type == TYPE_MOBILE);
+ }
+
+ add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered));
}
}
public void writeToStream(DataOutputStream out) throws IOException {
- out.writeInt(VERSION_ADD_NETWORK_ID);
+ out.writeInt(VERSION_ADD_METERED);
out.writeInt(size());
for (NetworkIdentity ident : this) {
out.writeInt(ident.getType());
@@ -74,6 +87,7 @@
writeOptionalString(out, ident.getSubscriberId());
writeOptionalString(out, ident.getNetworkId());
out.writeBoolean(ident.getRoaming());
+ out.writeBoolean(ident.getMetered());
}
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 612bae2..c248608 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -940,7 +940,7 @@
for (int subId : subIds) {
final String subscriberId = tele.getSubscriberId(subId);
final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
- TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
+ TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true);
if (template.matches(probeIdent)) {
return true;
}
@@ -1333,7 +1333,7 @@
private void ensureActiveMobilePolicyLocked(String subscriberId) {
// Poke around to see if we already have a policy
final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
- TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
+ TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true);
for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
final NetworkTemplate template = mNetworkPolicy.keyAt(i);
if (template.matches(probeIdent)) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 99c41ea..f20d0a1 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -30,8 +30,11 @@
import static android.service.notification.NotificationRankerService.REASON_PACKAGE_CHANGED;
import static android.service.notification.NotificationRankerService.REASON_PACKAGE_SUSPENDED;
import static android.service.notification.NotificationRankerService.REASON_PROFILE_TURNED_OFF;
+import static android.service.notification.NotificationRankerService.REASON_UNAUTOBUNDLED;
import static android.service.notification.NotificationRankerService.REASON_USER_STOPPED;
import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
+import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS;
+import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_CALL_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;
@@ -39,8 +42,6 @@
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;
-import static org.xmlpull.v1.XmlPullParser.START_TAG;
import android.Manifest;
import android.annotation.Nullable;
@@ -97,6 +98,7 @@
import android.os.UserManager;
import android.os.Vibrator;
import android.provider.Settings;
+import android.service.notification.Adjustment;
import android.service.notification.Condition;
import android.service.notification.IConditionProvider;
import android.service.notification.INotificationListener;
@@ -114,6 +116,7 @@
import android.util.AtomicFile;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.Xml;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -136,7 +139,6 @@
import libcore.io.IoUtils;
-import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParser;
@@ -158,7 +160,6 @@
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -248,8 +249,9 @@
private String mSoundNotificationKey;
private String mVibrateNotificationKey;
- private final ArraySet<ManagedServiceInfo> mListenersDisablingEffects = new ArraySet<>();
- private ComponentName mEffectsSuppressor;
+ private final SparseArray<ArraySet<ManagedServiceInfo>> mListenersDisablingEffects =
+ new SparseArray<ArraySet<ManagedServiceInfo>>();
+ private List<ComponentName> mEffectsSuppressors = new ArrayList<ComponentName>();
private int mListenerHints; // right now, all hints are global
private int mInterruptionFilter = NotificationListenerService.INTERRUPTION_FILTER_UNKNOWN;
@@ -263,6 +265,7 @@
new ArrayList<NotificationRecord>();
final ArrayMap<String, NotificationRecord> mNotificationsByKey =
new ArrayMap<String, NotificationRecord>();
+ final ArrayMap<String, String> mAutobundledSummaries = new ArrayMap<>();
final ArrayList<ToastRecord> mToastQueue = new ArrayList<ToastRecord>();
final ArrayMap<String, NotificationRecord> mSummaryByGroupKey = new ArrayMap<>();
final PolicyAccess mPolicyAccess = new PolicyAccess();
@@ -283,11 +286,6 @@
private static final String TAG_NOTIFICATION_POLICY = "notification-policy";
private static final String ATTR_VERSION = "version";
- // Obsolete: converted if present, but not resaved to disk.
- private static final String TAG_BLOCKED_PKGS = "blocked-packages";
- private static final String TAG_PACKAGE = "package";
- private static final String ATTR_NAME = "name";
-
private RankingHelper mRankingHelper;
private final UserProfiles mUserProfiles = new UserProfiles();
@@ -1118,23 +1116,112 @@
}
private void updateListenerHintsLocked() {
- final int hints = mListenersDisablingEffects.isEmpty() ? 0 : HINT_HOST_DISABLE_EFFECTS;
+ final int hints = calculateHints();
if (hints == mListenerHints) return;
- ZenLog.traceListenerHintsChanged(mListenerHints, hints, mListenersDisablingEffects.size());
+ ZenLog.traceListenerHintsChanged(mListenerHints, hints, mEffectsSuppressors.size());
mListenerHints = hints;
scheduleListenerHintsChanged(hints);
}
private void updateEffectsSuppressorLocked() {
- final ComponentName suppressor = !mListenersDisablingEffects.isEmpty()
- ? mListenersDisablingEffects.valueAt(0).component : null;
- if (Objects.equals(suppressor, mEffectsSuppressor)) return;
- ZenLog.traceEffectsSuppressorChanged(mEffectsSuppressor, suppressor);
- mEffectsSuppressor = suppressor;
- mZenModeHelper.setEffectsSuppressed(suppressor != null);
+ final long updatedSuppressedEffects = calculateSuppressedEffects();
+ if (updatedSuppressedEffects == mZenModeHelper.getSuppressedEffects()) return;
+ final List<ComponentName> suppressors = getSuppressors();
+ ZenLog.traceEffectsSuppressorChanged(mEffectsSuppressors, suppressors, updatedSuppressedEffects);
+ mEffectsSuppressors = suppressors;
+ mZenModeHelper.setSuppressedEffects(updatedSuppressedEffects);
sendRegisteredOnlyBroadcast(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
}
+ private ArrayList<ComponentName> getSuppressors() {
+ ArrayList<ComponentName> names = new ArrayList<ComponentName>();
+ for (int i = mListenersDisablingEffects.size() - 1; i >= 0; --i) {
+ ArraySet<ManagedServiceInfo> serviceInfoList = mListenersDisablingEffects.valueAt(i);
+
+ for (ManagedServiceInfo info : serviceInfoList) {
+ names.add(info.component);
+ }
+ }
+
+ return names;
+ }
+
+ private boolean removeDisabledHints(ManagedServiceInfo info) {
+ return removeDisabledHints(info, 0);
+ }
+
+ private boolean removeDisabledHints(ManagedServiceInfo info, int hints) {
+ boolean removed = false;
+
+ for (int i = mListenersDisablingEffects.size() - 1; i >= 0; --i) {
+ final int hint = mListenersDisablingEffects.keyAt(i);
+ final ArraySet<ManagedServiceInfo> listeners =
+ mListenersDisablingEffects.valueAt(i);
+
+ if (hints == 0 || (hint & hints) == hint) {
+ removed = removed || listeners.remove(info);
+ }
+ }
+
+ return removed;
+ }
+
+ private void addDisabledHints(ManagedServiceInfo info, int hints) {
+ if ((hints & HINT_HOST_DISABLE_EFFECTS) != 0) {
+ addDisabledHint(info, HINT_HOST_DISABLE_EFFECTS);
+ }
+
+ if ((hints & HINT_HOST_DISABLE_NOTIFICATION_EFFECTS) != 0) {
+ addDisabledHint(info, HINT_HOST_DISABLE_NOTIFICATION_EFFECTS);
+ }
+
+ if ((hints & HINT_HOST_DISABLE_CALL_EFFECTS) != 0) {
+ addDisabledHint(info, HINT_HOST_DISABLE_CALL_EFFECTS);
+ }
+ }
+
+ private void addDisabledHint(ManagedServiceInfo info, int hint) {
+ if (mListenersDisablingEffects.indexOfKey(hint) < 0) {
+ mListenersDisablingEffects.put(hint, new ArraySet<ManagedServiceInfo>());
+ }
+
+ ArraySet<ManagedServiceInfo> hintListeners = mListenersDisablingEffects.get(hint);
+ hintListeners.add(info);
+ }
+
+ private int calculateHints() {
+ int hints = 0;
+ for (int i = mListenersDisablingEffects.size() - 1; i >= 0; --i) {
+ int hint = mListenersDisablingEffects.keyAt(i);
+ ArraySet<ManagedServiceInfo> serviceInfoList = mListenersDisablingEffects.valueAt(i);
+
+ if (!serviceInfoList.isEmpty()) {
+ hints |= hint;
+ }
+ }
+
+ return hints;
+ }
+
+ private long calculateSuppressedEffects() {
+ int hints = calculateHints();
+ long suppressedEffects = 0;
+
+ if ((hints & HINT_HOST_DISABLE_EFFECTS) != 0) {
+ suppressedEffects |= ZenModeHelper.SUPPRESSED_EFFECT_ALL;
+ }
+
+ if ((hints & HINT_HOST_DISABLE_NOTIFICATION_EFFECTS) != 0) {
+ suppressedEffects |= ZenModeHelper.SUPPRESSED_EFFECT_NOTIFICATIONS;
+ }
+
+ if ((hints & HINT_HOST_DISABLE_CALL_EFFECTS) != 0) {
+ suppressedEffects |= ZenModeHelper.SUPPRESSED_EFFECT_CALLS;
+ }
+
+ return suppressedEffects;
+ }
+
private void updateInterruptionFilterLocked() {
int interruptionFilter = mZenModeHelper.getZenModeListenerInterruptionFilter();
if (interruptionFilter == mInterruptionFilter) return;
@@ -1259,10 +1346,13 @@
checkCallerIsSystemOrSameApp(pkg);
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), userId, true, false, "cancelNotificationWithTag", pkg);
- // Don't allow client applications to cancel foreground service notis.
+ // Don't allow client applications to cancel foreground service notis or autobundled
+ // summaries.
cancelNotification(Binder.getCallingUid(), Binder.getCallingPid(), pkg, tag, id, 0,
- Binder.getCallingUid() == Process.SYSTEM_UID
- ? 0 : Notification.FLAG_FOREGROUND_SERVICE, false, userId,
+ (Binder.getCallingUid() == Process.SYSTEM_UID
+ ? 0 : Notification.FLAG_FOREGROUND_SERVICE)
+ | (Binder.getCallingUid() == Process.SYSTEM_UID
+ ? 0 : Notification.FLAG_AUTOGROUP_SUMMARY), false, userId,
REASON_APP_CANCEL, null);
}
@@ -1404,7 +1494,9 @@
final int N = mNotificationList.size();
for (int i = 0; i < N; i++) {
final StatusBarNotification sbn = mNotificationList.get(i).sbn;
- if (sbn.getPackageName().equals(pkg) && sbn.getUserId() == userId) {
+ if (sbn.getPackageName().equals(pkg) && sbn.getUserId() == userId
+ && (sbn.getNotification().flags
+ & Notification.FLAG_AUTOGROUP_SUMMARY) != 0) {
// We could pass back a cloneLight() but clients might get confused and
// try to send this thing back to notify() again, which would not work
// very well.
@@ -1519,7 +1611,8 @@
checkCallerIsSystemOrSameApp(component.getPackageName());
long identity = Binder.clearCallingIdentity();
try {
- ManagedServices manager = mRankerServices.isComponentEnabledForCurrentProfiles(component)
+ ManagedServices manager =
+ mRankerServices.isComponentEnabledForCurrentProfiles(component)
? mRankerServices
: mListeners;
manager.setComponentState(component, true);
@@ -1651,11 +1744,14 @@
try {
synchronized (mNotificationList) {
final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
- final boolean disableEffects = (hints & HINT_HOST_DISABLE_EFFECTS) != 0;
+ final int disableEffectsMask = HINT_HOST_DISABLE_EFFECTS
+ | HINT_HOST_DISABLE_NOTIFICATION_EFFECTS
+ | HINT_HOST_DISABLE_CALL_EFFECTS;
+ final boolean disableEffects = (hints & disableEffectsMask) != 0;
if (disableEffects) {
- mListenersDisablingEffects.add(info);
+ addDisabledHints(info, hints);
} else {
- mListenersDisablingEffects.remove(info);
+ removeDisabledHints(info, hints);
}
updateListenerHintsLocked();
updateEffectsSuppressorLocked();
@@ -1913,7 +2009,7 @@
@Override
public ComponentName getEffectsSuppressor() {
enforceSystemOrSystemUIOrVolume("INotificationManager.getEffectsSuppressor");
- return mEffectsSuppressor;
+ return mEffectsSuppressors.get(0);
}
@Override
@@ -2035,25 +2131,123 @@
}
@Override
- public void setImportanceFromRankerService(INotificationListener token, String key,
- int importance, CharSequence explanation) throws RemoteException {
- if (importance == IMPORTANCE_NONE) {
- throw new IllegalArgumentException("blocking not allowed: key=" + key);
- }
+ public void applyAdjustmentFromRankerService(INotificationListener token,
+ Adjustment adjustment) throws RemoteException {
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mNotificationList) {
mRankerServices.checkServiceTokenLocked(token);
- NotificationRecord n = mNotificationsByKey.get(key);
- n.setImportance(importance, explanation);
- mRankingHandler.requestSort();
+ applyAdjustmentLocked(adjustment);
}
+ maybeAddAutobundleSummary(adjustment);
+ mRankingHandler.requestSort();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void applyAdjustmentsFromRankerService(INotificationListener token,
+ List<Adjustment> adjustments) throws RemoteException {
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mNotificationList) {
+ mRankerServices.checkServiceTokenLocked(token);
+ for (Adjustment adjustment : adjustments) {
+ applyAdjustmentLocked(adjustment);
+ }
+ }
+ for (Adjustment adjustment : adjustments) {
+ maybeAddAutobundleSummary(adjustment);
+ }
+ mRankingHandler.requestSort();
} finally {
Binder.restoreCallingIdentity(identity);
}
}
};
+ private void applyAdjustmentLocked(Adjustment adjustment) {
+ maybeClearAutobundleSummaryLocked(adjustment);
+ NotificationRecord n = mNotificationsByKey.get(adjustment.getKey());
+ if (n == null) {
+ return;
+ }
+ if (adjustment.getImportance() != IMPORTANCE_NONE) {
+ n.setImportance(adjustment.getImportance(), adjustment.getExplanation());
+ }
+ if (adjustment.getSignals() != null) {
+ Bundle.setDefusable(adjustment.getSignals(), true);
+ n.sbn.setOverrideGroupKey(adjustment.getSignals().getString(
+ Adjustment.GROUP_KEY_OVERRIDE_KEY, null));
+ }
+ }
+
+ // Clears the 'fake' auto-bunding summary.
+ private void maybeClearAutobundleSummaryLocked(Adjustment adjustment) {
+ if (adjustment.getSignals() != null
+ && adjustment.getSignals().containsKey(Adjustment.NEEDS_AUTOGROUPING_KEY)
+ && !adjustment.getSignals().getBoolean(Adjustment.NEEDS_AUTOGROUPING_KEY, false)) {
+ if (mAutobundledSummaries.containsKey(adjustment.getPackage())) {
+ // Clear summary.
+ final NotificationRecord removed = mNotificationsByKey.get(
+ mAutobundledSummaries.remove(adjustment.getPackage()));
+ if (removed != null) {
+ mNotificationList.remove(removed);
+ cancelNotificationLocked(removed, false, REASON_UNAUTOBUNDLED);
+ }
+ }
+ }
+ }
+
+ // Posts a 'fake' summary for a package that has exceeded the solo-notification limit.
+ private void maybeAddAutobundleSummary(Adjustment adjustment) {
+ if (adjustment.getSignals() != null
+ && adjustment.getSignals().getBoolean(Adjustment.NEEDS_AUTOGROUPING_KEY, false)) {
+ final String newAutoBundleKey =
+ adjustment.getSignals().getString(Adjustment.GROUP_KEY_OVERRIDE_KEY, null);
+ int userId = -1;
+ NotificationRecord summaryRecord = null;
+ synchronized (mNotificationList) {
+ if (!mAutobundledSummaries.containsKey(adjustment.getPackage())
+ && newAutoBundleKey != null) {
+ // Add summary
+ final StatusBarNotification adjustedSbn
+ = mNotificationsByKey.get(adjustment.getKey()).sbn;
+
+ final ApplicationInfo appInfo =
+ adjustedSbn.getNotification().extras.getParcelable(
+ Notification.EXTRA_BUILDER_APPLICATION_INFO);
+ final Bundle extras = new Bundle();
+ extras.putParcelable(Notification.EXTRA_BUILDER_APPLICATION_INFO, appInfo);
+ final Notification summaryNotification =
+ new Notification.Builder(getContext()).setSmallIcon(
+ adjustedSbn.getNotification().getSmallIcon())
+ .setGroupSummary(true)
+ .setGroup(newAutoBundleKey)
+ .setFlag(Notification.FLAG_AUTOGROUP_SUMMARY, true)
+ .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
+ .build();
+ summaryNotification.extras.putAll(extras);
+ final StatusBarNotification summarySbn =
+ new StatusBarNotification(adjustedSbn.getPackageName(),
+ adjustedSbn.getOpPkg(),
+ Integer.MAX_VALUE, Adjustment.GROUP_KEY_OVERRIDE_KEY,
+ adjustedSbn.getUid(), adjustedSbn.getInitialPid(),
+ summaryNotification, adjustedSbn.getUser(), newAutoBundleKey,
+ System.currentTimeMillis());
+ summaryRecord = new NotificationRecord(getContext(), summarySbn);
+ mAutobundledSummaries.put(adjustment.getPackage(), summarySbn.getKey());
+ userId = adjustedSbn.getUser().getIdentifier();
+ }
+ }
+ if (summaryRecord != null) {
+ mHandler.post(new EnqueueNotificationRunnable(userId, summaryRecord));
+ }
+ }
+ }
+
private String disableNotificationEffects(NotificationRecord record) {
if (mDisableNotificationEffects) {
return "booleanState";
@@ -2175,9 +2369,19 @@
pw.print(" mListenersDisablingEffects: (");
N = mListenersDisablingEffects.size();
for (int i = 0; i < N; i++) {
- final ManagedServiceInfo listener = mListenersDisablingEffects.valueAt(i);
- if (i > 0) pw.print(',');
- pw.print(listener.component);
+ final int hint = mListenersDisablingEffects.keyAt(i);
+ if (i > 0) pw.print(';');
+ pw.print("hint[" + hint + "]:");
+
+ final ArraySet<ManagedServiceInfo> listeners =
+ mListenersDisablingEffects.valueAt(i);
+ final int listenerSize = listeners.size();
+
+ for (int j = 0; j < listenerSize; j++) {
+ if (i > 0) pw.print(',');
+ final ManagedServiceInfo listener = listeners.valueAt(i);
+ pw.print(listener.component);
+ }
}
pw.println(')');
pw.println("\n mRankerServicePackageName: " + mRankerServicePackageName);
@@ -2253,6 +2457,17 @@
callingUid, incomingUserId, true, false, "enqueueNotification", pkg);
final UserHandle user = new UserHandle(userId);
+ // Fix the notification as best we can.
+ try {
+ Notification.addFieldsFromContext(getContext().createApplicationContext(
+ getContext().getPackageManager().getApplicationInfoAsUser(
+ pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, userId),
+ Context.CONTEXT_RESTRICTED), notification);
+ } catch (NameNotFoundException e) {
+ Slog.e(TAG, "Cannot create a context for sending app", e);
+ return;
+ }
+
// Limit the number of notifications that any given package except the android
// package or a registered listener can enqueue. Prevents DOS attacks and deals with leaks.
if (!isSystemNotification && !isNotificationFromListener) {
@@ -2492,7 +2707,7 @@
StatusBarNotification sbn = r.sbn;
String group = sbn.getGroupKey();
boolean isSummary = sbn.getNotification().isGroupSummary();
- boolean isChild = sbn.getNotification().isGroupChild();
+ boolean isChild = !isSummary && sbn.isGroup();
NotificationRecord summary = mSummaryByGroupKey.get(group);
if (isChild && summary != null) {
@@ -2857,11 +3072,13 @@
synchronized (mNotificationList) {
final int N = mNotificationList.size();
ArrayList<String> orderBefore = new ArrayList<String>(N);
+ ArrayList<String> groupOverrideBefore = new ArrayList<>(N);
int[] visibilities = new int[N];
- int [] importances = new int[N];
+ int[] importances = new int[N];
for (int i = 0; i < N; i++) {
final NotificationRecord r = mNotificationList.get(i);
orderBefore.add(r.getKey());
+ groupOverrideBefore.add(r.sbn.getGroupKey());
visibilities[i] = r.getPackageVisibilityOverride();
importances[i] = r.getImportance();
mRankingHelper.extractSignals(r);
@@ -2871,7 +3088,8 @@
final NotificationRecord r = mNotificationList.get(i);
if (!orderBefore.get(i).equals(r.getKey())
|| visibilities[i] != r.getPackageVisibilityOverride()
- || importances[i] != r.getImportance()) {
+ || importances[i] != r.getImportance()
+ || !groupOverrideBefore.get(i).equals(r.sbn.getGroupKey())) {
scheduleSendRankingUpdate();
return;
}
@@ -3070,6 +3288,7 @@
mLights.remove(canceledKey);
// Record usage stats
+ // TODO: add unbundling stats?
switch (reason) {
case REASON_DELEGATE_CANCEL:
case REASON_DELEGATE_CANCEL_ALL:
@@ -3089,6 +3308,9 @@
if (groupSummary != null && groupSummary.getKey().equals(r.getKey())) {
mSummaryByGroupKey.remove(groupKey);
}
+ if (r.sbn.getKey().equals(mAutobundledSummaries.get(r.sbn.getPackageName()))) {
+ mAutobundledSummaries.remove(r.sbn.getPackageName());
+ }
// Save it for users of getHistoricalNotifications()
mArchive.record(r.sbn);
@@ -3287,7 +3509,7 @@
for (int i = N - 1; i >= 0; i--) {
NotificationRecord childR = mNotificationList.get(i);
StatusBarNotification childSbn = childR.sbn;
- if (childR.getNotification().isGroupChild() &&
+ if ((childSbn.isGroup() && !childSbn.getNotification().isGroupSummary()) &&
childR.getGroupKey().equals(r.getGroupKey())) {
EventLogTags.writeNotificationCancel(callingUid, callingPid, pkg, childSbn.getId(),
childSbn.getTag(), userId, 0, 0, reason, listenerName);
@@ -3438,6 +3660,7 @@
ArrayList<String> keys = new ArrayList<String>(N);
ArrayList<String> interceptedKeys = new ArrayList<String>(N);
ArrayList<Integer> importance = new ArrayList<>(N);
+ Bundle overrideGroupKeys = new Bundle();
Bundle visibilityOverrides = new Bundle();
Bundle suppressedVisualEffects = new Bundle();
Bundle explanation = new Bundle();
@@ -3461,6 +3684,7 @@
!= NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) {
visibilityOverrides.putInt(key, record.getPackageVisibilityOverride());
}
+ overrideGroupKeys.putString(key, record.sbn.getOverrideGroupKey());
}
final int M = keys.size();
String[] keysAr = keys.toArray(new String[M]);
@@ -3470,7 +3694,7 @@
importanceAr[i] = importance.get(i);
}
return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
- suppressedVisualEffects, importanceAr, explanation);
+ suppressedVisualEffects, importanceAr, explanation, overrideGroupKeys);
}
private boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
@@ -3690,7 +3914,7 @@
@Override
protected void onServiceRemovedLocked(ManagedServiceInfo removed) {
- if (mListenersDisablingEffects.remove(removed)) {
+ if (removeDisabledHints(removed)) {
updateListenerHintsLocked();
updateEffectsSuppressorLocked();
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index fd893fa..f29970c 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -24,18 +24,15 @@
import android.app.Notification;
import android.content.Context;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
import android.media.AudioAttributes;
-import android.os.Build;
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.server.EventLogTags;
@@ -179,10 +176,7 @@
mRankingTimeMs = calculateRankingTimeMs(previous.getRankingTimeMs());
mCreationTimeMs = previous.mCreationTimeMs;
mVisibleSinceMs = previous.mVisibleSinceMs;
- mUserImportance = previous.mUserImportance;
- mImportance = previous.mImportance;
- mImportanceExplanation = previous.mImportanceExplanation;
- // Don't copy mGlobalSortKey, recompute it.
+ // Don't copy importance information or mGlobalSortKey, recompute them.
}
public Notification getNotification() { return sbn.getNotification(); }
diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java
index c45071b..207bdba 100644
--- a/services/core/java/com/android/server/notification/ZenLog.java
+++ b/services/core/java/com/android/server/notification/ZenLog.java
@@ -31,6 +31,7 @@
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.List;
public class ZenLog {
private static final String TAG = "ZenLog";
@@ -126,10 +127,11 @@
append(TYPE_DISABLE_EFFECTS, record.getKey() + "," + reason);
}
- public static void traceEffectsSuppressorChanged(ComponentName oldSuppressor,
- ComponentName newSuppressor) {
- append(TYPE_SUPPRESSOR_CHANGED, componentToString(oldSuppressor) + "->"
- + componentToString(newSuppressor));
+ public static void traceEffectsSuppressorChanged(List<ComponentName> oldSuppressors,
+ List<ComponentName> newSuppressors, long suppressedEffects) {
+ append(TYPE_SUPPRESSOR_CHANGED, "suppressed effects:" + suppressedEffects + ","
+ + componentListToString(oldSuppressors) + "->"
+ + componentListToString(newSuppressors));
}
public static void traceListenerHintsChanged(int oldHints, int newHints, int listenerCount) {
@@ -193,6 +195,19 @@
return component != null ? component.toShortString() : null;
}
+ private static String componentListToString(List<ComponentName> components) {
+ StringBuilder stringBuilder = new StringBuilder();
+
+ for (int i = 0; i < components.size(); ++i) {
+ if (i > 0) {
+ stringBuilder.append(", ");
+ }
+ stringBuilder.append(componentToString(components.get(i)));
+ }
+
+ return stringBuilder.toString();
+ }
+
private static void append(int type, String msg) {
synchronized(MSGS) {
TIMES[sNext] = System.currentTimeMillis();
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 5c5c8f8..eb49e9f 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -102,7 +102,12 @@
private ZenModeConfig mConfig;
private AudioManagerInternal mAudioManager;
private PackageManager mPm;
- private boolean mEffectsSuppressed;
+ private long mSuppressedEffects;
+
+ public static final long SUPPRESSED_EFFECT_NOTIFICATIONS = 1;
+ public static final long SUPPRESSED_EFFECT_CALLS = 1 << 1;
+ public static final long SUPPRESSED_EFFECT_ALL = SUPPRESSED_EFFECT_CALLS
+ | SUPPRESSED_EFFECT_NOTIFICATIONS;
public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
mContext = context;
@@ -228,12 +233,16 @@
}
}
- public void setEffectsSuppressed(boolean effectsSuppressed) {
- if (mEffectsSuppressed == effectsSuppressed) return;
- mEffectsSuppressed = effectsSuppressed;
+ public void setSuppressedEffects(long suppressedEffects) {
+ if (mSuppressedEffects == suppressedEffects) return;
+ mSuppressedEffects = suppressedEffects;
applyRestrictions();
}
+ public long getSuppressedEffects() {
+ return mSuppressedEffects;
+ }
+
public int getZenMode() {
return mZenMode;
}
@@ -484,7 +493,8 @@
synchronized (mConfig) {
dump(pw, prefix, "mConfig", mConfig);
}
- pw.print(prefix); pw.print("mEffectsSuppressed="); pw.println(mEffectsSuppressed);
+
+ pw.print(prefix); pw.print("mSuppressedEffects="); pw.println(mSuppressedEffects);
mFiltering.dump(pw, prefix);
mConditions.dump(pw, prefix);
}
@@ -708,9 +718,11 @@
final boolean zen = mZenMode != Global.ZEN_MODE_OFF;
// notification restrictions
- final boolean muteNotifications = mEffectsSuppressed;
+ final boolean muteNotifications =
+ (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
// call restrictions
- final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers;
+ final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers
+ || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
// total silence restrictions
final boolean muteEverything = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index eae2eaa..f6255af 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -16,6 +16,8 @@
package com.android.server.pm;
+import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
+
import android.app.AlarmManager;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
@@ -23,6 +25,9 @@
import android.app.job.JobService;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
import android.os.ServiceManager;
import android.util.ArraySet;
import android.util.Log;
@@ -38,7 +43,9 @@
static final long RETRY_LATENCY = 4 * AlarmManager.INTERVAL_HOUR;
- static final int BACKGROUND_DEXOPT_JOB = 800;
+ static final int JOB_IDLE_OPTIMIZE = 800;
+ static final int JOB_POST_BOOT_UPDATE = 801;
+
private static ComponentName sDexoptServiceName = new ComponentName(
"android",
BackgroundDexOptService.class.getName());
@@ -48,66 +55,193 @@
*/
static final ArraySet<String> sFailedPackageNames = new ArraySet<String>();
- final AtomicBoolean mIdleTime = new AtomicBoolean(false);
+ /**
+ * Atomics set to true if the JobScheduler requests an abort.
+ */
+ final AtomicBoolean mAbortPostBootUpdate = new AtomicBoolean(false);
+ final AtomicBoolean mAbortIdleOptimization = new AtomicBoolean(false);
+
+ /**
+ * Atomic set to true if one job should exit early because another job was started.
+ */
+ final AtomicBoolean mExitPostBootUpdate = new AtomicBoolean(false);
public static void schedule(Context context) {
JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
- JobInfo job = new JobInfo.Builder(BACKGROUND_DEXOPT_JOB, sDexoptServiceName)
- .setRequiresDeviceIdle(true)
- .setRequiresCharging(true)
- .setPeriodic(TimeUnit.DAYS.toMillis(1))
- .build();
- js.schedule(job);
+
+ // Schedule a one-off job which scans installed packages and updates
+ // out-of-date oat files.
+ js.schedule(new JobInfo.Builder(JOB_POST_BOOT_UPDATE, sDexoptServiceName)
+ .setMinimumLatency(TimeUnit.MINUTES.toMillis(1))
+ .setOverrideDeadline(TimeUnit.MINUTES.toMillis(1))
+ .build());
+
+ // Schedule a daily job which scans installed packages and compiles
+ // those with fresh profiling data.
+ js.schedule(new JobInfo.Builder(JOB_IDLE_OPTIMIZE, sDexoptServiceName)
+ .setRequiresDeviceIdle(true)
+ .setRequiresCharging(true)
+ .setPeriodic(TimeUnit.DAYS.toMillis(1))
+ .build());
+
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Jobs scheduled");
+ }
}
- @Override
- public boolean onStartJob(JobParameters params) {
- Log.i(TAG, "onStartJob");
- final PackageManagerService pm =
- (PackageManagerService)ServiceManager.getService("package");
-
- if (pm.isStorageLow()) {
- Log.i(TAG, "Low storage, skipping this run");
- return false;
+ public static void notifyPackageChanged(String packageName) {
+ // The idle maintanance job skips packages which previously failed to
+ // compile. The given package has changed and may successfully compile
+ // now. Remove it from the list of known failing packages.
+ synchronized (sFailedPackageNames) {
+ sFailedPackageNames.remove(packageName);
}
- final ArraySet<String> pkgs = pm.getOptimizablePackages();
- if (pkgs == null || pkgs.isEmpty()) {
- Log.i(TAG, "No packages to optimize");
+ }
+
+ // Returns the current battery level as a 0-100 integer.
+ private int getBatteryLevel() {
+ IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+ Intent intent = registerReceiver(null, filter);
+ int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
+ int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
+
+ if (level < 0 || scale <= 0) {
+ // Battery data unavailable. This should never happen, so assume the worst.
+ return 0;
+ }
+
+ return (100 * level / scale);
+ }
+
+ private boolean runPostBootUpdate(final JobParameters jobParams,
+ final PackageManagerService pm, final ArraySet<String> pkgs) {
+ if (mExitPostBootUpdate.get()) {
+ // This job has already been superseded. Do not start it.
return false;
}
- final JobParameters jobParams = params;
- mIdleTime.set(true);
- new Thread("BackgroundDexOptService_DexOpter") {
+ // Load low battery threshold from the system config. This is a 0-100 integer.
+ final int lowBatteryThreshold = getResources().getInteger(
+ com.android.internal.R.integer.config_lowBatteryWarningLevel);
+
+ mAbortPostBootUpdate.set(false);
+ new Thread("BackgroundDexOptService_PostBootUpdate") {
@Override
public void run() {
for (String pkg : pkgs) {
- if (!mIdleTime.get()) {
- // Out of the idle state. Stop the compilation.
+ if (mAbortPostBootUpdate.get()) {
+ // JobScheduler requested an early abort.
+ return;
+ }
+ if (mExitPostBootUpdate.get()) {
+ // Different job, which supersedes this one, is running.
+ break;
+ }
+ if (getBatteryLevel() < lowBatteryThreshold) {
+ // Rather bail than completely drain the battery.
+ break;
+ }
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Updating package " + pkg);
+ }
+ // Update package if needed. Note that there can be no race between concurrent
+ // jobs because PackageDexOptimizer.performDexOpt is synchronized.
+ pm.performDexOpt(pkg,
+ /* instruction set */ null,
+ /* checkProfiles */ false,
+ PackageManagerService.REASON_BOOT,
+ /* force */ false);
+ }
+ // Ran to completion, so we abandon our timeslice and do not reschedule.
+ jobFinished(jobParams, /* reschedule */ false);
+ }
+ }.start();
+ return true;
+ }
+
+ private boolean runIdleOptimization(final JobParameters jobParams,
+ final PackageManagerService pm, final ArraySet<String> pkgs) {
+ // If post-boot update is still running, request that it exits early.
+ mExitPostBootUpdate.set(true);
+
+ mAbortIdleOptimization.set(false);
+ new Thread("BackgroundDexOptService_IdleOptimization") {
+ @Override
+ public void run() {
+ for (String pkg : pkgs) {
+ if (mAbortIdleOptimization.get()) {
+ // JobScheduler requested an early abort.
return;
}
if (sFailedPackageNames.contains(pkg)) {
- // skip previously failing package
+ // Skip previously failing package
continue;
}
- if (!pm.performDexOpt(pkg, /* instruction set */ null, /* checkProfiles */ true,
- PackageManagerService.REASON_BACKGROUND_DEXOPT, /* force */ false)) {
- // there was a problem running dexopt,
- // remember this so we do not keep retrying.
+ // Conservatively add package to the list of failing ones in case performDexOpt
+ // never returns.
+ synchronized (sFailedPackageNames) {
sFailedPackageNames.add(pkg);
}
+ // Optimize package if needed. Note that there can be no race between
+ // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
+ if (pm.performDexOpt(pkg,
+ /* instruction set */ null,
+ /* checkProfiles */ true,
+ PackageManagerService.REASON_BACKGROUND_DEXOPT,
+ /* force */ false)) {
+ // Dexopt succeeded, remove package from the list of failing ones.
+ synchronized (sFailedPackageNames) {
+ sFailedPackageNames.remove(pkg);
+ }
+ }
}
- // ran to completion, so we abandon our timeslice and do not reschedule
- jobFinished(jobParams, false);
+ // Ran to completion, so we abandon our timeslice and do not reschedule.
+ jobFinished(jobParams, /* reschedule */ false);
}
}.start();
return true;
}
@Override
+ public boolean onStartJob(JobParameters params) {
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "onStartJob");
+ }
+
+ PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package");
+ if (pm.isStorageLow()) {
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Low storage, skipping this run");
+ }
+ return false;
+ }
+
+ final ArraySet<String> pkgs = pm.getOptimizablePackages();
+ if (pkgs == null || pkgs.isEmpty()) {
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "No packages to optimize");
+ }
+ return false;
+ }
+
+ if (params.getJobId() == JOB_POST_BOOT_UPDATE) {
+ return runPostBootUpdate(params, pm, pkgs);
+ } else {
+ return runIdleOptimization(params, pm, pkgs);
+ }
+ }
+
+ @Override
public boolean onStopJob(JobParameters params) {
- Log.i(TAG, "onIdleStop");
- mIdleTime.set(false);
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "onStopJob");
+ }
+
+ if (params.getJobId() == JOB_POST_BOOT_UPDATE) {
+ mAbortPostBootUpdate.set(true);
+ } else {
+ mAbortIdleOptimization.set(true);
+ }
return false;
}
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 7e25632..a11ee74 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -28,6 +28,8 @@
import dalvik.system.VMRuntime;
+import java.util.Arrays;
+
public final class Installer extends SystemService {
private static final String TAG = "Installer";
@@ -90,14 +92,14 @@
mInstaller.execute("migrate_app_data", uuid, pkgname, userid, flags);
}
- public void clearAppData(String uuid, String pkgname, int userid, int flags)
+ public void clearAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode)
throws InstallerException {
- mInstaller.execute("clear_app_data", uuid, pkgname, userid, flags);
+ mInstaller.execute("clear_app_data", uuid, pkgname, userid, flags, ceDataInode);
}
- public void destroyAppData(String uuid, String pkgname, int userid, int flags)
+ public void destroyAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode)
throws InstallerException {
- mInstaller.execute("destroy_app_data", uuid, pkgname, userid, flags);
+ mInstaller.execute("destroy_app_data", uuid, pkgname, userid, flags, ceDataInode);
}
public void moveCompleteApp(String from_uuid, String to_uuid, String package_name,
@@ -107,31 +109,26 @@
data_app_name, appid, seinfo, targetSdkVersion);
}
- public void getAppSize(String uuid, String pkgname, int userid, int flags, String apkPath,
- String libDirPath, String fwdLockApkPath, String asecPath, String[] instructionSets,
- PackageStats pStats) throws InstallerException {
- for (String instructionSet : instructionSets) {
- assertValidInstructionSet(instructionSet);
- }
-
- // TODO: Extend getSizeInfo to look at the full subdirectory tree,
- // not just the first level.
- // TODO: Extend getSizeInfo to look at *all* instrution sets, not
- // just the primary.
- final String rawRes = mInstaller.executeForResult("get_app_size", uuid, pkgname, userid,
- flags, apkPath, libDirPath, fwdLockApkPath, asecPath, instructionSets[0]);
- final String res[] = rawRes.split(" ");
-
- if ((res == null) || (res.length != 5)) {
- throw new InstallerException("Invalid size result: " + rawRes);
- }
+ public void getAppSize(String uuid, String pkgname, int userid, int flags, long ceDataInode,
+ String codePath, PackageStats stats) throws InstallerException {
+ final String[] res = mInstaller.execute("get_app_size", uuid, pkgname, userid, flags,
+ ceDataInode, codePath);
try {
- pStats.codeSize = Long.parseLong(res[1]);
- pStats.dataSize = Long.parseLong(res[2]);
- pStats.cacheSize = Long.parseLong(res[3]);
- pStats.externalCodeSize = Long.parseLong(res[4]);
- } catch (NumberFormatException e) {
- throw new InstallerException("Invalid size result: " + rawRes);
+ stats.codeSize += Long.parseLong(res[1]);
+ stats.dataSize += Long.parseLong(res[2]);
+ stats.cacheSize += Long.parseLong(res[3]);
+ } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
+ throw new InstallerException("Invalid size result: " + Arrays.toString(res));
+ }
+ }
+
+ public long getAppDataInode(String uuid, String pkgname, int userid, int flags)
+ throws InstallerException {
+ final String[] res = mInstaller.execute("get_app_data_inode", uuid, pkgname, userid, flags);
+ try {
+ return Long.parseLong(res[1]);
+ } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
+ throw new InstallerException("Invalid inode result: " + Arrays.toString(res));
}
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 4c18e15..79d9c86 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -213,8 +213,11 @@
* Checks if the caller is in the same group as the userToCheck.
*/
private void ensureInUserProfiles(UserHandle userToCheck, String message) {
+ ensureInUserProfiles(userToCheck.getIdentifier(), message);
+ }
+
+ private void ensureInUserProfiles(int targetUserId, String message) {
final int callingUserId = injectCallingUserId();
- final int targetUserId = userToCheck.getIdentifier();
if (targetUserId == callingUserId) return;
@@ -253,9 +256,13 @@
* Checks if the user is enabled.
*/
private boolean isUserEnabled(UserHandle user) {
+ return isUserEnabled(user.getIdentifier());
+ }
+
+ private boolean isUserEnabled(int userId) {
long ident = injectClearCallingIdentity();
try {
- UserInfo targetUserInfo = mUm.getUserInfo(user.getIdentifier());
+ UserInfo targetUserInfo = mUm.getUserInfo(userId);
return targetUserInfo != null && targetUserInfo.isEnabled();
} finally {
injectRestoreCallingIdentity(ident);
@@ -346,8 +353,12 @@
}
private void ensureShortcutPermission(@NonNull String callingPackage, UserHandle user) {
+ ensureShortcutPermission(callingPackage, user.getIdentifier());
+ }
+
+ private void ensureShortcutPermission(@NonNull String callingPackage, int userId) {
verifyCallingPackage(callingPackage);
- ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
+ ensureInUserProfiles(userId, "Cannot start activity for unrelated profile " + userId);
if (!mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(),
callingPackage)) {
@@ -357,32 +368,24 @@
@Override
public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
- String packageName, ComponentName componentName, int flags, UserHandle user) {
+ String packageName, List shortcutIds, ComponentName componentName, int flags,
+ UserHandle user) {
ensureShortcutPermission(callingPackage, user);
if (!isUserEnabled(user)) {
return new ParceledListSlice<>(new ArrayList(0));
}
+ if (shortcutIds != null && packageName == null) {
+ throw new IllegalArgumentException(
+ "To query by shortcut ID, package name must also be set");
+ }
return new ParceledListSlice<>(
mShortcutServiceInternal.getShortcuts(getCallingUserId(),
- callingPackage, changedSince, packageName,
+ callingPackage, changedSince, packageName, shortcutIds,
componentName, flags, user.getIdentifier()));
}
@Override
- public ParceledListSlice getShortcutInfo(String callingPackage, String packageName,
- List<String> ids, UserHandle user) {
- ensureShortcutPermission(callingPackage, user);
- if (!isUserEnabled(user)) {
- return new ParceledListSlice<>(new ArrayList(0));
- }
-
- return new ParceledListSlice<>(
- mShortcutServiceInternal.getShortcutInfo(getCallingUserId(),
- callingPackage, packageName, ids, user.getIdentifier()));
- }
-
- @Override
public void pinShortcuts(String callingPackage, String packageName, List<String> ids,
UserHandle user) {
ensureShortcutPermission(callingPackage, user);
@@ -396,27 +399,27 @@
}
@Override
- public int getShortcutIconResId(String callingPackage, ShortcutInfo shortcut,
- UserHandle user) {
- ensureShortcutPermission(callingPackage, user);
- if (!isUserEnabled(user)) {
+ public int getShortcutIconResId(String callingPackage, String packageName, String id,
+ int userId) {
+ ensureShortcutPermission(callingPackage, userId);
+ if (!isUserEnabled(userId)) {
return 0;
}
return mShortcutServiceInternal.getShortcutIconResId(getCallingUserId(),
- callingPackage, shortcut, user.getIdentifier());
+ callingPackage, packageName, id, userId);
}
@Override
- public ParcelFileDescriptor getShortcutIconFd(String callingPackage, ShortcutInfo shortcut,
- UserHandle user) {
- ensureShortcutPermission(callingPackage, user);
- if (!isUserEnabled(user)) {
+ public ParcelFileDescriptor getShortcutIconFd(String callingPackage,
+ String packageName, String id, int userId) {
+ ensureShortcutPermission(callingPackage, userId);
+ if (!isUserEnabled(userId)) {
return null;
}
return mShortcutServiceInternal.getShortcutIconFd(getCallingUserId(),
- callingPackage, shortcut, user.getIdentifier());
+ callingPackage, packageName, id, userId);
}
@Override
@@ -428,23 +431,23 @@
@Override
public boolean startShortcut(String callingPackage, String packageName, String shortcutId,
- Rect sourceBounds, Bundle startActivityOptions, UserHandle user) {
+ Rect sourceBounds, Bundle startActivityOptions, int userId) {
verifyCallingPackage(callingPackage);
- ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
+ ensureInUserProfiles(userId, "Cannot start activity for unrelated profile " + userId);
- if (!isUserEnabled(user)) {
+ if (!isUserEnabled(userId)) {
throw new IllegalStateException("Cannot start a shortcut for disabled profile "
- + user);
+ + userId);
}
// Even without the permission, pinned shortcuts are always launchable.
if (!mShortcutServiceInternal.isPinnedByCaller(getCallingUserId(),
- callingPackage, packageName, shortcutId, user.getIdentifier())) {
- ensureShortcutPermission(callingPackage, user);
+ callingPackage, packageName, shortcutId, userId)) {
+ ensureShortcutPermission(callingPackage, userId);
}
final Intent intent = mShortcutServiceInternal.createShortcutIntent(getCallingUserId(),
- callingPackage, packageName, shortcutId, user.getIdentifier());
+ callingPackage, packageName, shortcutId, userId);
if (intent == null) {
return false;
}
@@ -455,7 +458,7 @@
final long ident = Binder.clearCallingIdentity();
try {
- mContext.startActivityAsUser(intent, startActivityOptions, user);
+ mContext.startActivityAsUser(intent, startActivityOptions, UserHandle.of(userId));
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -768,7 +771,8 @@
final List<ShortcutInfo> list =
mShortcutServiceInternal.getShortcuts(launcherUserId,
cookie.packageName,
- /* changedSince= */ 0, packageName, /* component= */ null,
+ /* changedSince= */ 0, packageName, /* shortcutIds=*/ null,
+ /* component= */ null,
ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
| ShortcutQuery.FLAG_GET_PINNED
| ShortcutQuery.FLAG_GET_DYNAMIC
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index d13f472..b3ac05c 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -53,7 +53,6 @@
// TODO b/19550105 Remove error codes and use exceptions
static final int DEX_OPT_SKIPPED = 0;
static final int DEX_OPT_PERFORMED = 1;
- static final int DEX_OPT_DEFERRED = 2;
static final int DEX_OPT_FAILED = -1;
private final Installer mInstaller;
@@ -170,6 +169,8 @@
final boolean debuggable = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
boolean performedDexOpt = false;
+ boolean successfulDexOpt = true;
+
final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
for (String path : paths) {
@@ -226,15 +227,20 @@
performedDexOpt = true;
} catch (InstallerException e) {
Slog.w(TAG, "Failed to dexopt", e);
+ successfulDexOpt = false;
}
}
}
- // If we've gotten here, we're sure that no error occurred and that we haven't
- // deferred dex-opt. We've either dex-opted one more paths or instruction sets or
- // we've skipped all of them because they are up to date. In both cases this
- // package doesn't need dexopt any longer.
- return performedDexOpt ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
+ if (successfulDexOpt) {
+ // If we've gotten here, we're sure that no error occurred. We've either
+ // dex-opted one or more paths or instruction sets or we've skipped
+ // all of them because they are up to date. In both cases this package
+ // doesn't need dexopt any longer.
+ return performedDexOpt ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
+ } else {
+ return DEX_OPT_FAILED;
+ }
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 928c19f..8368185 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -862,8 +862,12 @@
IntentSender statusReceiver, int userId) {
final int callingUid = Binder.getCallingUid();
mPm.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall");
+ boolean allowSilentUninstall = true;
if ((callingUid != Process.SHELL_UID) && (callingUid != Process.ROOT_UID)) {
mAppOps.checkPackage(callingUid, callerPackageName);
+ final String installerPackageName = mPm.getInstallerPackageName(packageName);
+ allowSilentUninstall = installerPackageName != null
+ && installerPackageName.equals(callerPackageName);
}
// Check whether the caller is device owner, in which case we do it silently.
@@ -874,8 +878,8 @@
final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
statusReceiver, packageName, isDeviceOwner, userId);
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES)
- == PackageManager.PERMISSION_GRANTED) {
+ if (allowSilentUninstall && mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.DELETE_PACKAGES) == PackageManager.PERMISSION_GRANTED) {
// Sweet, call straight through!
mPm.deletePackage(packageName, adapter.getBinder(), userId, flags);
} else if (isDeviceOwner) {
@@ -901,7 +905,10 @@
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, TAG);
synchronized (mSessions) {
- mSessions.get(sessionId).setPermissionsResult(accepted);
+ PackageInstallerSession session = mSessions.get(sessionId);
+ if (session != null) {
+ session.setPermissionsResult(accepted);
+ }
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index ef53905..6cdc40f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -81,6 +81,7 @@
import java.io.FileDescriptor;
import java.io.FileFilter;
import java.io.IOException;
+import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -151,6 +152,7 @@
private String mPackageName;
private int mVersionCode;
private Signature[] mSignatures;
+ private Certificate[][] mCertificates;
/**
* Path to the validated base APK for this session, which may point at an
@@ -633,7 +635,7 @@
mRelinquished = true;
mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,
- installerPackageName, installerUid, user);
+ installerPackageName, installerUid, user, mCertificates);
}
/**
@@ -695,6 +697,7 @@
}
if (mSignatures == null) {
mSignatures = apk.signatures;
+ mCertificates = apk.certificates;
}
assertApkConsistent(String.valueOf(addedFile), apk);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 10ec6c9..fc829c3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -76,7 +76,6 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.pm.PackageParser.PARSE_IS_PRIVILEGED;
import static android.content.pm.PackageParser.isApkFile;
-import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
@@ -110,13 +109,13 @@
import android.app.admin.IDevicePolicyManager;
import android.app.admin.SecurityLog;
import android.app.backup.IBackupManager;
+import android.app.usage.UsageStatsManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.IntentFilter.AuthorityEntry;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.content.ServiceConnection;
@@ -149,7 +148,6 @@
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.ActivityIntentInfo;
-import android.content.pm.PackageParser.IntentInfo;
import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.PackageStats;
@@ -249,6 +247,7 @@
import com.android.server.pm.Settings.VersionInfo;
import com.android.server.storage.DeviceStorageMonitorInternal;
+import dalvik.system.CloseGuard;
import dalvik.system.DexFile;
import dalvik.system.VMRuntime;
@@ -277,6 +276,7 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
+import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.text.SimpleDateFormat;
@@ -299,14 +299,37 @@
import java.util.concurrent.atomic.AtomicLong;
/**
- * Keep track of all those .apks everywhere.
+ * Keep track of all those APKs everywhere.
+ * <p>
+ * Internally there are two important locks:
+ * <ul>
+ * <li>{@link #mPackages} is used to guard all in-memory parsed package details
+ * and other related state. It is a fine-grained lock that should only be held
+ * momentarily, as it's one of the most contended locks in the system.
+ * <li>{@link #mInstallLock} is used to guard all {@code installd} access, whose
+ * operations typically involve heavy lifting of application data on disk. Since
+ * {@code installd} is single-threaded, and it's operations can often be slow,
+ * this lock should never be acquired while already holding {@link #mPackages}.
+ * Conversely, it's safe to acquire {@link #mPackages} momentarily while already
+ * holding {@link #mInstallLock}.
+ * </ul>
+ * Many internal methods rely on the caller to hold the appropriate locks, and
+ * this contract is expressed through method name suffixes:
+ * <ul>
+ * <li>fooLI(): the caller must hold {@link #mInstallLock}
+ * <li>fooLIF(): the caller must hold {@link #mInstallLock} and the package
+ * being modified must be frozen
+ * <li>fooLPr(): the caller must hold {@link #mPackages} for reading
+ * <li>fooLPw(): the caller must hold {@link #mPackages} for writing
+ * </ul>
+ * <p>
+ * Because this class is very central to the platform's security; please run all
+ * CTS and unit tests whenever making modifications:
*
- * This is very central to the platform's security; please run the unit
- * tests whenever making modifications here:
- *
-runtest -c android.content.pm.PackageManagerTests frameworks-core
- *
- * {@hide}
+ * <pre>
+ * $ runtest -c android.content.pm.PackageManagerTests frameworks-core
+ * $ cts-tradefed run commandAndExit cts -m AppSecurityTests
+ * </pre>
*/
public class PackageManagerService extends IPackageManager.Stub {
static final String TAG = "PackageManager";
@@ -368,6 +391,7 @@
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 SCAN_IGNORE_FROZEN = 1<<18;
static final int REMOVE_CHATTY = 1<<16;
@@ -571,7 +595,19 @@
*/
boolean mPromoteSystemApps;
+ @GuardedBy("mPackages")
final Settings mSettings;
+
+ /**
+ * Set of package names that are currently "frozen", which means active
+ * surgery is being done on the code/data for that package. The platform
+ * will refuse to launch frozen packages to avoid race conditions.
+ *
+ * @see PackageFreezer
+ */
+ @GuardedBy("mPackages")
+ final ArraySet<String> mFrozenPackages = new ArraySet<>();
+
boolean mRestoredSettings;
// System configuration read by SystemConfig.
@@ -1064,8 +1100,9 @@
| FLAG_PERMISSION_REVOKE_ON_UPGRADE;
final @Nullable String mRequiredVerifierPackage;
- final @Nullable String mRequiredInstallerPackage;
+ final @NonNull String mRequiredInstallerPackage;
final @Nullable String mSetupWizardPackage;
+ final @NonNull String mServicesSystemSharedLibraryPackageName;
private final PackageUsage mPackageUsage = new PackageUsage();
@@ -2351,8 +2388,9 @@
if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
psit.remove();
logCriticalInfo(Log.WARN, "System package " + ps.name
- + " no longer exists; wiping its data");
- removeDataDirsLI(null, ps.name);
+ + " no longer exists; it's data will be wiped");
+ // Actual deletion of code and data will be handled by later
+ // reconciliation step
} else {
final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
@@ -2364,11 +2402,16 @@
//look for any incomplete package installations
ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
- //clean up list
- for(int i = 0; i < deletePkgsList.size(); i++) {
- //clean up here
- cleanupInstallFailedPackage(deletePkgsList.get(i));
+ for (int i = 0; i < deletePkgsList.size(); i++) {
+ // Actual deletion of code and data will be handled by later
+ // reconciliation step
+ final String packageName = deletePkgsList.get(i).name;
+ logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + packageName);
+ synchronized (mPackages) {
+ mSettings.removePackageLPw(packageName);
+ }
}
+
//delete tmp files
deleteTempPackageFiles();
@@ -2399,8 +2442,9 @@
String msg;
if (deletedPkg == null) {
msg = "Updated system package " + deletedAppName
- + " no longer exists; wiping its data";
- removeDataDirsLI(null, deletedAppName);
+ + " no longer exists; it's data will be wiped";
+ // Actual deletion of code and data will be handled by later
+ // reconciliation step
} else {
msg = "Updated system app + " + deletedAppName
+ " no longer present; removing system privileges for "
@@ -2546,7 +2590,7 @@
} else {
storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
}
- reconcileAppsData(StorageManager.UUID_PRIVATE_INTERNAL, UserHandle.USER_SYSTEM,
+ reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL, UserHandle.USER_SYSTEM,
storageFlags);
// If this is first boot after an OTA, and a normal boot, then
@@ -2556,8 +2600,12 @@
for (int i = 0; i < mSettings.mPackages.size(); i++) {
final PackageSetting ps = mSettings.mPackages.valueAt(i);
if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
- deleteCodeCacheDirsLI(ps.volumeUuid, ps.name);
+ // No apps are running this early, so no need to freeze
+ clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
+ StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
+ | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
+ clearAppProfilesLIF(ps.pkg);
}
ver.fingerprint = Build.FINGERPRINT;
}
@@ -2583,11 +2631,16 @@
mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr();
mIntentFilterVerifier = new IntentVerifierProxy(mContext,
mIntentFilterVerifierComponent);
+ mServicesSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
+ PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES);
+ getRequiredSharedLibraryLPr(
+ PackageManager.SYSTEM_SHARED_LIBRARY_SHARED);
} else {
mRequiredVerifierPackage = null;
mRequiredInstallerPackage = null;
mIntentFilterVerifierComponent = null;
mIntentFilterVerifier = null;
+ mServicesSystemSharedLibraryPackageName = null;
}
mInstallerService = new PackageInstallerService(context, this);
@@ -2667,6 +2720,16 @@
}
}
+ private @NonNull String getRequiredSharedLibraryLPr(String libraryName) {
+ synchronized (mPackages) {
+ SharedLibraryEntry libraryEntry = mSharedLibraries.get(libraryName);
+ if (libraryEntry == null) {
+ throw new IllegalStateException("Missing required shared library:" + libraryName);
+ }
+ return libraryEntry.apk;
+ }
+ }
+
private @NonNull String getRequiredInstallerLPr() {
final Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.addCategory(Intent.CATEGORY_DEFAULT);
@@ -2676,6 +2739,10 @@
MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
UserHandle.USER_SYSTEM);
if (matches.size() == 1) {
+ ResolveInfo resolveInfo = matches.get(0);
+ if (!resolveInfo.activityInfo.applicationInfo.isPrivilegedApp()) {
+ throw new RuntimeException("The installer must be a privileged app");
+ }
return matches.get(0).getComponentInfo().packageName;
} else {
throw new RuntimeException("There must be exactly one installer; found " + matches);
@@ -2922,22 +2989,6 @@
}
}
- void cleanupInstallFailedPackage(PackageSetting ps) {
- logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + ps.name);
-
- removeDataDirsLI(ps.volumeUuid, ps.name);
- if (ps.codePath != null) {
- removeCodePathLI(ps.codePath);
- }
- if (ps.resourcePath != null && !ps.resourcePath.equals(ps.codePath)) {
- if (ps.resourcePath.isDirectory()) {
- FileUtils.deleteContents(ps.resourcePath);
- }
- ps.resourcePath.delete();
- }
- mSettings.removePackageLPw(ps.name);
- }
-
static int[] appendInts(int[] cur, int[] add) {
if (add == null) return cur;
if (cur == null) return add;
@@ -2987,7 +3038,7 @@
throw new SecurityException("Package " + packageName + " not a system app!");
}
- if (ps.frozen) {
+ if (mFrozenPackages.contains(packageName)) {
throw new SecurityException("Package " + packageName + " is currently frozen!");
}
@@ -3036,7 +3087,7 @@
}
if (p == null) {
p = mPackages.get(packageName);
- if (matchFactoryOnly && !isSystemApp(p)) {
+ if (matchFactoryOnly && p != null && !isSystemApp(p)) {
return null;
}
}
@@ -3558,15 +3609,10 @@
}
@Override
- public @Nullable String getServicesSystemSharedLibraryPackageName() {
+ public @NonNull String getServicesSystemSharedLibraryPackageName() {
synchronized (mPackages) {
- SharedLibraryEntry libraryEntry = mSharedLibraries.get(
- PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES);
- if (libraryEntry != null) {
- return libraryEntry.apk;
- }
+ return mServicesSystemSharedLibraryPackageName;
}
- return null;
}
@Override
@@ -4389,6 +4435,13 @@
}
}
+ /**
+ * This method should typically only be used when granting or revoking
+ * permissions, since the app may immediately restart after this call.
+ * <p>
+ * If you're doing surgery on app code/data, use {@link PackageFreezer} to
+ * guard your work against the app being relaunched.
+ */
private void killUid(int appId, int userId, String reason) {
final long identity = Binder.clearCallingIdentity();
try {
@@ -6786,7 +6839,10 @@
!= PackageManager.SIGNATURE_MATCH) {
logCriticalInfo(Log.WARN, "Package " + ps.name + " appeared on system, but"
+ " signatures don't match existing userdata copy; removing");
- deletePackageLI(pkg.packageName, null, true, null, 0, null, false, null);
+ try (PackageFreezer freezer = freezePackage(pkg.packageName,
+ "scanPackageInternalLI")) {
+ deletePackageLIF(pkg.packageName, null, true, null, 0, null, false, null);
+ }
ps = null;
} else {
/*
@@ -7005,11 +7061,28 @@
pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this);
}
+ UsageStatsManager usageMgr =
+ (UsageStatsManager) mContext.getSystemService(Context.USAGE_STATS_SERVICE);
+
int curr = 0;
int total = pkgs.size();
for (PackageParser.Package pkg : pkgs) {
curr++;
+ if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Skipping update of of non-optimizable app " + pkg.packageName);
+ }
+ continue;
+ }
+
+ if (!causeFirstBoot && usageMgr.isAppInactive(pkg.packageName)) {
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Skipping update of of idle app " + pkg.packageName);
+ }
+ continue;
+ }
+
if (DEBUG_DEXOPT) {
Log.i(TAG, "Extracting app " + curr + " of " + total + ": " + pkg.packageName);
}
@@ -7023,16 +7096,11 @@
}
}
- if (PackageDexOptimizer.canOptimizePackage(pkg)) {
- // If the cache was pruned, any compiled odex files will likely be out of date
- // and would have to be patched (would be SELF_PATCHOAT, which is deprecated).
- // Instead, force the extraction in this case.
- performDexOpt(pkg.packageName,
- null /* instructionSet */,
- false /* checkProfiles */,
- causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT,
- false /* force */);
- }
+ performDexOpt(pkg.packageName,
+ null /* instructionSet */,
+ false /* checkProfiles */,
+ causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT,
+ false /* force */);
}
}
@@ -7079,6 +7147,8 @@
}
}
+ // Run dexopt on a given package. Returns true if dexopt did not fail, i.e.
+ // if the package can now be considered up to date for the given filter.
private boolean performDexOptInternal(String packageName, String instructionSet,
boolean checkProfiles, String targetCompilerFilter, boolean force) {
PackageParser.Package p;
@@ -7099,7 +7169,7 @@
final String[] instructionSets = new String[] { targetInstructionSet };
int result = performDexOptInternalWithDependenciesLI(p, instructionSets,
checkProfiles, targetCompilerFilter, force);
- return result == PackageDexOptimizer.DEX_OPT_PERFORMED;
+ return result != PackageDexOptimizer.DEX_OPT_FAILED;
}
} finally {
Binder.restoreCallingIdentity(callingId);
@@ -7243,23 +7313,6 @@
return true;
}
- private boolean removeDataDirsLI(String volumeUuid, String packageName) {
- // TODO: triage flags as part of 26466827
- final int flags = StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE;
-
- boolean res = true;
- final int[] users = sUserManager.getUserIds();
- for (int user : users) {
- try {
- mInstaller.destroyAppData(volumeUuid, packageName, user, flags);
- } catch (InstallerException e) {
- Slog.w(TAG, "Failed to delete data directory", e);
- res = false;
- }
- }
- return res;
- }
-
void removeCodePathLI(File codePath) {
if (codePath.isDirectory()) {
try {
@@ -7272,87 +7325,106 @@
}
}
- void destroyAppDataLI(String volumeUuid, String packageName, int userId, int flags) {
- try {
- mInstaller.destroyAppData(volumeUuid, packageName, userId, flags);
- } catch (InstallerException e) {
- Slog.w(TAG, "Failed to destroy app data", e);
- }
+ private int[] resolveUserIds(int userId) {
+ return (userId == UserHandle.USER_ALL) ? sUserManager.getUserIds() : new int[] { userId };
}
- void restoreconAppDataLI(String volumeUuid, String packageName, int userId, int flags,
- int appId, String seinfo) {
- try {
- mInstaller.restoreconAppData(volumeUuid, packageName, userId, flags, appId, seinfo);
- } catch (InstallerException e) {
- Slog.e(TAG, "Failed to restorecon for " + packageName + ": " + e);
- }
- }
-
- private void deleteProfilesLI(String packageName, boolean destroy) {
- final PackageParser.Package pkg;
- synchronized (mPackages) {
- pkg = mPackages.get(packageName);
- }
+ private void clearAppDataLIF(PackageParser.Package pkg, int userId, int flags) {
if (pkg == null) {
- Slog.w(TAG, "Failed to delete profiles. No package: " + packageName);
+ Slog.wtf(TAG, "Package was null!", new Throwable());
return;
}
- deleteProfilesLI(pkg, destroy);
- }
-
- private void deleteProfilesLI(PackageParser.Package pkg, boolean destroy) {
- try {
- if (destroy) {
- mInstaller.destroyAppProfiles(pkg.packageName);
- } else {
- mInstaller.clearAppProfiles(pkg.packageName);
- }
- } catch (InstallerException ex) {
- Log.e(TAG, "Could not delete profiles for package " + pkg.packageName);
+ clearAppDataLeafLIF(pkg, userId, flags);
+ final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+ for (int i = 0; i < childCount; i++) {
+ clearAppDataLeafLIF(pkg.childPackages.get(i), userId, flags);
}
}
- private void deleteCodeCacheDirsLI(String volumeUuid, String packageName) {
- final PackageParser.Package pkg;
+ private void clearAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {
+ final PackageSetting ps;
synchronized (mPackages) {
- pkg = mPackages.get(packageName);
+ ps = mSettings.mPackages.get(pkg.packageName);
}
- if (pkg == null) {
- Slog.w(TAG, "Failed to delete code cache directory. No package: " + packageName);
- return;
- }
- deleteCodeCacheDirsLI(pkg);
- }
-
- private void deleteCodeCacheDirsLI(PackageParser.Package pkg) {
- // TODO: triage flags as part of 26466827
- final int flags = StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE;
-
- int[] users = sUserManager.getUserIds();
- int res = 0;
- for (int user : users) {
- // Remove the parent code cache
+ for (int realUserId : resolveUserIds(userId)) {
+ final long ceDataInode = (ps != null) ? ps.getCeDataInode(realUserId) : 0;
try {
- mInstaller.clearAppData(pkg.volumeUuid, pkg.packageName, user,
- flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ mInstaller.clearAppData(pkg.volumeUuid, pkg.packageName, realUserId, flags,
+ ceDataInode);
} catch (InstallerException e) {
- Slog.w(TAG, "Failed to delete code cache directory", e);
+ Slog.w(TAG, String.valueOf(e));
}
- final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
- for (int i = 0; i < childCount; i++) {
- PackageParser.Package childPkg = pkg.childPackages.get(i);
- // Remove the child code cache
- try {
- mInstaller.clearAppData(childPkg.volumeUuid, childPkg.packageName,
- user, flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
- } catch (InstallerException e) {
- Slog.w(TAG, "Failed to delete code cache directory", e);
- }
+ }
+ }
+
+ private void destroyAppDataLIF(PackageParser.Package pkg, int userId, int flags) {
+ if (pkg == null) {
+ Slog.wtf(TAG, "Package was null!", new Throwable());
+ return;
+ }
+ destroyAppDataLeafLIF(pkg, userId, flags);
+ final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+ for (int i = 0; i < childCount; i++) {
+ destroyAppDataLeafLIF(pkg.childPackages.get(i), userId, flags);
+ }
+ }
+
+ private void destroyAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {
+ final PackageSetting ps;
+ synchronized (mPackages) {
+ ps = mSettings.mPackages.get(pkg.packageName);
+ }
+ for (int realUserId : resolveUserIds(userId)) {
+ final long ceDataInode = (ps != null) ? ps.getCeDataInode(realUserId) : 0;
+ try {
+ mInstaller.destroyAppData(pkg.volumeUuid, pkg.packageName, realUserId, flags,
+ ceDataInode);
+ } catch (InstallerException e) {
+ Slog.w(TAG, String.valueOf(e));
}
}
}
+ private void destroyAppProfilesLIF(PackageParser.Package pkg) {
+ if (pkg == null) {
+ Slog.wtf(TAG, "Package was null!", new Throwable());
+ return;
+ }
+ destroyAppProfilesLeafLIF(pkg);
+ final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+ for (int i = 0; i < childCount; i++) {
+ destroyAppProfilesLeafLIF(pkg.childPackages.get(i));
+ }
+ }
+
+ private void destroyAppProfilesLeafLIF(PackageParser.Package pkg) {
+ try {
+ mInstaller.destroyAppProfiles(pkg.packageName);
+ } catch (InstallerException e) {
+ Slog.w(TAG, String.valueOf(e));
+ }
+ }
+
+ private void clearAppProfilesLIF(PackageParser.Package pkg) {
+ if (pkg == null) {
+ Slog.wtf(TAG, "Package was null!", new Throwable());
+ return;
+ }
+ clearAppProfilesLeafLIF(pkg);
+ final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+ for (int i = 0; i < childCount; i++) {
+ clearAppProfilesLeafLIF(pkg.childPackages.get(i));
+ }
+ }
+
+ private void clearAppProfilesLeafLIF(PackageParser.Package pkg) {
+ try {
+ mInstaller.clearAppProfiles(pkg.packageName);
+ } catch (InstallerException e) {
+ Slog.w(TAG, String.valueOf(e));
+ }
+ }
+
private void setInstallAndUpdateTime(PackageParser.Package pkg, long firstInstallTime,
long lastUpdateTime) {
// Set parent install/update time
@@ -7538,7 +7610,10 @@
return res;
} finally {
if (!success && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
- removeDataDirsLI(pkg.volumeUuid, pkg.packageName);
+ // DELETE_DATA_ON_FAILURES is only used by frozen paths
+ destroyAppDataLIF(pkg, UserHandle.USER_ALL,
+ StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
+ destroyAppProfilesLIF(pkg);
}
}
}
@@ -8095,20 +8170,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.
- 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");
-
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
+ if ((scanFlags & SCAN_BOOTING) != 0) {
+ // No apps can run during boot scan, so they don't need to be frozen
+ } else if ((scanFlags & SCAN_DONT_KILL_APP) != 0) {
+ // Caller asked to not kill app, so it's probably not frozen
+ } else if ((scanFlags & SCAN_IGNORE_FROZEN) != 0) {
+ // Caller asked us to ignore frozen check for some reason; they
+ // probably didn't know the package name
+ } else {
+ // We're doing major surgery on this package, so it better be frozen
+ // right now to keep it from launching
+ checkPackageFrozen(pkgName);
}
// Also need to kill any apps that are dependent on the library.
@@ -8579,7 +8651,7 @@
if (abi32 >= 0) {
final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32];
if (abi64 >= 0) {
- if (cpuAbiOverride == null && pkg.use32bitAbi) {
+ if (pkg.use32bitAbi) {
pkg.applicationInfo.secondaryCpuAbi = pkg.applicationInfo.primaryCpuAbi;
pkg.applicationInfo.primaryCpuAbi = abi;
} else {
@@ -8975,27 +9047,21 @@
}
}
- private void killPackage(PackageParser.Package pkg, String reason) {
- // Kill the parent package
- killApplication(pkg.packageName, pkg.applicationInfo.uid, reason);
- // Kill the child packages
- final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
- for (int i = 0; i < childCount; i++) {
- PackageParser.Package childPkg = pkg.childPackages.get(i);
- killApplication(childPkg.packageName, childPkg.applicationInfo.uid, reason);
- }
- }
-
private void killApplication(String pkgName, int appId, String reason) {
// 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.
- IActivityManager am = ActivityManagerNative.getDefault();
- if (am != null) {
- try {
- am.killApplicationWithAppId(pkgName, appId, reason);
- } catch (RemoteException e) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ IActivityManager am = ActivityManagerNative.getDefault();
+ if (am != null) {
+ try {
+ am.killApplicationWithAppId(pkgName, appId, reason);
+ } catch (RemoteException e) {
+ }
}
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
@@ -10964,7 +11030,8 @@
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*/);
+ null /*packageAbiOverride*/, null /*grantedPermissions*/,
+ null /*certificates*/);
params.setTraceMethod("installAsUser").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
@@ -10978,7 +11045,8 @@
void installStage(String packageName, File stagedDir, String stagedCid,
IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
- String installerPackageName, int installerUid, UserHandle user) {
+ String installerPackageName, int installerUid, UserHandle user,
+ Certificate[][] certificates) {
if (DEBUG_EPHEMERAL) {
if ((sessionParams.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0) {
Slog.d(TAG, "Ephemeral install of " + packageName);
@@ -10999,7 +11067,7 @@
final InstallParams params = new InstallParams(origin, null, observer,
sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
verificationInfo, user, sessionParams.abiOverride,
- sessionParams.grantedRuntimePermissions);
+ sessionParams.grantedRuntimePermissions, certificates);
params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
@@ -11177,7 +11245,10 @@
if (installed) {
if (pkgSetting.pkg != null) {
- prepareAppDataAfterInstall(pkgSetting.pkg);
+ synchronized (mInstallLock) {
+ // We don't need to freeze for a brand new install
+ prepareAppDataAfterInstallLIF(pkgSetting.pkg);
+ }
}
sendPackageAddedForUser(packageName, pkgSetting, userId);
}
@@ -11726,6 +11797,9 @@
// Okay!
targetPackageSetting.installerPackageName = installerPackageName;
+ if (installerPackageName != null) {
+ mSettings.mInstallerPackages.add(installerPackageName);
+ }
scheduleWriteSettingsLocked();
}
}
@@ -12094,11 +12168,12 @@
final String packageAbiOverride;
final String[] grantedRuntimePermissions;
final VerificationInfo verificationInfo;
+ final Certificate[][] certificates;
InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
int installFlags, String installerPackageName, String volumeUuid,
VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride,
- String[] grantedPermissions) {
+ String[] grantedPermissions, Certificate[][] certificates) {
super(user);
this.origin = origin;
this.move = move;
@@ -12109,6 +12184,7 @@
this.verificationInfo = verificationInfo;
this.packageAbiOverride = packageAbiOverride;
this.grantedRuntimePermissions = grantedPermissions;
+ this.certificates = certificates;
}
@Override
@@ -12577,6 +12653,7 @@
/** If non-null, drop an async trace when the install completes */
final String traceMethod;
final int traceCookie;
+ final Certificate[][] certificates;
// The list of instruction sets supported by this app. This is currently
// only used during the rmdex() phase to clean up resources. We can get rid of this
@@ -12587,7 +12664,7 @@
int installFlags, String installerPackageName, String volumeUuid,
UserHandle user, String[] instructionSets,
String abiOverride, String[] installGrantPermissions,
- String traceMethod, int traceCookie) {
+ String traceMethod, int traceCookie, Certificate[][] certificates) {
this.origin = origin;
this.move = move;
this.installFlags = installFlags;
@@ -12600,6 +12677,7 @@
this.installGrantPermissions = installGrantPermissions;
this.traceMethod = traceMethod;
this.traceCookie = traceCookie;
+ this.certificates = certificates;
}
abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
@@ -12692,9 +12770,9 @@
FileInstallArgs(InstallParams params) {
super(params.origin, params.move, params.observer, params.installFlags,
params.installerPackageName, params.volumeUuid,
- params.getUser(), null /* instruction sets */, params.packageAbiOverride,
+ params.getUser(), null /*instructionSets*/, params.packageAbiOverride,
params.grantedRuntimePermissions,
- params.traceMethod, params.traceCookie);
+ params.traceMethod, params.traceCookie, params.certificates);
if (isFwdLocked()) {
throw new IllegalArgumentException("Forward locking only supported in ASEC");
}
@@ -12703,7 +12781,7 @@
/** Existing install */
FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {
super(OriginInfo.fromNothing(), null, null, 0, null, null, null, instructionSets,
- null, null, null, 0);
+ null, null, null, 0, null /*certificates*/);
this.codeFile = (codePath != null) ? new File(codePath) : null;
this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
}
@@ -12928,15 +13006,15 @@
params.installerPackageName, params.volumeUuid,
params.getUser(), null /* instruction sets */, params.packageAbiOverride,
params.grantedRuntimePermissions,
- params.traceMethod, params.traceCookie);
+ params.traceMethod, params.traceCookie, params.certificates);
}
/** Existing install */
AsecInstallArgs(String fullCodePath, String[] instructionSets,
boolean isExternal, boolean isForwardLocked) {
super(OriginInfo.fromNothing(), null, null, (isExternal ? INSTALL_EXTERNAL : 0)
- | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
- instructionSets, null, null, null, 0);
+ | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
+ instructionSets, null, null, null, 0, null /*certificates*/);
// Hackily pretend we're still looking at a full code path
if (!fullCodePath.endsWith(RES_FILE_NAME)) {
fullCodePath = new File(fullCodePath, RES_FILE_NAME).getAbsolutePath();
@@ -12952,8 +13030,8 @@
AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked) {
super(OriginInfo.fromNothing(), null, null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0)
- | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
- instructionSets, null, null, null, 0);
+ | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
+ instructionSets, null, null, null, 0, null /*certificates*/);
this.cid = cid;
setMountPath(PackageHelper.getSdDir(cid));
}
@@ -13222,7 +13300,7 @@
params.installerPackageName, params.volumeUuid,
params.getUser(), null /* instruction sets */, params.packageAbiOverride,
params.grantedRuntimePermissions,
- params.traceMethod, params.traceCookie);
+ params.traceMethod, params.traceCookie, params.certificates);
}
int copyApk(IMediaContainerService imcs, boolean temp) {
@@ -13295,7 +13373,13 @@
Slog.d(TAG, "Cleaning up " + move.packageName + " on " + volumeUuid);
synchronized (mInstallLock) {
// Clean up both app data and code
- removeDataDirsLI(volumeUuid, move.packageName);
+ // All package moves are frozen until finished
+ try {
+ mInstaller.destroyAppData(volumeUuid, move.packageName, UserHandle.USER_ALL,
+ StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE, 0);
+ } catch (InstallerException e) {
+ Slog.w(TAG, String.valueOf(e));
+ }
removeCodePathLI(codeFile);
}
return true;
@@ -13440,7 +13524,7 @@
/*
* Install a non-existing package.
*/
- private void installNewPackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags,
+ private void installNewPackageLIF(PackageParser.Package pkg, int parseFlags, int scanFlags,
UserHandle user, String installerPackageName, String volumeUuid,
PackageInstalledInfo res) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");
@@ -13476,12 +13560,12 @@
updateSettingsLI(newPackage, installerPackageName, null, res, user);
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
- prepareAppDataAfterInstall(newPackage);
+ prepareAppDataAfterInstallLIF(newPackage);
} else {
// Remove package from internal structures, but keep around any
// data that might have already existed
- deletePackageLI(pkgName, UserHandle.ALL, false, null,
+ deletePackageLIF(pkgName, UserHandle.ALL, false, null,
PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null);
}
} catch (PackageManagerException e) {
@@ -13527,14 +13611,13 @@
return false;
}
- private void replacePackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags,
+ private void replacePackageLIF(PackageParser.Package pkg, int parseFlags, int scanFlags,
UserHandle user, String installerPackageName, PackageInstalledInfo res) {
final boolean isEphemeral = (parseFlags & PackageParser.PARSE_IS_EPHEMERAL) != 0;
final PackageParser.Package oldPackage;
final String pkgName = pkg.packageName;
final int[] allUsers;
- final boolean weFroze;
// First find the old package info and check signatures
synchronized(mPackages) {
@@ -13577,32 +13660,8 @@
// In case of rollback, remember per-user/profile install state
allUsers = sUserManager.getUserIds();
-
- // Mark the app as frozen to prevent launching during the upgrade
- // process, and then kill all running instances
- if (!ps.frozen) {
- ps.frozen = true;
- weFroze = true;
- } else {
- weFroze = false;
- }
}
- try {
- replacePackageDirtyLI(pkg, oldPackage, parseFlags, scanFlags, user, allUsers,
- installerPackageName, res);
- } finally {
- // Regardless of success or failure of upgrade steps above, always
- // unfreeze the package if we froze it
- if (weFroze) {
- unfreezePackage(pkgName);
- }
- }
- }
-
- private void replacePackageDirtyLI(PackageParser.Package pkg, PackageParser.Package oldPackage,
- int parseFlags, int scanFlags, UserHandle user, int[] allUsers,
- String installerPackageName, PackageInstalledInfo res) {
// Update what is removed
res.removedInfo = new PackageRemovedInfo();
res.removedInfo.uid = oldPackage.applicationInfo.uid;
@@ -13642,10 +13701,10 @@
boolean sysPkg = (isSystemApp(oldPackage));
if (sysPkg) {
- replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags,
+ replaceSystemPackageLIF(oldPackage, pkg, parseFlags, scanFlags,
user, allUsers, installerPackageName, res);
} else {
- replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags,
+ replaceNonSystemPackageLIF(oldPackage, pkg, parseFlags, scanFlags,
user, allUsers, installerPackageName, res);
}
}
@@ -13659,7 +13718,7 @@
return result;
}
- private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
+ private void replaceNonSystemPackageLIF(PackageParser.Package deletedPackage,
PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user,
int[] allUsers, String installerPackageName, PackageInstalledInfo res) {
if (DEBUG_INSTALL) Slog.d(TAG, "replaceNonSystemPackageLI: new=" + pkg + ", old="
@@ -13677,7 +13736,7 @@
? ((PackageSetting)pkg.mExtras).lastUpdateTime : 0;
// First delete the existing package while retaining the data directory
- if (!deletePackageLI(pkgName, null, true, allUsers, deleteFlags,
+ if (!deletePackageLIF(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");
@@ -13697,8 +13756,9 @@
sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null);
}
- deleteCodeCacheDirsLI(pkg);
- deleteProfilesLI(pkg, /*destroy*/ false);
+ clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE
+ | StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ clearAppProfilesLIF(pkg);
try {
final PackageParser.Package newPackage = scanPackageTracedLI(pkg, parseFlags,
@@ -13725,7 +13785,7 @@
childPs.oldCodePaths = ps.oldCodePaths;
}
}
- prepareAppDataAfterInstall(newPackage);
+ prepareAppDataAfterInstallLIF(newPackage);
addedPkg = true;
} catch (PackageManagerException e) {
res.setError("Package couldn't be installed in " + pkg.codePath, e);
@@ -13737,7 +13797,7 @@
// Revert all internal state mutations and added folders for the failed install
if (addedPkg) {
- deletePackageLI(pkgName, null, true, allUsers, deleteFlags,
+ deletePackageLIF(pkgName, null, true, allUsers, deleteFlags,
res.removedInfo, true, null);
}
@@ -13797,7 +13857,7 @@
}
}
- private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
+ private void replaceSystemPackageLIF(PackageParser.Package deletedPackage,
PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user,
int[] allUsers, String installerPackageName, PackageInstalledInfo res) {
if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
@@ -13812,9 +13872,6 @@
parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
}
- // Kill package processes including services, providers, etc.
- killPackage(deletedPackage, "replace sys pkg");
-
// Remove existing system package
removePackageLI(deletedPackage, true);
@@ -13832,8 +13889,9 @@
}
// Successfully disabled the old package. Now proceed with re-installation
- deleteCodeCacheDirsLI(pkg);
- deleteProfilesLI(pkg, /*destroy*/ false);
+ clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE
+ | StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ clearAppProfilesLIF(pkg);
res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
pkg.setApplicationInfoFlags(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP,
@@ -13873,14 +13931,14 @@
if (ps != null && res.removedInfo.removedChildPackages != null) {
PackageRemovedInfo removedChildRes = res.removedInfo
.removedChildPackages.get(deletedChildPkg.packageName);
- removePackageDataLI(ps, allUsers, removedChildRes, 0, false);
+ removePackageDataLIF(ps, allUsers, removedChildRes, 0, false);
removedChildRes.removedForAllUsers = mPackages.get(ps.name) == null;
}
}
}
updateSettingsLI(newPackage, installerPackageName, allUsers, res, user);
- prepareAppDataAfterInstall(newPackage);
+ prepareAppDataAfterInstallLIF(newPackage);
}
} catch (PackageManagerException e) {
res.setReturnCode(INSTALL_FAILED_INTERNAL_ERROR);
@@ -14262,7 +14320,18 @@
}
try {
- PackageParser.collectCertificates(pkg, parseFlags);
+ // either use what we've been given or parse directly from the APK
+ if (args.certificates != null) {
+ try {
+ PackageParser.populateCertificates(pkg, args.certificates);
+ } catch (PackageParserException e) {
+ // there was something wrong with the certificates we were given;
+ // try to pull them from the APK
+ PackageParser.collectCertificates(pkg, parseFlags);
+ }
+ } else {
+ PackageParser.collectCertificates(pkg, parseFlags);
+ }
} catch (PackageParserException e) {
res.setError("Failed collect during installPackageLI", e);
return;
@@ -14448,7 +14517,6 @@
return;
}
-
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
// Do not run PackageDexOptimizer through the local performDexOpt
// method because `pkg` is not in `mPackages` yet.
@@ -14456,10 +14524,15 @@
false /* checkProfiles */, getCompilerFilterForReason(REASON_INSTALL));
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
- String msg = "Extracking package failed for " + pkgName;
+ String msg = "Extracting package failed for " + pkgName;
res.setError(INSTALL_FAILED_DEXOPT, msg);
return;
}
+
+ // Notify BackgroundDexOptService that the package has been changed.
+ // If this is an update of a package which used to fail to compile,
+ // BDOS will remove it from its blacklist.
+ BackgroundDexOptService.notifyPackageChanged(pkg.packageName);
}
if (!args.doRename(res.returnCode, pkg, oldCodePath)) {
@@ -14469,12 +14542,15 @@
startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg);
- if (replace) {
- replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
- installerPackageName, res);
- } else {
- installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
- args.user, installerPackageName, volumeUuid, res);
+ try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,
+ "installPackageLI")) {
+ if (replace) {
+ replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
+ installerPackageName, res);
+ } else {
+ installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
+ args.user, installerPackageName, volumeUuid, res);
+ }
}
synchronized (mPackages) {
final PackageSetting ps = mSettings.mPackages.get(pkgName);
@@ -14722,13 +14798,13 @@
@Override
public void deletePackage(final String packageName,
- final IPackageDeleteObserver2 observer, final int userId, final int flags) {
+ final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DELETE_PACKAGES, null);
Preconditions.checkNotNull(packageName);
Preconditions.checkNotNull(observer);
final int uid = Binder.getCallingUid();
- final boolean deleteAllUsers = (flags & PackageManager.DELETE_ALL_USERS) != 0;
+ final boolean deleteAllUsers = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0;
final int[] users = deleteAllUsers ? sUserManager.getUserIds() : new int[]{ userId };
if (UserHandle.getUserId(uid) != userId || (deleteAllUsers && users.length > 1)) {
mContext.enforceCallingOrSelfPermission(
@@ -14764,15 +14840,15 @@
mHandler.removeCallbacks(this);
int returnCode;
if (!deleteAllUsers) {
- returnCode = deletePackageX(packageName, userId, flags);
+ returnCode = deletePackageX(packageName, userId, deleteFlags);
} 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);
+ returnCode = deletePackageX(packageName, userId, deleteFlags);
} else {
// Otherwise uninstall individually for users with blockUninstalls=false
- final int userFlags = flags & ~PackageManager.DELETE_ALL_USERS;
+ final int userFlags = deleteFlags & ~PackageManager.DELETE_ALL_USERS;
for (int userId : users) {
if (!ArrayUtils.contains(blockUninstallUserIds, userId)) {
returnCode = deletePackageX(packageName, userId, userFlags);
@@ -14853,7 +14929,7 @@
* This method is an internal method that could be get invoked either
* to delete an installed package or to clean up a failed installation.
* After deleting an installed package, a broadcast is sent to notify any
- * listeners that the package has been installed. For cleaning up a failed
+ * listeners that the package has been removed. For cleaning up a failed
* installation, the broadcast is not necessary since the package's
* installation wouldn't have sent the initial broadcast either
* The key steps in deleting a package are
@@ -14863,11 +14939,11 @@
* persisting settings for later use
* sending a broadcast if necessary
*/
- private int deletePackageX(String packageName, int userId, int flags) {
+ private int deletePackageX(String packageName, int userId, int deleteFlags) {
final PackageRemovedInfo info = new PackageRemovedInfo();
final boolean res;
- final UserHandle removeForUser = (flags & PackageManager.DELETE_ALL_USERS) != 0
+ final UserHandle removeForUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0
? UserHandle.ALL : new UserHandle(userId);
if (isPackageDeviceAdmin(packageName, removeForUser.getIdentifier())) {
@@ -14892,8 +14968,11 @@
synchronized (mInstallLock) {
if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
- res = deletePackageLI(packageName, removeForUser, true, allUsers,
- flags | REMOVE_CHATTY, info, true, null);
+ try (PackageFreezer freezer = freezePackageForDelete(packageName, deleteFlags,
+ "deletePackageX")) {
+ res = deletePackageLIF(packageName, removeForUser, true, allUsers,
+ deleteFlags | REMOVE_CHATTY, info, true, null);
+ }
synchronized (mPackages) {
if (res) {
mEphemeralApplicationRegistry.onPackageUninstalledLPw(uninstalledPs.pkg);
@@ -14902,7 +14981,7 @@
}
if (res) {
- final boolean killApp = (flags & PackageManager.INSTALL_DONT_KILL_APP) == 0;
+ final boolean killApp = (deleteFlags & PackageManager.DELETE_DONT_KILL_APP) == 0;
info.sendPackageRemovedBroadcasts(killApp);
info.sendSystemPackageUpdatedBroadcasts();
info.sendSystemPackageAppearedBroadcasts();
@@ -15012,15 +15091,16 @@
* make sure this flag is set for partially installed apps. If not its meaningless to
* delete a partially installed application.
*/
- private void removePackageDataLI(PackageSetting ps, int[] allUserHandles,
+ private void removePackageDataLIF(PackageSetting ps, int[] allUserHandles,
PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
String packageName = ps.name;
if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + ps);
- removePackageLI(ps, (flags&REMOVE_CHATTY) != 0);
// Retrieve object to delete permissions for shared user later on
+ final PackageParser.Package deletedPkg;
final PackageSetting deletedPs;
// reader
synchronized (mPackages) {
+ deletedPkg = mPackages.get(packageName);
deletedPs = mSettings.mPackages.get(packageName);
if (outInfo != null) {
outInfo.removedPackage = packageName;
@@ -15029,13 +15109,19 @@
: null;
}
}
- if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
- removeDataDirsLI(ps.volumeUuid, packageName);
+
+ removePackageLI(ps, (flags & REMOVE_CHATTY) != 0);
+
+ if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
+ destroyAppDataLIF(deletedPkg, UserHandle.USER_ALL,
+ StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
+ destroyAppProfilesLIF(deletedPkg);
if (outInfo != null) {
outInfo.dataRemoved = true;
}
schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);
}
+
// writer
synchronized (mPackages) {
if (deletedPs != null) {
@@ -15115,7 +15201,7 @@
/*
* Tries to delete system package.
*/
- private boolean deleteSystemPackageLI(PackageParser.Package deletedPkg,
+ private boolean deleteSystemPackageLIF(PackageParser.Package deletedPkg,
PackageSetting deletedPs, int[] allUserHandles, int flags, PackageRemovedInfo outInfo,
boolean writeSettings) {
if (deletedPs.parentPackageName != null) {
@@ -15180,7 +15266,7 @@
flags |= PackageManager.DELETE_KEEP_DATA;
}
- boolean ret = deleteInstalledPackageLI(deletedPs, true, flags, allUserHandles,
+ boolean ret = deleteInstalledPackageLIF(deletedPs, true, flags, allUserHandles,
outInfo, writeSettings, disabledPs.pkg);
if (!ret) {
return false;
@@ -15210,7 +15296,7 @@
return false;
}
- prepareAppDataAfterInstall(newPkg);
+ prepareAppDataAfterInstallLIF(newPkg);
// writer
synchronized (mPackages) {
@@ -15248,7 +15334,7 @@
return true;
}
- private boolean deleteInstalledPackageLI(PackageSetting ps,
+ private boolean deleteInstalledPackageLIF(PackageSetting ps,
boolean deleteCodeAndResources, int flags, int[] allUserHandles,
PackageRemovedInfo outInfo, boolean writeSettings,
PackageParser.Package replacingPackage) {
@@ -15276,7 +15362,7 @@
}
// Delete package data from internal structures and also remove data if flag is set
- removePackageDataLI(ps, allUserHandles, outInfo, flags, writeSettings);
+ removePackageDataLIF(ps, allUserHandles, outInfo, flags, writeSettings);
// Delete the child packages data
final int childCount = (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0;
@@ -15293,7 +15379,7 @@
&& (replacingPackage != null
&& !replacingPackage.hasChildPackage(childPs.name))
? flags & ~DELETE_KEEP_DATA : flags;
- removePackageDataLI(childPs, allUserHandles, childOutInfo,
+ removePackageDataLIF(childPs, allUserHandles, childOutInfo,
deleteFlags, writeSettings);
}
}
@@ -15370,7 +15456,7 @@
/*
* This method handles package deletion in general
*/
- private boolean deletePackageLI(String packageName, UserHandle user,
+ private boolean deletePackageLIF(String packageName, UserHandle user,
boolean deleteCodeAndResources, int[] allUserHandles, int flags,
PackageRemovedInfo outInfo, boolean writeSettings,
PackageParser.Package replacingPackage) {
@@ -15398,7 +15484,7 @@
}
final int removedUserId = (user != null) ? user.getIdentifier()
: UserHandle.USER_ALL;
- if (!clearPackageStateForUser(ps, removedUserId, outInfo)) {
+ if (!clearPackageStateForUserLIF(ps, removedUserId, outInfo)) {
return false;
}
markPackageUninstalledForUserLPw(ps, user);
@@ -15424,7 +15510,7 @@
// we need to do is clear this user's data and save that
// it is uninstalled.
if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users");
- if (!clearPackageStateForUser(ps, user.getIdentifier(), outInfo)) {
+ if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
return false;
}
scheduleWritePackageRestrictionsLocked(user);
@@ -15441,7 +15527,7 @@
// we need to do is clear this user's data and save that
// it is uninstalled.
if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
- if (!clearPackageStateForUser(ps, user.getIdentifier(), outInfo)) {
+ if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
return false;
}
scheduleWritePackageRestrictionsLocked(user);
@@ -15473,15 +15559,10 @@
if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package: " + ps.name);
// When an updated system application is deleted we delete the existing resources
// as well and fall back to existing code in system partition
- ret = deleteSystemPackageLI(ps.pkg, ps, allUserHandles, flags, outInfo, writeSettings);
+ ret = deleteSystemPackageLIF(ps.pkg, ps, allUserHandles, flags, outInfo, writeSettings);
} else {
if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package: " + ps.name);
- // Kill application pre-emptively especially for apps on sd.
- final boolean killApp = (flags & PackageManager.DELETE_DONT_KILL_APP) == 0;
- if (killApp) {
- killApplication(packageName, ps.appId, "uninstall pkg");
- }
- ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags, allUserHandles,
+ ret = deleteInstalledPackageLIF(ps, deleteCodeAndResources, flags, allUserHandles,
outInfo, writeSettings, replacingPackage);
}
@@ -15541,7 +15622,7 @@
if (DEBUG_REMOVE) {
Slog.d(TAG, "Marking package:" + ps.name + " uninstalled for user:" + nextUserId);
}
- ps.setUserState(nextUserId, COMPONENT_ENABLED_STATE_DEFAULT,
+ ps.setUserState(nextUserId, 0, COMPONENT_ENABLED_STATE_DEFAULT,
false /*installed*/, true /*stopped*/, true /*notLaunched*/,
false /*hidden*/, false /*suspended*/, null, null, null,
false /*blockUninstall*/,
@@ -15549,8 +15630,13 @@
}
}
- private boolean clearPackageStateForUser(PackageSetting ps, int userId,
+ private boolean clearPackageStateForUserLIF(PackageSetting ps, int userId,
PackageRemovedInfo outInfo) {
+ final PackageParser.Package pkg;
+ synchronized (mPackages) {
+ pkg = mPackages.get(ps.name);
+ }
+
final int[] userIds = (userId == UserHandle.USER_ALL) ? sUserManager.getUserIds()
: new int[] {userId};
for (int nextUserId : userIds) {
@@ -15558,13 +15644,9 @@
Slog.d(TAG, "Updating package:" + ps.name + " install state for user:"
+ nextUserId);
}
- final int flags = StorageManager.FLAG_STORAGE_CE| StorageManager.FLAG_STORAGE_DE;
- try {
- mInstaller.destroyAppData(ps.volumeUuid, ps.name, nextUserId, flags);
- } catch (InstallerException e) {
- Slog.w(TAG, "Couldn't remove cache files for package " + ps.name, e);
- return false;
- }
+
+ destroyAppDataLIF(pkg, userId,
+ StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
removeKeystoreDataIfNeeded(nextUserId, ps.appId);
schedulePackageCleaning(ps.name, nextUserId, false);
synchronized (mPackages) {
@@ -15601,6 +15683,8 @@
}
private void clearExternalStorageDataSync(String packageName, int userId, boolean allData) {
+ if (DEFAULT_CONTAINER_PACKAGE.equals(packageName)) return;
+
final boolean mounted;
if (Environment.isExternalStorageEmulated()) {
mounted = true;
@@ -15660,10 +15744,16 @@
@Override
public void clearApplicationProfileData(String packageName) {
enforceSystemOrRoot("Only the system can clear all profile data");
- try {
- mInstaller.clearAppProfiles(packageName);
- } catch (InstallerException ex) {
- Log.e(TAG, "Could not clear profile data of package " + packageName);
+
+ final PackageParser.Package pkg;
+ synchronized (mPackages) {
+ pkg = mPackages.get(packageName);
+ }
+
+ try (PackageFreezer freezer = freezePackage(packageName, "clearApplicationProfileData")) {
+ synchronized (mInstallLock) {
+ clearAppProfilesLIF(pkg);
+ }
}
}
@@ -15686,10 +15776,13 @@
public void run() {
mHandler.removeCallbacks(this);
final boolean succeeded;
- synchronized (mInstallLock) {
- succeeded = clearApplicationUserDataLI(packageName, userId);
+ try (PackageFreezer freezer = freezePackage(packageName,
+ "clearApplicationUserData")) {
+ synchronized (mInstallLock) {
+ succeeded = clearApplicationUserDataLIF(packageName, userId);
+ }
+ clearExternalStorageDataSync(packageName, userId, true);
}
- clearExternalStorageDataSync(packageName, userId, true);
if (succeeded) {
// invoke DeviceStorageMonitor's update method to clear any notifications
DeviceStorageMonitorInternal dsm = LocalServices
@@ -15709,7 +15802,7 @@
});
}
- private boolean clearApplicationUserDataLI(String packageName, int userId) {
+ private boolean clearApplicationUserDataLIF(String packageName, int userId) {
if (packageName == null) {
Slog.w(TAG, "Attempt to delete null packageName.");
return false;
@@ -15735,35 +15828,22 @@
resetUserChangesToRuntimePermissionsAndFlagsLPw(ps, userId);
}
- // Always delete data directories for package, even if we found no other
- // record of app. This helps users recover from UID mismatches without
- // resorting to a full data wipe.
- // TODO: triage flags as part of 26466827
- final int flags = StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE;
- try {
- mInstaller.clearAppData(pkg.volumeUuid, packageName, userId, flags);
- } catch (InstallerException e) {
- Slog.w(TAG, "Couldn't remove cache files for package " + packageName, e);
- return false;
- }
+ clearAppDataLIF(pkg, userId,
+ StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);
removeKeystoreDataIfNeeded(userId, appId);
- // Create a native library symlink only if we have native libraries
- // and if the native libraries are 32 bit libraries. We do not provide
- // this symlink for 64 bit libraries.
- if (pkg.applicationInfo.primaryCpuAbi != null &&
- !VMRuntime.is64BitAbi(pkg.applicationInfo.primaryCpuAbi)) {
- final String nativeLibPath = pkg.applicationInfo.nativeLibraryDir;
- try {
- mInstaller.linkNativeLibraryDirectory(pkg.volumeUuid, pkg.packageName,
- nativeLibPath, userId);
- } catch (InstallerException e) {
- Slog.w(TAG, "Failed linking native library dir", e);
- return false;
- }
+ final UserManager um = mContext.getSystemService(UserManager.class);
+ final int flags;
+ if (um.isUserUnlocked(userId)) {
+ flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
+ } else if (um.isUserRunning(userId)) {
+ flags = StorageManager.FLAG_STORAGE_DE;
+ } else {
+ flags = 0;
}
+ prepareAppDataContentsLIF(pkg, userId, flags);
return true;
}
@@ -15933,56 +16013,35 @@
android.Manifest.permission.DELETE_CACHE_FILES, null);
// Queue up an async operation since the package deletion may take a little while.
final int userId = UserHandle.getCallingUserId();
+
+ final PackageParser.Package pkg;
+ synchronized (mPackages) {
+ pkg = mPackages.get(packageName);
+ }
+
mHandler.post(new Runnable() {
public void run() {
- mHandler.removeCallbacks(this);
- final boolean succeded;
- synchronized (mInstallLock) {
- succeded = deleteApplicationCacheFilesLI(packageName, userId);
+ try (PackageFreezer freezer = freezePackage(packageName,
+ "deleteApplicationCacheFiles")) {
+ synchronized (mInstallLock) {
+ final int flags = StorageManager.FLAG_STORAGE_DE
+ | StorageManager.FLAG_STORAGE_CE;
+ clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CACHE_ONLY);
+ clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ }
+ clearExternalStorageDataSync(packageName, userId, false);
}
- clearExternalStorageDataSync(packageName, userId, false);
if (observer != null) {
try {
- observer.onRemoveCompleted(packageName, succeded);
+ observer.onRemoveCompleted(packageName, true);
} catch (RemoteException e) {
Log.i(TAG, "Observer no longer exists.");
}
- } //end if observer
- } //end run
+ }
+ }
});
}
- private boolean deleteApplicationCacheFilesLI(String packageName, int userId) {
- if (packageName == null) {
- Slog.w(TAG, "Attempt to delete null packageName.");
- return false;
- }
- PackageParser.Package p;
- synchronized (mPackages) {
- p = mPackages.get(packageName);
- }
- if (p == null) {
- Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
- return false;
- }
- final ApplicationInfo applicationInfo = p.applicationInfo;
- if (applicationInfo == null) {
- Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
- return false;
- }
- // TODO: triage flags as part of 26466827
- final int flags = StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE;
- try {
- mInstaller.clearAppData(p.volumeUuid, packageName, userId,
- flags | Installer.FLAG_CLEAR_CACHE_ONLY);
- } catch (InstallerException e) {
- Slog.w(TAG, "Couldn't remove cache files for package "
- + packageName + " u" + userId, e);
- return false;
- }
- return true;
- }
-
@Override
public void getPackageSizeInfo(final String packageName, int userHandle,
final IPackageStatsObserver observer) {
@@ -16003,90 +16062,24 @@
mHandler.sendMessage(msg);
}
- private boolean getPackageSizeInfoLI(String packageName, int userHandle,
- PackageStats pStats) {
- if (packageName == null) {
- Slog.w(TAG, "Attempt to get size of null packageName.");
- return false;
- }
- PackageParser.Package p;
- boolean dataOnly = false;
- String libDirRoot = null;
- String asecPath = null;
- PackageSetting ps = null;
+ private boolean getPackageSizeInfoLI(String packageName, int userId, PackageStats stats) {
+ final PackageSetting ps;
synchronized (mPackages) {
- p = mPackages.get(packageName);
ps = mSettings.mPackages.get(packageName);
- if(p == null) {
- dataOnly = true;
- if((ps == null) || (ps.pkg == null)) {
- Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
- return false;
- }
- p = ps.pkg;
- }
- if (ps != null) {
- libDirRoot = ps.legacyNativeLibraryPathString;
- }
- if (p != null && (p.isForwardLocked() || p.applicationInfo.isExternalAsec())) {
- final long token = Binder.clearCallingIdentity();
- try {
- String secureContainerId = cidFromCodePath(p.applicationInfo.getBaseCodePath());
- if (secureContainerId != null) {
- asecPath = PackageHelper.getSdFilesystem(secureContainerId);
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- }
- String publicSrcDir = null;
- if(!dataOnly) {
- final ApplicationInfo applicationInfo = p.applicationInfo;
- if (applicationInfo == null) {
- Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
+ if (ps == null) {
+ Slog.w(TAG, "Failed to find settings for " + packageName);
return false;
}
- if (p.isForwardLocked()) {
- publicSrcDir = applicationInfo.getBaseResourcePath();
- }
}
- // TODO: extend to measure size of split APKs
- // TODO(multiArch): Extend getSizeInfo to look at the full subdirectory tree,
- // not just the first level.
- // TODO(multiArch): Extend getSizeInfo to look at *all* instruction sets, not
- // just the primary.
- String[] dexCodeInstructionSets = getDexCodeInstructionSets(getAppDexInstructionSets(ps));
-
- String apkPath;
- File packageDir = new File(p.codePath);
-
- if (packageDir.isDirectory() && p.canHaveOatDir()) {
- apkPath = packageDir.getAbsolutePath();
- // If libDirRoot is inside a package dir, set it to null to avoid it being counted twice
- if (libDirRoot != null && libDirRoot.startsWith(apkPath)) {
- libDirRoot = null;
- }
- } else {
- apkPath = p.baseCodePath;
- }
-
- // TODO: triage flags as part of 26466827
- final int flags = StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE;
try {
- mInstaller.getAppSize(p.volumeUuid, packageName, userHandle, flags, apkPath,
- libDirRoot, publicSrcDir, asecPath, dexCodeInstructionSets, pStats);
+ mInstaller.getAppSize(ps.volumeUuid, packageName, userId,
+ StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE,
+ ps.getCeDataInode(userId), ps.codePathString, stats);
+ return true;
} catch (InstallerException e) {
+ Slog.w(TAG, String.valueOf(e));
return false;
}
-
- // Fix-up for forward-locked applications in ASEC containers.
- if (!isExternal(p)) {
- pStats.codeSize += pStats.externalCodeSize;
- pStats.externalCodeSize = 0L;
- }
-
- return true;
}
private int getUidTargetSdkVersionLockedLPr(int uid) {
@@ -17401,6 +17394,7 @@
public static final int DUMP_INSTALLS = 1 << 16;
public static final int DUMP_INTENT_FILTER_VERIFIERS = 1 << 17;
public static final int DUMP_DOMAIN_PREFERRED = 1 << 18;
+ public static final int DUMP_FROZEN = 1 << 19;
public static final int OPTION_SHOW_FILTERS = 1 << 0;
@@ -17634,6 +17628,8 @@
dumpState.setDump(DumpState.DUMP_KEYSETS);
} else if ("installs".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_INSTALLS);
+ } else if ("frozen".equals(cmd)) {
+ dumpState.setDump(DumpState.DUMP_FROZEN);
} else if ("write".equals(cmd)) {
synchronized (mPackages) {
mSettings.writeLPr();
@@ -17972,6 +17968,25 @@
mInstallerService.dump(new IndentingPrintWriter(pw, " ", 120));
}
+ if (!checkin && dumpState.isDumping(DumpState.DUMP_FROZEN) && packageName == null) {
+ // XXX should handle packageName != null by dumping only install data that
+ // the given package is involved with.
+ if (dumpState.onTitlePrinted()) pw.println();
+
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
+ ipw.println();
+ ipw.println("Frozen packages:");
+ ipw.increaseIndent();
+ if (mFrozenPackages.size() == 0) {
+ ipw.println("(none)");
+ } else {
+ for (int i = 0; i < mFrozenPackages.size(); i++) {
+ ipw.println(mFrozenPackages.valueAt(i));
+ }
+ }
+ ipw.decreaseIndent();
+ }
+
if (!checkin && dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
if (dumpState.onTitlePrinted()) pw.println();
mSettings.dumpReadMessagesLPr(pw, dumpState);
@@ -18284,7 +18299,9 @@
synchronized (mInstallLock) {
PackageParser.Package pkg = null;
try {
- pkg = scanPackageTracedLI(new File(codePath), parseFlags, 0, 0, null);
+ // Sadly we don't know the package name yet to freeze it
+ pkg = scanPackageTracedLI(new File(codePath), parseFlags,
+ SCAN_IGNORE_FROZEN, 0, null);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to scan " + codePath + ": " + e.getMessage());
}
@@ -18383,8 +18400,13 @@
// Delete package internally
PackageRemovedInfo outInfo = new PackageRemovedInfo();
synchronized (mInstallLock) {
- boolean res = deletePackageLI(pkgName, null, false, null,
- PackageManager.DELETE_KEEP_DATA, outInfo, false, null);
+ final int deleteFlags = PackageManager.DELETE_KEEP_DATA;
+ final boolean res;
+ try (PackageFreezer freezer = freezePackageForDelete(pkgName, deleteFlags,
+ "unloadMediaPackages")) {
+ res = deletePackageLIF(pkgName, null, false, null, deleteFlags, outInfo, false,
+ null);
+ }
if (res) {
pkgList.add(pkgName);
} else {
@@ -18439,6 +18461,7 @@
return;
}
+ final ArrayList<PackageFreezer> freezers = new ArrayList<>();
final ArrayList<ApplicationInfo> loaded = new ArrayList<>();
final int parseFlags = mDefParseFlags | PackageParser.PARSE_EXTERNAL_STORAGE;
@@ -18449,9 +18472,8 @@
packages = mSettings.getVolumePackagesLPr(volumeUuid);
}
- // TODO: introduce a new concept similar to "frozen" to prevent these
- // apps from being launched until after data has been fully reconciled
for (PackageSetting ps : packages) {
+ freezers.add(freezePackage(ps.name, "loadPrivatePackagesInner"));
synchronized (mInstallLock) {
final PackageParser.Package pkg;
try {
@@ -18463,7 +18485,9 @@
}
if (!Build.FINGERPRINT.equals(ver.fingerprint)) {
- deleteCodeCacheDirsLI(ps.volumeUuid, ps.name);
+ clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
+ StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
+ | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
}
}
@@ -18482,7 +18506,9 @@
}
sm.prepareUserStorage(volumeUuid, user.id, user.serialNumber, flags);
- reconcileAppsData(volumeUuid, user.id, flags);
+ synchronized (mInstallLock) {
+ reconcileAppsDataLI(volumeUuid, user.id, flags);
+ }
}
synchronized (mPackages) {
@@ -18500,6 +18526,10 @@
mSettings.writeLPr();
}
+ for (PackageFreezer freezer : freezers) {
+ freezer.close();
+ }
+
if (DEBUG_INSTALL) Slog.d(TAG, "Loaded packages " + loaded);
sendResourcesChangedBroadcast(true, false, loaded, null);
}
@@ -18528,12 +18558,17 @@
if (ps.pkg == null) continue;
final ApplicationInfo info = ps.pkg.applicationInfo;
+ final int deleteFlags = PackageManager.DELETE_KEEP_DATA;
final PackageRemovedInfo outInfo = new PackageRemovedInfo();
- if (deletePackageLI(ps.name, null, false, null,
- PackageManager.DELETE_KEEP_DATA, outInfo, false, null)) {
- unloaded.add(info);
- } else {
- Slog.w(TAG, "Failed to unload " + ps.codePath);
+
+ try (PackageFreezer freezer = freezePackageForDelete(ps.name, deleteFlags,
+ "unloadPrivatePackagesInner")) {
+ if (deletePackageLIF(ps.name, null, false, null, deleteFlags, outInfo,
+ false, null)) {
+ unloaded.add(info);
+ } else {
+ Slog.w(TAG, "Failed to unload " + ps.codePath);
+ }
}
}
@@ -18665,7 +18700,9 @@
final StorageManager storage = mContext.getSystemService(StorageManager.class);
for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
final String volumeUuid = vol.getFsUuid();
- reconcileAppsData(volumeUuid, userId, flags);
+ synchronized (mInstallLock) {
+ reconcileAppsDataLI(volumeUuid, userId, flags);
+ }
}
}
@@ -18678,7 +18715,7 @@
* Verifies that directories exist and that ownership and labeling is
* correct for all installed apps.
*/
- private void reconcileAppsData(String volumeUuid, int userId, int flags) {
+ private void reconcileAppsDataLI(String volumeUuid, int userId, int flags) {
Slog.v(TAG, "reconcileAppsData for " + volumeUuid + " u" + userId + " 0x"
+ Integer.toHexString(flags));
@@ -18705,9 +18742,11 @@
assertPackageKnownAndInstalled(volumeUuid, packageName, userId);
} catch (PackageManagerException e) {
logCriticalInfo(Log.WARN, "Destroying " + file + " due to: " + e);
- synchronized (mInstallLock) {
- destroyAppDataLI(volumeUuid, packageName, userId,
- StorageManager.FLAG_STORAGE_CE);
+ try {
+ mInstaller.destroyAppData(volumeUuid, packageName, userId,
+ StorageManager.FLAG_STORAGE_CE, 0);
+ } catch (InstallerException e2) {
+ logCriticalInfo(Log.WARN, "Failed to destroy: " + e2);
}
}
}
@@ -18722,9 +18761,11 @@
assertPackageKnownAndInstalled(volumeUuid, packageName, userId);
} catch (PackageManagerException e) {
logCriticalInfo(Log.WARN, "Destroying " + file + " due to: " + e);
- synchronized (mInstallLock) {
- destroyAppDataLI(volumeUuid, packageName, userId,
- StorageManager.FLAG_STORAGE_DE);
+ try {
+ mInstaller.destroyAppData(volumeUuid, packageName, userId,
+ StorageManager.FLAG_STORAGE_DE, 0);
+ } catch (InstallerException e2) {
+ logCriticalInfo(Log.WARN, "Failed to destroy: " + e2);
}
}
}
@@ -18747,12 +18788,12 @@
}
if (ps.getInstalled(userId)) {
- prepareAppData(volumeUuid, userId, flags, ps.pkg, restoreconNeeded);
+ prepareAppDataLIF(ps.pkg, userId, flags, restoreconNeeded);
- if (maybeMigrateAppData(volumeUuid, userId, ps.pkg)) {
+ if (maybeMigrateAppDataLIF(ps.pkg, userId)) {
// We may have just shuffled around app data directories, so
// prepare them one more time
- prepareAppData(volumeUuid, userId, flags, ps.pkg, restoreconNeeded);
+ prepareAppDataLIF(ps.pkg, userId, flags, restoreconNeeded);
}
preparedCount++;
@@ -18784,16 +18825,7 @@
* <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);
- final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
- for (int i = 0; i < childCount; i++) {
- PackageParser.Package childPackage = pkg.childPackages.get(i);
- prepareAppDataAfterInstallInternal(childPackage);
- }
- }
-
- private void prepareAppDataAfterInstallInternal(PackageParser.Package pkg) {
+ private void prepareAppDataAfterInstallLIF(PackageParser.Package pkg) {
final PackageSetting ps;
synchronized (mPackages) {
ps = mSettings.mPackages.get(pkg.packageName);
@@ -18814,7 +18846,7 @@
if (ps.getInstalled(user.id)) {
// Whenever an app changes, force a restorecon of its data
// TODO: when user data is locked, mark that we're still dirty
- prepareAppData(pkg.volumeUuid, user.id, flags, pkg, true);
+ prepareAppDataLIF(pkg, user.id, flags, true);
}
}
}
@@ -18827,57 +18859,112 @@
* will try recovering system apps by wiping data; third-party app data is
* left intact.
*/
- private void prepareAppData(String volumeUuid, int userId, int flags,
- PackageParser.Package pkg, boolean restoreconNeeded) {
+ private void prepareAppDataLIF(PackageParser.Package pkg, int userId, int flags,
+ boolean restoreconNeeded) {
+ if (pkg == null) {
+ Slog.wtf(TAG, "Package was null!", new Throwable());
+ return;
+ }
+ prepareAppDataLeafLIF(pkg, userId, flags, restoreconNeeded);
+ final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+ for (int i = 0; i < childCount; i++) {
+ prepareAppDataLeafLIF(pkg.childPackages.get(i), userId, flags, restoreconNeeded);
+ }
+ }
+
+ private void prepareAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags,
+ boolean restoreconNeeded) {
if (DEBUG_APP_DATA) {
Slog.v(TAG, "prepareAppData for " + pkg.packageName + " u" + userId + " 0x"
+ Integer.toHexString(flags) + (restoreconNeeded ? " restoreconNeeded" : ""));
}
+ final String volumeUuid = pkg.volumeUuid;
final String packageName = pkg.packageName;
final ApplicationInfo app = pkg.applicationInfo;
final int appId = UserHandle.getAppId(app.uid);
Preconditions.checkNotNull(app.seinfo);
- synchronized (mInstallLock) {
- try {
- mInstaller.createAppData(volumeUuid, packageName, userId, flags,
- appId, app.seinfo, app.targetSdkVersion);
- } catch (InstallerException e) {
- if (app.isSystemApp()) {
- logCriticalInfo(Log.ERROR, "Failed to create app data for " + packageName
- + ", but trying to recover: " + e);
- destroyAppDataLI(volumeUuid, packageName, userId, flags);
- try {
- mInstaller.createAppData(volumeUuid, packageName, userId, flags,
- appId, app.seinfo, app.targetSdkVersion);
- logCriticalInfo(Log.DEBUG, "Recovery succeeded!");
- } catch (InstallerException e2) {
- logCriticalInfo(Log.DEBUG, "Recovery failed!");
- }
- } else {
- Slog.e(TAG, "Failed to create app data for " + packageName + ": " + e);
+ try {
+ mInstaller.createAppData(volumeUuid, packageName, userId, flags,
+ appId, app.seinfo, app.targetSdkVersion);
+ } catch (InstallerException e) {
+ if (app.isSystemApp()) {
+ logCriticalInfo(Log.ERROR, "Failed to create app data for " + packageName
+ + ", but trying to recover: " + e);
+ destroyAppDataLeafLIF(pkg, userId, flags);
+ try {
+ mInstaller.createAppData(volumeUuid, packageName, userId, flags,
+ appId, app.seinfo, app.targetSdkVersion);
+ logCriticalInfo(Log.DEBUG, "Recovery succeeded!");
+ } catch (InstallerException e2) {
+ logCriticalInfo(Log.DEBUG, "Recovery failed!");
}
+ } else {
+ Slog.e(TAG, "Failed to create app data for " + packageName + ": " + e);
}
+ }
- if (restoreconNeeded) {
- restoreconAppDataLI(volumeUuid, packageName, userId, flags, appId, app.seinfo);
+ if (restoreconNeeded) {
+ try {
+ mInstaller.restoreconAppData(volumeUuid, packageName, userId, flags, appId,
+ app.seinfo);
+ } catch (InstallerException e) {
+ Slog.e(TAG, "Failed to restorecon for " + packageName + ": " + e);
}
+ }
- if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) {
- // Create a native library symlink only if we have native libraries
- // and if the native libraries are 32 bit libraries. We do not provide
- // this symlink for 64 bit libraries.
- if (app.primaryCpuAbi != null && !VMRuntime.is64BitAbi(app.primaryCpuAbi)) {
- final String nativeLibPath = app.nativeLibraryDir;
- try {
- mInstaller.linkNativeLibraryDirectory(volumeUuid, packageName,
- nativeLibPath, userId);
- } catch (InstallerException e) {
- Slog.e(TAG, "Failed to link native for " + packageName + ": " + e);
+ if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) {
+ try {
+ // CE storage is unlocked right now, so read out the inode and
+ // remember for use later when it's locked
+ // TODO: mark this structure as dirty so we persist it!
+ final long ceDataInode = mInstaller.getAppDataInode(volumeUuid, packageName, userId,
+ StorageManager.FLAG_STORAGE_CE);
+ synchronized (mPackages) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (ps != null) {
+ ps.setCeDataInode(ceDataInode, userId);
}
}
+ } catch (InstallerException e) {
+ Slog.e(TAG, "Failed to find inode for " + packageName + ": " + e);
+ }
+ }
+
+ prepareAppDataContentsLeafLIF(pkg, userId, flags);
+ }
+
+ private void prepareAppDataContentsLIF(PackageParser.Package pkg, int userId, int flags) {
+ if (pkg == null) {
+ Slog.wtf(TAG, "Package was null!", new Throwable());
+ return;
+ }
+ prepareAppDataContentsLeafLIF(pkg, userId, flags);
+ final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+ for (int i = 0; i < childCount; i++) {
+ prepareAppDataContentsLeafLIF(pkg.childPackages.get(i), userId, flags);
+ }
+ }
+
+ private void prepareAppDataContentsLeafLIF(PackageParser.Package pkg, int userId, int flags) {
+ final String volumeUuid = pkg.volumeUuid;
+ final String packageName = pkg.packageName;
+ final ApplicationInfo app = pkg.applicationInfo;
+
+ if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) {
+ // Create a native library symlink only if we have native libraries
+ // and if the native libraries are 32 bit libraries. We do not provide
+ // this symlink for 64 bit libraries.
+ if (app.primaryCpuAbi != null && !VMRuntime.is64BitAbi(app.primaryCpuAbi)) {
+ final String nativeLibPath = app.nativeLibraryDir;
+ try {
+ mInstaller.linkNativeLibraryDirectory(volumeUuid, packageName,
+ nativeLibPath, userId);
+ } catch (InstallerException e) {
+ Slog.e(TAG, "Failed to link native for " + packageName + ": " + e);
+ }
}
}
}
@@ -18887,18 +18974,17 @@
* CE/DE data to match the {@code defaultToDeviceProtectedStorage} flag
* requested by the app.
*/
- private boolean maybeMigrateAppData(String volumeUuid, int userId, PackageParser.Package pkg) {
+ private boolean maybeMigrateAppDataLIF(PackageParser.Package pkg, int userId) {
if (pkg.isSystemApp() && !StorageManager.isFileEncryptedNativeOrEmulated()
&& PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
final int storageTarget = pkg.applicationInfo.isDefaultToDeviceProtectedStorage()
? 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());
- }
+ try {
+ mInstaller.migrateAppData(pkg.volumeUuid, pkg.packageName, userId,
+ storageTarget);
+ } catch (InstallerException e) {
+ logCriticalInfo(Log.WARN,
+ "Failed to migrate " + pkg.packageName + ": " + e.getMessage());
}
return true;
} else {
@@ -18906,11 +18992,116 @@
}
}
- private void unfreezePackage(String packageName) {
+ public PackageFreezer freezePackage(String packageName, String killReason) {
+ return new PackageFreezer(packageName, killReason);
+ }
+
+ public PackageFreezer freezePackageForInstall(String packageName, int installFlags,
+ String killReason) {
+ if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
+ return new PackageFreezer();
+ } else {
+ return freezePackage(packageName, killReason);
+ }
+ }
+
+ public PackageFreezer freezePackageForDelete(String packageName, int deleteFlags,
+ String killReason) {
+ if ((deleteFlags & PackageManager.DELETE_DONT_KILL_APP) != 0) {
+ return new PackageFreezer();
+ } else {
+ return freezePackage(packageName, killReason);
+ }
+ }
+
+ /**
+ * Class that freezes and kills the given package upon creation, and
+ * unfreezes it upon closing. This is typically used when doing surgery on
+ * app code/data to prevent the app from running while you're working.
+ */
+ private class PackageFreezer implements AutoCloseable {
+ private final String mPackageName;
+ private final PackageFreezer[] mChildren;
+
+ private final boolean mWeFroze;
+
+ private final AtomicBoolean mClosed = new AtomicBoolean();
+ private final CloseGuard mCloseGuard = CloseGuard.get();
+
+ /**
+ * Create and return a stub freezer that doesn't actually do anything,
+ * typically used when someone requested
+ * {@link PackageManager#INSTALL_DONT_KILL_APP} or
+ * {@link PackageManager#DELETE_DONT_KILL_APP}.
+ */
+ public PackageFreezer() {
+ mPackageName = null;
+ mChildren = null;
+ mWeFroze = false;
+ mCloseGuard.open("close");
+ }
+
+ public PackageFreezer(String packageName, String killReason) {
+ synchronized (mPackages) {
+ mPackageName = packageName;
+ mWeFroze = mFrozenPackages.add(mPackageName);
+
+ final PackageSetting ps = mSettings.mPackages.get(mPackageName);
+ if (ps != null) {
+ killApplication(ps.name, ps.appId, killReason);
+ }
+
+ final PackageParser.Package p = mPackages.get(packageName);
+ if (p != null && p.childPackages != null) {
+ final int N = p.childPackages.size();
+ mChildren = new PackageFreezer[N];
+ for (int i = 0; i < N; i++) {
+ mChildren[i] = new PackageFreezer(p.childPackages.get(i).packageName,
+ killReason);
+ }
+ } else {
+ mChildren = null;
+ }
+ }
+ mCloseGuard.open("close");
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ mCloseGuard.warnIfOpen();
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ @Override
+ public void close() {
+ mCloseGuard.close();
+ if (mClosed.compareAndSet(false, true)) {
+ synchronized (mPackages) {
+ if (mWeFroze) {
+ mFrozenPackages.remove(mPackageName);
+ }
+
+ if (mChildren != null) {
+ for (PackageFreezer freezer : mChildren) {
+ freezer.close();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Verify that given package is currently frozen.
+ */
+ private void checkPackageFrozen(String packageName) {
synchronized (mPackages) {
- final PackageSetting ps = mSettings.mPackages.get(packageName);
- if (ps != null) {
- ps.frozen = false;
+ if (!mFrozenPackages.contains(packageName)) {
+ Slog.wtf(TAG, "Expected " + packageName + " to be frozen!", new Throwable());
}
}
}
@@ -18950,6 +19141,7 @@
final String seinfo;
final String label;
final int targetSdkVersion;
+ final PackageFreezer freezer;
// reader
synchronized (mPackages) {
@@ -18991,11 +19183,10 @@
"Device admin cannot be moved");
}
- if (ps.frozen) {
+ if (mFrozenPackages.contains(packageName)) {
throw new PackageManagerException(MOVE_FAILED_OPERATION_PENDING,
"Failed to move already frozen package");
}
- ps.frozen = true;
codeFile = new File(pkg.codePath);
installerPackageName = ps.installerPackageName;
@@ -19004,14 +19195,7 @@
seinfo = pkg.applicationInfo.seinfo;
label = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo));
targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
- }
-
- // Now that we're guarded by frozen state, kill app during move
- final long token = Binder.clearCallingIdentity();
- try {
- killApplication(packageName, appId, "move pkg");
- } finally {
- Binder.restoreCallingIdentity(token);
+ freezer = new PackageFreezer(packageName, "movePackageInternal");
}
final Bundle extras = new Bundle();
@@ -19035,7 +19219,7 @@
final VolumeInfo volume = storage.findVolumeByUuid(volumeUuid);
if (volume == null || volume.getType() != VolumeInfo.TYPE_PRIVATE
|| !volume.isMountedWritable()) {
- unfreezePackage(packageName);
+ freezer.close();
throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR,
"Move location not mounted private volume");
}
@@ -19050,7 +19234,7 @@
final PackageStats stats = new PackageStats(null, -1);
synchronized (mInstaller) {
if (!getPackageSizeInfoLI(packageName, -1, stats)) {
- unfreezePackage(packageName);
+ freezer.close();
throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR,
"Failed to measure package size");
}
@@ -19068,7 +19252,7 @@
}
if (sizeBytes > storage.getStorageBytesUntilLow(measurePath)) {
- unfreezePackage(packageName);
+ freezer.close();
throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR,
"Not enough free space to move");
}
@@ -19089,10 +19273,7 @@
+ PackageManager.installStatusToString(returnCode, msg));
installedLatch.countDown();
-
- // Regardless of success or failure of the move operation,
- // always unfreeze the package
- unfreezePackage(packageName);
+ freezer.close();
final int status = PackageManager.installStatusToPublicStatus(returnCode);
switch (status) {
@@ -19147,7 +19328,7 @@
final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
final InstallParams params = new InstallParams(origin, move, installObserver, installFlags,
installerPackageName, volumeUuid, null /*verificationInfo*/, user,
- packageAbiOverride, null);
+ packageAbiOverride, null /*grantedPermissions*/, null /*certificates*/);
params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 1434718..9d04472 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -114,12 +114,6 @@
int installStatus = PKG_INSTALL_COMPLETE;
/**
- * Non-persisted value indicating this package has been temporarily frozen,
- * usually during a critical section of the package update pipeline. The
- * 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
@@ -329,6 +323,14 @@
return res;
}
+ long getCeDataInode(int userId) {
+ return readUserState(userId).ceDataInode;
+ }
+
+ void setCeDataInode(long ceDataInode, int userId) {
+ modifyUserState(userId).ceDataInode = ceDataInode;
+ }
+
boolean getStopped(int userId) {
return readUserState(userId).stopped;
}
@@ -369,12 +371,13 @@
modifyUserState(userId).blockUninstall = blockUninstall;
}
- void setUserState(int userId, int enabled, boolean installed, boolean stopped,
+ void setUserState(int userId, long ceDataInode, int enabled, boolean installed, boolean stopped,
boolean notLaunched, boolean hidden, boolean suspended,
String lastDisableAppCaller, ArraySet<String> enabledComponents,
ArraySet<String> disabledComponents, boolean blockUninstall, int domainVerifState,
int linkGeneration) {
PackageUserState state = modifyUserState(userId);
+ state.ceDataInode = ceDataInode;
state.enabled = enabled;
state.installed = installed;
state.stopped = stopped;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 3c3c576..847f993 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -195,23 +195,26 @@
private static final String ATTR_NAME = "name";
private static final String ATTR_USER = "user";
private static final String ATTR_CODE = "code";
- private static final String ATTR_NOT_LAUNCHED = "nl";
- private static final String ATTR_ENABLED = "enabled";
private static final String ATTR_GRANTED = "granted";
private static final String ATTR_FLAGS = "flags";
- private static final String ATTR_ENABLED_CALLER = "enabledCaller";
+
+ private static final String ATTR_CE_DATA_INODE = "ceDataInode";
+ private static final String ATTR_INSTALLED = "inst";
private static final String ATTR_STOPPED = "stopped";
+ private static final String ATTR_NOT_LAUNCHED = "nl";
// Legacy, here for reading older versions of the package-restrictions.
private static final String ATTR_BLOCKED = "blocked";
// New name for the above attribute.
private static final String ATTR_HIDDEN = "hidden";
private static final String ATTR_SUSPENDED = "suspended";
- private static final String ATTR_INSTALLED = "inst";
private static final String ATTR_BLOCK_UNINSTALL = "blockUninstall";
+ private static final String ATTR_ENABLED = "enabled";
+ private static final String ATTR_ENABLED_CALLER = "enabledCaller";
private static final String ATTR_DOMAIN_VERIFICATON_STATE = "domainVerificationStatus";
+ private static final String ATTR_APP_LINK_GENERATION = "app-link-generation";
+
private static final String ATTR_PACKAGE_NAME = "packageName";
private static final String ATTR_FINGERPRINT = "fingerprint";
- private static final String ATTR_APP_LINK_GENERATION = "app-link-generation";
private static final String ATTR_VOLUME_UUID = "volumeUuid";
private static final String ATTR_SDK_VERSION = "sdkVersion";
private static final String ATTR_DATABASE_VERSION = "databaseVersion";
@@ -247,6 +250,9 @@
/** Map from package name to settings */
final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<>();
+ /** List of packages that installed other packages */
+ final ArraySet<String> mInstallerPackages = new ArraySet<>();
+
/** Map from package name to appId */
private final ArrayMap<String, Integer> mKernelMapping = new ArrayMap<>();
@@ -360,7 +366,7 @@
// Packages that have been uninstalled and still need their external
// storage data deleted.
final ArrayList<PackageCleanItem> mPackagesToBeCleaned = new ArrayList<PackageCleanItem>();
-
+
// Packages that have been renamed since they were first installed.
// Keys are the new names of the packages, values are the original
// names. The packages appear everwhere else under their original
@@ -506,6 +512,9 @@
PackageSetting p = mPackages.get(pkgName);
if (p != null) {
p.setInstallerPackageName(installerPkgName);
+ if (installerPkgName != null) {
+ mInstallerPackages.add(installerPkgName);
+ }
}
}
@@ -572,7 +581,7 @@
}
PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath,
p.legacyNativeLibraryPathString, p.primaryCpuAbiString,
- p.secondaryCpuAbiString, p.secondaryCpuAbiString,
+ p.secondaryCpuAbiString, p.cpuAbiOverrideString,
p.appId, p.versionCode, p.pkgFlags, p.pkgPrivateFlags,
p.parentPackageName, p.childPackageNames);
mDisabledSysPackages.remove(name);
@@ -784,7 +793,7 @@
|| (installUserId == UserHandle.USER_ALL
&& !isAdbInstallDisallowed(userManager, user.id))
|| installUserId == user.id;
- p.setUserState(user.id, COMPONENT_ENABLED_STATE_DEFAULT,
+ p.setUserState(user.id, 0, COMPONENT_ENABLED_STATE_DEFAULT,
installed,
true, // stopped,
true, // notLaunched
@@ -1062,6 +1071,7 @@
final PackageSetting p = mPackages.get(name);
if (p != null) {
mPackages.remove(name);
+ removeInstallerPackageStatus(name);
if (p.sharedUser != null) {
p.sharedUser.removePackage(p);
if (p.sharedUser.packages.size() == 0) {
@@ -1077,6 +1087,26 @@
return -1;
}
+ /**
+ * Checks if {@param packageName} is an installer package and if so, clear the installer
+ * package name of the packages that are installed by this.
+ */
+ private void removeInstallerPackageStatus(String packageName) {
+ // Check if the package to be removed is an installer package.
+ if (!mInstallerPackages.contains(packageName)) {
+ return;
+ }
+ for (int i = 0; i < mPackages.size(); i++) {
+ final PackageSetting ps = mPackages.valueAt(i);
+ final String installerPackageName = ps.getInstallerPackageName();
+ if (installerPackageName != null
+ && installerPackageName.equals(packageName)) {
+ ps.setInstallerPackageName(null);
+ }
+ }
+ mInstallerPackages.remove(packageName);
+ }
+
private void replacePackageLPw(String name, PackageSetting newp) {
final PackageSetting p = mPackages.get(name);
if (p != null) {
@@ -1547,7 +1577,7 @@
// in the stopped state, but not at first boot. Also
// consider all applications to be installed.
for (PackageSetting pkg : mPackages.values()) {
- pkg.setUserState(userId, COMPONENT_ENABLED_STATE_DEFAULT,
+ pkg.setUserState(userId, 0, COMPONENT_ENABLED_STATE_DEFAULT,
true, // installed
false, // stopped
false, // notLaunched
@@ -1599,17 +1629,16 @@
XmlUtils.skipCurrentTag(parser);
continue;
}
- final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
- final int enabled = enabledStr == null
- ? COMPONENT_ENABLED_STATE_DEFAULT : Integer.parseInt(enabledStr);
- final String enabledCaller = parser.getAttributeValue(null,
- ATTR_ENABLED_CALLER);
- final String installedStr = parser.getAttributeValue(null, ATTR_INSTALLED);
- final boolean installed = installedStr == null
- ? true : Boolean.parseBoolean(installedStr);
- final String stoppedStr = parser.getAttributeValue(null, ATTR_STOPPED);
- final boolean stopped = stoppedStr == null
- ? false : Boolean.parseBoolean(stoppedStr);
+
+ final long ceDataInode = XmlUtils.readLongAttribute(parser, ATTR_CE_DATA_INODE,
+ 0);
+ final boolean installed = XmlUtils.readBooleanAttribute(parser, ATTR_INSTALLED,
+ true);
+ final boolean stopped = XmlUtils.readBooleanAttribute(parser, ATTR_STOPPED,
+ false);
+ final boolean notLaunched = XmlUtils.readBooleanAttribute(parser,
+ ATTR_NOT_LAUNCHED, false);
+
// For backwards compatibility with the previous name of "blocked", which
// now means hidden, read the old attribute as well.
final String blockedStr = parser.getAttributeValue(null, ATTR_BLOCKED);
@@ -1618,25 +1647,21 @@
final String hiddenStr = parser.getAttributeValue(null, ATTR_HIDDEN);
hidden = hiddenStr == null
? hidden : Boolean.parseBoolean(hiddenStr);
- final String suspendedStr = parser.getAttributeValue(null, ATTR_SUSPENDED);
- final boolean suspended = suspendedStr == null
- ? false : Boolean.parseBoolean(suspendedStr);
- final String notLaunchedStr = parser.getAttributeValue(null, ATTR_NOT_LAUNCHED);
- final boolean notLaunched = stoppedStr == null
- ? false : Boolean.parseBoolean(notLaunchedStr);
- final String blockUninstallStr = parser.getAttributeValue(null,
- ATTR_BLOCK_UNINSTALL);
- final boolean blockUninstall = blockUninstallStr == null
- ? false : Boolean.parseBoolean(blockUninstallStr);
- final String verifStateStr =
- parser.getAttributeValue(null, ATTR_DOMAIN_VERIFICATON_STATE);
- final int verifState = (verifStateStr == null) ?
- PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED :
- Integer.parseInt(verifStateStr);
+ final boolean suspended = XmlUtils.readBooleanAttribute(parser, ATTR_SUSPENDED,
+ false);
+ final boolean blockUninstall = XmlUtils.readBooleanAttribute(parser,
+ ATTR_BLOCK_UNINSTALL, false);
+ final int enabled = XmlUtils.readIntAttribute(parser, ATTR_ENABLED,
+ COMPONENT_ENABLED_STATE_DEFAULT);
+ final String enabledCaller = parser.getAttributeValue(null,
+ ATTR_ENABLED_CALLER);
- final String linkGenStr = parser.getAttributeValue(null, ATTR_APP_LINK_GENERATION);
- final int linkGeneration = linkGenStr == null ? 0 : Integer.parseInt(linkGenStr);
+ final int verifState = XmlUtils.readIntAttribute(parser,
+ ATTR_DOMAIN_VERIFICATON_STATE,
+ PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED);
+ final int linkGeneration = XmlUtils.readIntAttribute(parser,
+ ATTR_APP_LINK_GENERATION, 0);
if (linkGeneration > maxAppLinkGeneration) {
maxAppLinkGeneration = linkGeneration;
}
@@ -1660,8 +1685,8 @@
}
}
- ps.setUserState(userId, enabled, installed, stopped, notLaunched, hidden,
- suspended, enabledCaller, enabledComponents, disabledComponents,
+ ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched,
+ hidden, suspended, enabledCaller, enabledComponents, disabledComponents,
blockUninstall, verifState, linkGeneration);
} else if (tagName.equals("preferred-activities")) {
readPreferredActivitiesLPw(parser, userId);
@@ -1900,80 +1925,69 @@
serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
for (final PackageSetting pkg : mPackages.values()) {
- PackageUserState ustate = pkg.readUserState(userId);
- if (ustate.stopped || ustate.notLaunched || !ustate.installed
- || ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT
- || ustate.hidden
- || ustate.suspended
- || (ustate.enabledComponents != null
- && ustate.enabledComponents.size() > 0)
- || (ustate.disabledComponents != null
- && ustate.disabledComponents.size() > 0)
- || ustate.blockUninstall
- || (ustate.domainVerificationStatus !=
- PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED)) {
- serializer.startTag(null, TAG_PACKAGE);
- serializer.attribute(null, ATTR_NAME, pkg.name);
- if (DEBUG_MU) Log.i(TAG, " pkg=" + pkg.name + ", state=" + ustate.enabled);
+ final PackageUserState ustate = pkg.readUserState(userId);
+ if (DEBUG_MU) Log.i(TAG, " pkg=" + pkg.name + ", state=" + ustate.enabled);
- if (!ustate.installed) {
- serializer.attribute(null, ATTR_INSTALLED, "false");
- }
- if (ustate.stopped) {
- serializer.attribute(null, ATTR_STOPPED, "true");
- }
- if (ustate.notLaunched) {
- serializer.attribute(null, ATTR_NOT_LAUNCHED, "true");
- }
- if (ustate.hidden) {
- serializer.attribute(null, ATTR_HIDDEN, "true");
- }
- if (ustate.suspended) {
- serializer.attribute(null, ATTR_SUSPENDED, "true");
- }
- if (ustate.blockUninstall) {
- serializer.attribute(null, ATTR_BLOCK_UNINSTALL, "true");
- }
- if (ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
- serializer.attribute(null, ATTR_ENABLED,
- Integer.toString(ustate.enabled));
- if (ustate.lastDisableAppCaller != null) {
- serializer.attribute(null, ATTR_ENABLED_CALLER,
- ustate.lastDisableAppCaller);
- }
- }
- if (ustate.domainVerificationStatus !=
- PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) {
- serializer.attribute(null, ATTR_DOMAIN_VERIFICATON_STATE,
- Integer.toString(ustate.domainVerificationStatus));
- }
- if (ustate.appLinkGeneration != 0) {
- serializer.attribute(null, ATTR_APP_LINK_GENERATION,
- Integer.toString(ustate.appLinkGeneration));
- }
- if (ustate.enabledComponents != null
- && ustate.enabledComponents.size() > 0) {
- serializer.startTag(null, TAG_ENABLED_COMPONENTS);
- for (final String name : ustate.enabledComponents) {
- serializer.startTag(null, TAG_ITEM);
- serializer.attribute(null, ATTR_NAME, name);
- serializer.endTag(null, TAG_ITEM);
- }
- serializer.endTag(null, TAG_ENABLED_COMPONENTS);
- }
- if (ustate.disabledComponents != null
- && ustate.disabledComponents.size() > 0) {
- serializer.startTag(null, TAG_DISABLED_COMPONENTS);
- for (final String name : ustate.disabledComponents) {
- serializer.startTag(null, TAG_ITEM);
- serializer.attribute(null, ATTR_NAME, name);
- serializer.endTag(null, TAG_ITEM);
- }
- serializer.endTag(null, TAG_DISABLED_COMPONENTS);
- }
-
- serializer.endTag(null, TAG_PACKAGE);
+ serializer.startTag(null, TAG_PACKAGE);
+ serializer.attribute(null, ATTR_NAME, pkg.name);
+ if (ustate.ceDataInode != 0) {
+ XmlUtils.writeLongAttribute(serializer, ATTR_CE_DATA_INODE, ustate.ceDataInode);
}
+ if (!ustate.installed) {
+ serializer.attribute(null, ATTR_INSTALLED, "false");
+ }
+ if (ustate.stopped) {
+ serializer.attribute(null, ATTR_STOPPED, "true");
+ }
+ if (ustate.notLaunched) {
+ serializer.attribute(null, ATTR_NOT_LAUNCHED, "true");
+ }
+ if (ustate.hidden) {
+ serializer.attribute(null, ATTR_HIDDEN, "true");
+ }
+ if (ustate.suspended) {
+ serializer.attribute(null, ATTR_SUSPENDED, "true");
+ }
+ if (ustate.blockUninstall) {
+ serializer.attribute(null, ATTR_BLOCK_UNINSTALL, "true");
+ }
+ if (ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
+ serializer.attribute(null, ATTR_ENABLED,
+ Integer.toString(ustate.enabled));
+ if (ustate.lastDisableAppCaller != null) {
+ serializer.attribute(null, ATTR_ENABLED_CALLER,
+ ustate.lastDisableAppCaller);
+ }
+ }
+ if (ustate.domainVerificationStatus !=
+ PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) {
+ XmlUtils.writeIntAttribute(serializer, ATTR_DOMAIN_VERIFICATON_STATE,
+ ustate.domainVerificationStatus);
+ }
+ if (ustate.appLinkGeneration != 0) {
+ XmlUtils.writeIntAttribute(serializer, ATTR_APP_LINK_GENERATION,
+ ustate.appLinkGeneration);
+ }
+ if (!ArrayUtils.isEmpty(ustate.enabledComponents)) {
+ serializer.startTag(null, TAG_ENABLED_COMPONENTS);
+ for (final String name : ustate.enabledComponents) {
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, name);
+ serializer.endTag(null, TAG_ITEM);
+ }
+ serializer.endTag(null, TAG_ENABLED_COMPONENTS);
+ }
+ if (!ArrayUtils.isEmpty(ustate.disabledComponents)) {
+ serializer.startTag(null, TAG_DISABLED_COMPONENTS);
+ for (final String name : ustate.disabledComponents) {
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, name);
+ serializer.endTag(null, TAG_ITEM);
+ }
+ serializer.endTag(null, TAG_DISABLED_COMPONENTS);
+ }
+
+ serializer.endTag(null, TAG_PACKAGE);
}
writePreferredActivitiesLPr(serializer, userId, true);
@@ -2742,6 +2756,7 @@
mPendingPackages.clear();
mPastSignatures.clear();
mKeySetRefs.clear();
+ mInstallerPackages.clear();
try {
if (str == null) {
@@ -3706,6 +3721,10 @@
packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0, null);
}
+ if (installerPackageName != null) {
+ mInstallerPackages.add(installerPackageName);
+ }
+
final String installStatusStr = parser.getAttributeValue(null, "installStatus");
if (installStatusStr != null) {
if (installStatusStr.equalsIgnoreCase("false")) {
@@ -3724,7 +3743,7 @@
}
String tagName = parser.getName();
- // Legacy
+ // Legacy
if (tagName.equals(TAG_DISABLED_COMPONENTS)) {
readDisabledComponentsLPw(packageSetting, parser, 0);
} else if (tagName.equals(TAG_ENABLED_COMPONENTS)) {
@@ -4293,10 +4312,6 @@
pw.print(Integer.toHexString(System.identityHashCode(ps)));
pw.println("):");
- if (ps.frozen) {
- pw.print(prefix); pw.println(" FROZEN!");
- }
-
if (ps.realName != null) {
pw.print(prefix); pw.print(" compat name=");
pw.println(ps.name);
@@ -4504,6 +4519,8 @@
for (UserInfo user : users) {
pw.print(prefix); pw.print(" User "); pw.print(user.id); pw.print(": ");
+ pw.print("ceDataInode=");
+ pw.print(ps.getCeDataInode(user.id));
pw.print(" installed=");
pw.print(ps.getInstalled(user.id));
pw.print(" hidden=");
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 1076a7a..58559a5 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -17,6 +17,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
@@ -522,7 +523,7 @@
ret.getPackageInfo().loadFromXml(parser, fromBackup);
continue;
case TAG_SHORTCUT:
- final ShortcutInfo si = parseShortcut(parser, packageName);
+ final ShortcutInfo si = parseShortcut(parser, packageName, ownerUserId);
// Don't use addShortcut(), we don't need to save the icon.
ret.mShortcuts.put(si.getId(), si);
@@ -534,8 +535,8 @@
return ret;
}
- private static ShortcutInfo parseShortcut(XmlPullParser parser, String packageName)
- throws IOException, XmlPullParserException {
+ private static ShortcutInfo parseShortcut(XmlPullParser parser, String packageName,
+ @UserIdInt int userId) throws IOException, XmlPullParserException {
String id;
ComponentName activityComponent;
// Icon icon;
@@ -586,7 +587,7 @@
throw ShortcutService.throwForInvalidTag(depth, tag);
}
return new ShortcutInfo(
- id, packageName, activityComponent, /* icon =*/ null, title, text, intent,
+ userId, id, packageName, activityComponent, /* icon =*/ null, title, text, intent,
intentPersistableExtras, weight, extras, lastChangedTimestamp, flags,
iconRes, bitmapPath);
}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 5c1e7a8..c124255 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -968,7 +968,8 @@
return; // has no icon
}
- Bitmap bitmap = null;
+ Bitmap bitmap;
+ Bitmap bitmapToRecycle = null;
try {
switch (icon.getType()) {
case Icon.TYPE_RESOURCE: {
@@ -979,7 +980,7 @@
return;
}
case Icon.TYPE_BITMAP: {
- bitmap = icon.getBitmap();
+ bitmap = icon.getBitmap(); // Don't recycle in this case.
break;
}
case Icon.TYPE_URI: {
@@ -987,7 +988,8 @@
try (InputStream is = mContext.getContentResolver().openInputStream(uri)) {
- bitmap = BitmapFactory.decodeStream(is);
+ bitmapToRecycle = BitmapFactory.decodeStream(is);
+ bitmap = bitmapToRecycle;
} catch (IOException e) {
Slog.e(TAG, "Unable to load icon from " + uri);
@@ -1011,8 +1013,14 @@
try {
path = out.getFile();
- shrinkBitmap(bitmap, mMaxIconDimension)
- .compress(mIconPersistFormat, mIconPersistQuality, out);
+ Bitmap shrunk = shrinkBitmap(bitmap, mMaxIconDimension);
+ try {
+ shrunk.compress(mIconPersistFormat, mIconPersistQuality, out);
+ } finally {
+ if (bitmap != shrunk) {
+ shrunk.recycle();
+ }
+ }
shortcut.setBitmapPath(out.getFile().getAbsolutePath());
shortcut.addFlags(ShortcutInfo.FLAG_HAS_ICON_FILE);
@@ -1027,8 +1035,8 @@
}
}
} finally {
- if (bitmap != null) {
- bitmap.recycle();
+ if (bitmapToRecycle != null) {
+ bitmapToRecycle.recycle();
}
// Once saved, we won't use the original icon information, so null it out.
shortcut.clearIcon();
@@ -1076,8 +1084,6 @@
c.drawBitmap(in, /*src=*/ null, dst, /* paint =*/ null);
- in.recycle();
-
return scaledBitmap;
}
@@ -1580,13 +1586,17 @@
@Override
public List<ShortcutInfo> getShortcuts(int launcherUserId,
@NonNull String callingPackage, long changedSince,
- @Nullable String packageName, @Nullable ComponentName componentName,
+ @Nullable String packageName, @Nullable List<String> shortcutIds,
+ @Nullable ComponentName componentName,
int queryFlags, int userId) {
final ArrayList<ShortcutInfo> ret = new ArrayList<>();
final int cloneFlag =
((queryFlags & ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY) == 0)
? ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER
: ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO;
+ if (packageName == null) {
+ shortcutIds = null; // LauncherAppsService already threw for it though.
+ }
synchronized (mLock) {
getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
@@ -1594,14 +1604,14 @@
if (packageName != null) {
getShortcutsInnerLocked(launcherUserId,
- callingPackage, packageName, changedSince,
+ callingPackage, packageName, shortcutIds, changedSince,
componentName, queryFlags, userId, ret, cloneFlag);
} else {
final ArrayMap<String, ShortcutPackage> packages =
getUserShortcutsLocked(userId).getAllPackages();
for (int i = packages.size() - 1; i >= 0; i--) {
getShortcutsInnerLocked(launcherUserId,
- callingPackage, packages.keyAt(i), changedSince,
+ callingPackage, packages.keyAt(i), shortcutIds, changedSince,
componentName, queryFlags, userId, ret, cloneFlag);
}
}
@@ -1610,14 +1620,20 @@
}
private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage,
- @Nullable String packageName,long changedSince,
+ @Nullable String packageName, @Nullable List<String> shortcutIds, long changedSince,
@Nullable ComponentName componentName, int queryFlags,
int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) {
+ final ArraySet<String> ids = shortcutIds == null ? null
+ : new ArraySet<>(shortcutIds);
+
getPackageShortcutsLocked(packageName, userId).findAll(ShortcutService.this, ret,
(ShortcutInfo si) -> {
if (si.getLastChangedTimestamp() < changedSince) {
return false;
}
+ if (ids != null && !ids.contains(si.getId())) {
+ return false;
+ }
if (componentName != null
&& !componentName.equals(si.getActivityComponent())) {
return false;
@@ -1633,27 +1649,6 @@
}
@Override
- public List<ShortcutInfo> getShortcutInfo(int launcherUserId,
- @NonNull String callingPackage,
- @NonNull String packageName, @Nullable List<String> ids, int userId) {
- // Calling permission must be checked by LauncherAppsImpl.
- Preconditions.checkStringNotEmpty(packageName, "packageName");
-
- final ArrayList<ShortcutInfo> ret = new ArrayList<>(ids.size());
- final ArraySet<String> idSet = new ArraySet<>(ids);
- synchronized (mLock) {
- getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
- .attemptToRestoreIfNeededAndSave(ShortcutService.this);
-
- getPackageShortcutsLocked(packageName, userId).findAll(
- ShortcutService.this, ret,
- (ShortcutInfo si) -> idSet.contains(si.getId()),
- ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER, callingPackage, launcherUserId);
- }
- return ret;
- }
-
- @Override
public boolean isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
@NonNull String packageName, @NonNull String shortcutId, int userId) {
Preconditions.checkStringNotEmpty(packageName, "packageName");
@@ -1733,17 +1728,18 @@
}
@Override
- public int getShortcutIconResId(int launcherUserId,
- @NonNull String callingPackage,
- @NonNull ShortcutInfo shortcut, int userId) {
- Preconditions.checkNotNull(shortcut, "shortcut");
+ public int getShortcutIconResId(int launcherUserId, @NonNull String callingPackage,
+ @NonNull String packageName, @NonNull String shortcutId, int userId) {
+ Preconditions.checkNotNull(callingPackage, "callingPackage");
+ Preconditions.checkNotNull(packageName, "packageName");
+ Preconditions.checkNotNull(shortcutId, "shortcutId");
synchronized (mLock) {
getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
.attemptToRestoreIfNeededAndSave(ShortcutService.this);
final ShortcutInfo shortcutInfo = getPackageShortcutsLocked(
- shortcut.getPackageName(), userId).findShortcutById(shortcut.getId());
+ packageName, userId).findShortcutById(shortcutId);
return (shortcutInfo != null && shortcutInfo.hasIconResource())
? shortcutInfo.getIconResourceId() : 0;
}
@@ -1751,16 +1747,18 @@
@Override
public ParcelFileDescriptor getShortcutIconFd(int launcherUserId,
- @NonNull String callingPackage,
- @NonNull ShortcutInfo shortcutIn, int userId) {
- Preconditions.checkNotNull(shortcutIn, "shortcut");
+ @NonNull String callingPackage, @NonNull String packageName,
+ @NonNull String shortcutId, int userId) {
+ Preconditions.checkNotNull(callingPackage, "callingPackage");
+ Preconditions.checkNotNull(packageName, "packageName");
+ Preconditions.checkNotNull(shortcutId, "shortcutId");
synchronized (mLock) {
getLauncherShortcutsLocked(callingPackage, userId, launcherUserId)
.attemptToRestoreIfNeededAndSave(ShortcutService.this);
final ShortcutInfo shortcutInfo = getPackageShortcutsLocked(
- shortcutIn.getPackageName(), userId).findShortcutById(shortcutIn.getId());
+ packageName, userId).findShortcutById(shortcutId);
if (shortcutInfo == null || !shortcutInfo.hasIconFile()) {
return null;
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 06a91fb..60ea254 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -65,6 +65,7 @@
import android.system.Os;
import android.system.OsConstants;
import android.util.AtomicFile;
+import android.util.IntArray;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -467,13 +468,31 @@
@Override
public List<UserInfo> getProfiles(int userId, boolean enabledOnly) {
+ boolean returnFullInfo = true;
+ if (userId != UserHandle.getCallingUserId()) {
+ checkManageUsersPermission("getting profiles related to user " + userId);
+ } else {
+ returnFullInfo = hasManageUsersPermission();
+ }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mUsersLock) {
+ return getProfilesLU(userId, enabledOnly, returnFullInfo);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
+ public int[] getProfileIds(int userId, boolean enabledOnly) {
if (userId != UserHandle.getCallingUserId()) {
checkManageUsersPermission("getting profiles related to user " + userId);
}
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mUsersLock) {
- return getProfilesLU(userId, enabledOnly);
+ return getProfileIdsLU(userId, enabledOnly).toArray();
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -481,12 +500,34 @@
}
/** Assume permissions already checked and caller's identity cleared */
- private List<UserInfo> getProfilesLU(int userId, boolean enabledOnly) {
+ private List<UserInfo> getProfilesLU(int userId, boolean enabledOnly, boolean fullInfo) {
+ IntArray profileIds = getProfileIdsLU(userId, enabledOnly);
+ ArrayList<UserInfo> users = new ArrayList<>(profileIds.size());
+ for (int i = 0; i < profileIds.size(); i++) {
+ int profileId = profileIds.get(i);
+ UserInfo userInfo = mUsers.get(profileId).info;
+ // If full info is not required - clear PII data to prevent 3P apps from reading it
+ if (!fullInfo) {
+ userInfo = new UserInfo(userInfo);
+ userInfo.name = null;
+ userInfo.iconPath = null;
+ } else {
+ userInfo = userWithName(userInfo);
+ }
+ users.add(userInfo);
+ }
+ return users;
+ }
+
+ /**
+ * Assume permissions already checked and caller's identity cleared
+ */
+ private IntArray getProfileIdsLU(int userId, boolean enabledOnly) {
UserInfo user = getUserInfoLU(userId);
- ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
+ IntArray result = new IntArray(mUsers.size());
if (user == null) {
// Probably a dying user
- return users;
+ return result;
}
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
@@ -503,9 +544,9 @@
if (profile.partial) {
continue;
}
- users.add(userWithName(profile));
+ result.add(profile.id);
}
- return users;
+ return result;
}
@Override
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 97c0cf1..5ce451f 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -69,6 +69,7 @@
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPlaybackClient;
import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
+import android.hardware.input.InputManagerInternal;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioSystem;
@@ -305,6 +306,7 @@
WindowManagerInternal mWindowManagerInternal;
PowerManager mPowerManager;
ActivityManagerInternal mActivityManagerInternal;
+ InputManagerInternal mInputManagerInternal;
DreamManagerInternal mDreamManagerInternal;
PowerManagerInternal mPowerManagerInternal;
IStatusBarService mStatusBarService;
@@ -604,6 +606,9 @@
boolean mConsumeSearchKeyUp;
boolean mAssistKeyLongPressed;
boolean mPendingMetaAction;
+ boolean mPendingCapsLockToggle;
+ int mMetaState;
+ int mInitialMetaState;
boolean mForceShowSystemBars;
// support for activating the lock screen while the screen is on
@@ -687,9 +692,7 @@
private final LogDecelerateInterpolator mLogDecelerateInterpolator
= new LogDecelerateInterpolator(100, 0);
- private boolean mForceWindowDrawsStatusBarBackground;
private final MutableBoolean mTmpBoolean = new MutableBoolean(false);
-
private static final int MSG_ENABLE_POINTER_LOCATION = 1;
private static final int MSG_DISABLE_POINTER_LOCATION = 2;
private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
@@ -1494,6 +1497,7 @@
mWindowManagerFuncs = windowManagerFuncs;
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
+ mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
@@ -1739,8 +1743,6 @@
mScreenshotChordEnabled = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enableScreenshotChord);
- mForceWindowDrawsStatusBarBackground = mContext.getResources().getBoolean(
- R.bool.config_forceWindowDrawsStatusBarBackground);
mGlobalKeyManager = new GlobalKeyManager(mContext);
@@ -2211,9 +2213,12 @@
if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
}
+ final boolean forceWindowDrawsStatusBarBackground =
+ (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND)
+ != 0;
if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
- || (mForceWindowDrawsStatusBarBackground
- && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT)) {
+ || forceWindowDrawsStatusBarBackground
+ && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) {
attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
}
}
@@ -2968,6 +2973,10 @@
if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) {
mPendingMetaAction = false;
}
+ // Any key that is not Alt or Meta cancels Caps Lock combo tracking.
+ if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) {
+ mPendingCapsLockToggle = false;
+ }
// First we always handle the home key here, so applications
// can never break it, although if keyguard is on, we do let
@@ -3216,6 +3225,38 @@
}
}
+ // Toggle Caps Lock on META-ALT.
+ boolean actionTriggered = false;
+ if (KeyEvent.isModifierKey(keyCode)) {
+ if (!mPendingCapsLockToggle) {
+ // Start tracking meta state for combo.
+ mInitialMetaState = mMetaState;
+ mPendingCapsLockToggle = true;
+ } else if (event.getAction() == KeyEvent.ACTION_UP) {
+ int altOnMask = mMetaState & KeyEvent.META_ALT_MASK;
+ int metaOnMask = mMetaState & KeyEvent.META_META_MASK;
+
+ // Check for Caps Lock toggle
+ if ((metaOnMask != 0) && (altOnMask != 0)) {
+ // Check if nothing else is pressed
+ if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) {
+ // Handle Caps Lock Toggle
+ mInputManagerInternal.toggleCapsLock(event.getDeviceId());
+ actionTriggered = true;
+ }
+ }
+
+ // Always stop tracking when key goes up.
+ mPendingCapsLockToggle = false;
+ }
+ }
+ // Store current meta state to be able to evaluate it later.
+ mMetaState = metaState;
+
+ if (actionTriggered) {
+ return -1;
+ }
+
if (KeyEvent.isMetaKey(keyCode)) {
if (down) {
mPendingMetaAction = true;
@@ -4232,6 +4273,7 @@
}
final int fl = PolicyControl.getWindowFlags(win, attrs);
+ final int pfl = attrs.privateFlags;
final int sim = attrs.softInputMode;
final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
@@ -4327,7 +4369,7 @@
&& (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
&& (fl & WindowManager.LayoutParams.
FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
- && !mForceWindowDrawsStatusBarBackground) {
+ && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
// Ensure policy decor includes status bar
dcf.top = mStableTop;
}
@@ -7201,6 +7243,15 @@
return vis;
}
+ private boolean drawsSystemBarBackground(WindowState win) {
+ return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
+ }
+
+ private boolean forcesDrawStatusBarBackground(WindowState win) {
+ return win == null || (win.getAttrs().privateFlags
+ & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
+ }
+
private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
final boolean freeformStackVisible =
@@ -7214,11 +7265,22 @@
final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
// apply translucent bar vis flags
- WindowState transWin = isStatusBarKeyguard() && !mHideLockScreen
+ WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen
? mStatusBar
: mTopFullscreenOpaqueWindowState;
- vis = mStatusBarController.applyTranslucentFlagLw(transWin, vis, oldVis);
- vis = mNavigationBarController.applyTranslucentFlagLw(transWin, vis, oldVis);
+ vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
+ vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
+ final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
+ mTopDockedOpaqueWindowState, 0, 0);
+
+ final boolean fullscreenDrawsStatusBarBackground =
+ (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
+ && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
+ || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
+ final boolean dockedDrawsStatusBarBackground =
+ (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
+ && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
+ || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
// prevent status bar interaction from clearing certain flags
int type = win.getAttrs().type;
@@ -7235,18 +7297,16 @@
vis = (vis & ~flags) | (oldVis & flags);
}
- if ((!areTranslucentBarsAllowed() && transWin != mStatusBar)
+ if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
+ vis |= View.STATUS_BAR_TRANSPARENT;
+ vis &= ~View.STATUS_BAR_TRANSLUCENT;
+ } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
|| forceOpaqueStatusBar) {
vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
}
vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
- if (mForceWindowDrawsStatusBarBackground) {
- vis |= View.STATUS_BAR_TRANSPARENT;
- vis &= ~View.STATUS_BAR_TRANSLUCENT;
- }
-
// update status bar
boolean immersiveSticky =
(vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index bcafddc..5b9d139 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -93,6 +93,7 @@
// Indicates whether we are rebooting into safe mode
public static final String REBOOT_SAFEMODE_PROPERTY = "persist.sys.safemode";
+ public static final String RO_SAFEMODE_PROPERTY = "ro.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";
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index 858f7c7..9c2c6bf 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -375,7 +375,7 @@
} else {
mTrustAgentService.onConfigure(Collections.EMPTY_LIST, null);
}
- final long maxTimeToLock = dpm.getMaximumTimeToLock(null);
+ final long maxTimeToLock = dpm.getMaximumTimeToLockForUserAndProfiles(mUserId);
if (maxTimeToLock != mMaximumTimeToLock) {
// If the timeout changes, cancel the alarm and send a timeout event to have
// the agent re-evaluate trust.
diff --git a/services/core/java/com/android/server/vr/EnabledComponentsObserver.java b/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
index eb926c1..30194bf 100644
--- a/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
+++ b/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
@@ -24,7 +24,6 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.pm.UserInfo;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
@@ -213,18 +212,7 @@
if (userManager == null) {
return null;
}
- int currentUserId = ActivityManager.getCurrentUser();
- List<UserInfo> profiles = userManager.getProfiles(currentUserId);
- if (profiles == null) {
- return null;
- }
- final int s = profiles.size();
- int[] userIds = new int[s];
- int ctr = 0;
- for (UserInfo info : profiles) {
- userIds[ctr++] = info.id;
- }
- return userIds;
+ return userManager.getProfileIdsWithDisabled(ActivityManager.getCurrentUser());
}
public static ArraySet<ComponentName> loadComponentNames(PackageManager pm, int userId,
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index e6e5a2d..f004b45 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -490,8 +490,15 @@
private void revokeNotificationPolicyAccess(String pkg) {
NotificationManager nm = mContext.getSystemService(NotificationManager.class);
if (mPreviousNotificationPolicyAccessPackage != null) {
- nm.setNotificationPolicyAccessGranted(mPreviousNotificationPolicyAccessPackage, false);
- mPreviousNotificationPolicyAccessPackage = null;
+ if (mPreviousNotificationPolicyAccessPackage.equals(pkg)) {
+ // Remove any DND zen rules possibly created by the package.
+ nm.removeAutomaticZenRules(mPreviousNotificationPolicyAccessPackage);
+ // Remove Notification Policy Access.
+ nm.setNotificationPolicyAccessGranted(mPreviousNotificationPolicyAccessPackage, false);
+ mPreviousNotificationPolicyAccessPackage = null;
+ } else {
+ Slog.e(TAG, "Couldn't remove Notification Policy Access for package: " + pkg);
+ }
}
}
diff --git a/services/core/java/com/android/server/webkit/SystemImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java
index d82b8b4..ed935ce 100644
--- a/services/core/java/com/android/server/webkit/SystemImpl.java
+++ b/services/core/java/com/android/server/webkit/SystemImpl.java
@@ -19,6 +19,7 @@
import android.app.ActivityManagerNative;
import android.app.AppGlobals;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -184,15 +185,19 @@
@Override
public void uninstallAndDisablePackageForAllUsers(Context context, String packageName) {
- context.getPackageManager().deletePackage(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)
- enablePackageForAllUsers(context, packageName, false);
+ enablePackageForAllUsers(context, packageName, false);
+ try {
+ PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
+ ApplicationInfo applicationInfo = pm.getApplicationInfo(packageName, 0);
+ if (applicationInfo != null && applicationInfo.isUpdatedSystemApp()) {
+ pm.deletePackage(packageName, new IPackageDeleteObserver.Stub() {
+ public void packageDeleted(String packageName, int returnCode) {
+ enablePackageForAllUsers(context, packageName, false);
+ }
+ }, PackageManager.DELETE_SYSTEM_APP | PackageManager.DELETE_ALL_USERS);
}
- }, PackageManager.DELETE_SYSTEM_APP | PackageManager.DELETE_ALL_USERS);
+ } catch (NameNotFoundException e) {
+ }
}
@Override
@@ -211,8 +216,9 @@
enable ? PackageManager.COMPONENT_ENABLED_STATE_DEFAULT :
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, 0,
userId, null);
- } catch (RemoteException e) {
- Log.w(TAG, "Tried to disable " + packageName + " for user " + userId + ": " + e);
+ } catch (RemoteException | IllegalArgumentException e) {
+ Log.w(TAG, "Tried to " + (enable ? "enable " : "disable ") + packageName
+ + " for user " + userId + ": " + e);
}
}
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index 17efcc2..1f6fb2a 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -20,17 +20,12 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.Signature;
import android.os.Binder;
import android.os.PatternMatcher;
import android.os.Process;
import android.os.ResultReceiver;
import android.os.UserHandle;
-import android.util.Base64;
import android.util.Slog;
import android.webkit.IWebViewUpdateService;
import android.webkit.WebViewFactory;
@@ -40,9 +35,7 @@
import com.android.server.SystemService;
import java.io.FileDescriptor;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.List;
/**
* Private service to wait for the updatable WebView to be ready for use.
@@ -51,28 +44,18 @@
public class WebViewUpdateService extends SystemService {
private static final String TAG = "WebViewUpdateService";
- private static final int WAIT_TIMEOUT_MS = 4500; // KEY_DISPATCHING_TIMEOUT is 5000.
-
- // Keeps track of the number of running relro creations
- private int mNumRelroCreationsStarted = 0;
- private int mNumRelroCreationsFinished = 0;
- // Implies that we need to rerun relro creation because we are using an out-of-date package
- private boolean mWebViewPackageDirty = false;
- private boolean mAnyWebViewInstalled = false;
-
- private int NUMBER_OF_RELROS_UNKNOWN = Integer.MAX_VALUE;
-
- private int mMinimumVersionCode = -1;
-
- // The WebView package currently in use (or the one we are preparing).
- private PackageInfo mCurrentWebViewPackage = null;
private BroadcastReceiver mWebViewUpdatedReceiver;
- private SystemInterface mSystemInterface;
+ private WebViewUpdateServiceImpl mImpl;
+
+ static final int PACKAGE_CHANGED = 0;
+ static final int PACKAGE_ADDED = 1;
+ static final int PACKAGE_ADDED_REPLACED = 2;
+ static final int PACKAGE_REMOVED = 3;
public WebViewUpdateService(Context context) {
super(context);
- mSystemInterface = new SystemImpl();
+ mImpl = new WebViewUpdateServiceImpl(context, new SystemImpl());
}
@Override
@@ -80,76 +63,36 @@
mWebViewUpdatedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- // When a package is replaced we will receive two intents, one representing
- // the removal of the old package and one representing the addition of the
- // new package.
- // In the case where we receive an intent to remove the old version of the
- // package that is being replaced we early-out here so that we don't run the
- // update-logic twice.
- if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)
- && intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) {
- 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 (!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 : mSystemInterface.getWebViewPackages()) {
- String webviewPackage = "package:" + provider.packageName;
-
- if (webviewPackage.equals(intent.getDataString())) {
- boolean updateWebView = false;
- boolean removedOrChangedOldPackage = false;
- String oldProviderName = null;
- PackageInfo newPackage = null;
- synchronized(WebViewUpdateService.this) {
- try {
- newPackage = findPreferredWebViewPackage();
- if (mCurrentWebViewPackage != null)
- oldProviderName = mCurrentWebViewPackage.packageName;
- // Only trigger update actions if the updated package is the one
- // that will be used, or the one that was in use before the
- // update, or if we haven't seen a valid WebView package before.
- updateWebView =
- provider.packageName.equals(newPackage.packageName)
- || provider.packageName.equals(oldProviderName)
- || mCurrentWebViewPackage == null;
- // We removed the old package if we received an intent to remove
- // or replace the old package.
- removedOrChangedOldPackage =
- provider.packageName.equals(oldProviderName);
- if (updateWebView) {
- onWebViewProviderChanged(newPackage);
- }
- } catch (WebViewFactory.MissingWebViewPackageException e) {
- Slog.e(TAG, "Could not find valid WebView package to create " +
- "relro with " + e);
- }
+ switch (intent.getAction()) {
+ case Intent.ACTION_PACKAGE_REMOVED:
+ // When a package is replaced we will receive two intents, one
+ // representing the removal of the old package and one representing the
+ // addition of the new package.
+ // In the case where we receive an intent to remove the old version of
+ // the package that is being replaced we early-out here so that we don't
+ // run the update-logic twice.
+ if (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) return;
+ mImpl.packageStateChanged(packageNameFromIntent(intent),
+ PACKAGE_REMOVED);
+ break;
+ case Intent.ACTION_PACKAGE_CHANGED:
+ // Ensure that we only heed PACKAGE_CHANGED intents if they change an
+ // entire package, not just a component
+ if (entirePackageChanged(intent)) {
+ mImpl.packageStateChanged(packageNameFromIntent(intent),
+ PACKAGE_CHANGED);
}
- 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
- // only kills dependents of packages that are being removed.
- mSystemInterface.killPackageDependents(oldProviderName);
- }
- return;
- }
+ break;
+ case Intent.ACTION_PACKAGE_ADDED:
+ mImpl.packageStateChanged(packageNameFromIntent(intent),
+ (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)
+ ? PACKAGE_ADDED_REPLACED : PACKAGE_ADDED));
+ break;
+ case Intent.ACTION_USER_ADDED:
+ int userId =
+ intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+ mImpl.handleNewUser(userId);
+ break;
}
}
};
@@ -159,7 +102,7 @@
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 : mSystemInterface.getWebViewPackages()) {
+ for (WebViewProviderInfo provider : mImpl.getWebViewPackages()) {
filter.addDataSchemeSpecificPart(provider.packageName, PatternMatcher.PATTERN_LITERAL);
}
getContext().registerReceiver(mWebViewUpdatedReceiver, filter);
@@ -171,349 +114,12 @@
publishBinderService("webviewupdate", new BinderService(), true /*allowIsolated*/);
}
- private boolean existsValidNonFallbackProvider(WebViewProviderInfo[] providers) {
- for (WebViewProviderInfo provider : providers) {
- if (provider.availableByDefault && !provider.isFallback) {
- try {
- PackageInfo packageInfo = mSystemInterface.getPackageInfoForProvider(provider);
- if (isEnabledPackage(packageInfo) && isValidProvider(provider, packageInfo)) {
- return true;
- }
- } catch (NameNotFoundException e) {
- // A non-existent provider is neither valid nor enabled
- }
- }
- }
- return false;
- }
-
- /**
- * Called when a new user has been added to update the state of its fallback package.
- */
- void handleNewUser(int userId) {
- if (!mSystemInterface.isFallbackLogicEnabled()) return;
-
- WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
- WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders);
- if (fallbackProvider == null) return;
-
- mSystemInterface.enablePackageForUser(fallbackProvider.packageName,
- !existsValidNonFallbackProvider(webviewProviders), 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 (!mSystemInterface.isFallbackLogicEnabled()) return;
-
- WebViewProviderInfo[] webviewProviders = mSystemInterface.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.availableByDefault) {
- 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);
-
- boolean isFallbackEnabled = false;
- try {
- isFallbackEnabled =
- isEnabledPackage(mSystemInterface.getPackageInfoForProvider(fallbackProvider));
- } catch (NameNotFoundException e) {
- }
-
- 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.
- && (isFallbackEnabled || intent == null)) {
- mSystemInterface.uninstallAndDisablePackageForAllUsers(context,
- fallbackProvider.packageName);
- } 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.
- && (!isFallbackEnabled || intent==null)) {
- // Enable the fallback package for all users.
- mSystemInterface.enablePackageForAllUsers(context, fallbackProvider.packageName, true);
- }
- }
-
- /**
- * Returns the only fallback provider, or null if there is none.
- */
- private static WebViewProviderInfo getFallbackProvider(WebViewProviderInfo[] webviewPackages) {
- for (WebViewProviderInfo provider : webviewPackages) {
- if (provider.isFallback) {
- return provider;
- }
- }
- return null;
- }
-
- private boolean isFallbackPackage(String packageName) {
- if (packageName == null || !mSystemInterface.isFallbackLogicEnabled()) return false;
-
- WebViewProviderInfo[] webviewPackages = mSystemInterface.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.
- * This must be called in the system server.
- * Currently, this means spawning the child processes which will create the relro files.
- */
public void prepareWebViewInSystemServer() {
- updateFallbackState(getContext(), null);
- try {
- synchronized(this) {
- mCurrentWebViewPackage = findPreferredWebViewPackage();
- onWebViewProviderChanged(mCurrentWebViewPackage);
- }
- } catch (Throwable t) {
- // Log and discard errors at this stage as we must not crash the system server.
- Slog.e(TAG, "error preparing webview provider from system server", t);
- }
+ mImpl.prepareWebViewInSystemServer();
}
-
- /**
- * 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 String changeProviderAndSetting(String newProviderName) {
- PackageInfo oldPackage = null;
- PackageInfo newPackage = null;
- synchronized(this) {
- oldPackage = mCurrentWebViewPackage;
- mSystemInterface.updateUserSetting(getContext(), newProviderName);
-
- try {
- newPackage = findPreferredWebViewPackage();
- if (oldPackage != null && newPackage.packageName.equals(oldPackage.packageName)) {
- // If we don't perform the user change, revert the settings change.
- mSystemInterface.updateUserSetting(getContext(), newPackage.packageName);
- 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 newProviderName;
- }
- onWebViewProviderChanged(newPackage);
- }
- // Kill apps using the old provider
- if (oldPackage != null) {
- mSystemInterface.killPackageDependents(oldPackage.packageName);
- }
- return newPackage.packageName;
- }
-
- /**
- * This is called when we change WebView provider, either when the current provider is updated
- * or a new provider is chosen / takes precedence.
- */
- private void onWebViewProviderChanged(PackageInfo newPackage) {
- synchronized(this) {
- mAnyWebViewInstalled = true;
- if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
- mCurrentWebViewPackage = newPackage;
- mSystemInterface.updateUserSetting(getContext(), newPackage.packageName);
-
- // The relro creations might 'finish' (not start at all) before
- // WebViewFactory.onWebViewProviderChanged which means we might not know the number
- // of started creations before they finish.
- mNumRelroCreationsStarted = NUMBER_OF_RELROS_UNKNOWN;
- mNumRelroCreationsFinished = 0;
- mNumRelroCreationsStarted = mSystemInterface.onWebViewProviderChanged(newPackage);
- // If the relro creations finish before we know the number of started creations we
- // will have to do any cleanup/notifying here.
- checkIfRelrosDoneLocked();
- } else {
- mWebViewPackageDirty = true;
- }
- }
- }
-
- private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos() {
- WebViewProviderInfo[] allProviders = mSystemInterface.getWebViewPackages();
- List<ProviderAndPackageInfo> providers = new ArrayList<>();
- for(int n = 0; n < allProviders.length; n++) {
- try {
- PackageInfo packageInfo =
- mSystemInterface.getPackageInfoForProvider(allProviders[n]);
- if (isValidProvider(allProviders[n], packageInfo)) {
- providers.add(new ProviderAndPackageInfo(allProviders[n], packageInfo));
- }
- } catch (NameNotFoundException e) {
- // Don't add non-existent packages
- }
- }
- return providers.toArray(new ProviderAndPackageInfo[providers.size()]);
- }
-
- /**
- * Fetch only the currently valid WebView packages.
- **/
- private WebViewProviderInfo[] getValidWebViewPackages() {
- ProviderAndPackageInfo[] providersAndPackageInfos = getValidWebViewPackagesAndInfos();
- WebViewProviderInfo[] providers = new WebViewProviderInfo[providersAndPackageInfos.length];
- for(int n = 0; n < providersAndPackageInfos.length; n++) {
- providers[n] = providersAndPackageInfos[n].provider;
- }
- return providers;
- }
-
- private class ProviderAndPackageInfo {
- public final WebViewProviderInfo provider;
- public final PackageInfo packageInfo;
-
- public ProviderAndPackageInfo(WebViewProviderInfo provider, PackageInfo packageInfo) {
- this.provider = provider;
- this.packageInfo = packageInfo;
- }
- }
-
- /**
- * Returns either the package info of the WebView provider determined in the following way:
- * If the user has chosen a provider then use that if it is valid,
- * otherwise use the first package in the webview priority list that is valid.
- *
- * @hide
- */
- private PackageInfo findPreferredWebViewPackage() {
- ProviderAndPackageInfo[] providers = getValidWebViewPackagesAndInfos();
-
- String userChosenProvider = mSystemInterface.getUserChosenWebViewProvider(getContext());
-
- // If the user has chosen provider, use that
- for (ProviderAndPackageInfo providerAndPackage : providers) {
- if (providerAndPackage.provider.packageName.equals(userChosenProvider)
- && isEnabledPackage(providerAndPackage.packageInfo)) {
- return providerAndPackage.packageInfo;
- }
- }
-
- // User did not choose, or the choice failed; use the most stable provider that is
- // enabled and available by default (not through user choice).
- for (ProviderAndPackageInfo providerAndPackage : providers) {
- if (providerAndPackage.provider.availableByDefault
- && isEnabledPackage(providerAndPackage.packageInfo)) {
- return providerAndPackage.packageInfo;
- }
- }
-
- // Could not find any enabled package either, use the most stable provider.
- for (ProviderAndPackageInfo providerAndPackage : providers) {
- return providerAndPackage.packageInfo;
- }
-
- mAnyWebViewInstalled = false;
- throw new WebViewFactory.MissingWebViewPackageException(
- "Could not find a loadable WebView package");
- }
-
-
- /**
- * Gets the minimum version code allowed for a valid provider. It is the minimum versionCode of
- * all available-by-default and non-fallback WebView provider packages. If there is no such
- * WebView provider package on the system, then return -1, which means all positive versionCode
- * WebView packages are accepted.
- */
- private int getMinimumVersionCode() {
- if (mMinimumVersionCode > 0) {
- return mMinimumVersionCode;
- }
-
- for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) {
- if (provider.availableByDefault && !provider.isFallback) {
- try {
- int versionCode = mSystemInterface.getFactoryPackageVersion(provider.packageName);
- if (mMinimumVersionCode < 0 || versionCode < mMinimumVersionCode) {
- mMinimumVersionCode = versionCode;
- }
- } catch (PackageManager.NameNotFoundException e) {
- // Safe to ignore.
- }
- }
- }
-
- return mMinimumVersionCode;
- }
-
- /**
- * Returns whether this provider is valid for use as a WebView provider.
- */
- private boolean isValidProvider(WebViewProviderInfo configInfo,
- PackageInfo packageInfo) {
- if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
- && packageInfo.versionCode < getMinimumVersionCode()
- && !mSystemInterface.systemIsDebuggable()) {
- // Non-system package webview providers may be downgraded arbitrarily low, prevent that
- // by enforcing minimum version code. This check is only enforced for user builds.
- return false;
- }
- if (providerHasValidSignature(configInfo, packageInfo)
- && WebViewFactory.getWebViewLibrary(packageInfo.applicationInfo) != null) {
- return true;
- }
- return false;
- }
-
- private boolean providerHasValidSignature(WebViewProviderInfo provider,
- PackageInfo packageInfo) {
- if (mSystemInterface.systemIsDebuggable()) {
- return true;
- }
- Signature[] packageSignatures;
- // If no signature is declared, instead check whether the package is included in the
- // system.
- if (provider.signatures == null || provider.signatures.length == 0) {
- return packageInfo.applicationInfo.isSystemApp();
- }
- packageSignatures = packageInfo.signatures;
- if (packageSignatures.length != 1)
- return false;
-
- final byte[] packageSignature = packageSignatures[0].toByteArray();
- // Return whether the package signature matches any of the valid signatures
- for (String signature : provider.signatures) {
- final byte[] validSignature = Base64.decode(signature, Base64.DEFAULT);
- if (Arrays.equals(packageSignature, validSignature))
- return true;
- }
- return false;
- }
-
- /**
- * Returns whether the given package is enabled.
- * This state can be changed by the user from Settings->Apps
- */
- public boolean isEnabledPackage(PackageInfo packageInfo) {
- return packageInfo.applicationInfo.enabled;
+ private static String packageNameFromIntent(Intent intent) {
+ return intent.getDataString().substring("package:".length());
}
/**
@@ -528,32 +134,6 @@
intent.getDataString().substring("package:".length()));
}
- /**
- * Returns whether WebView is ready and is not going to go through its preparation phase again
- * directly.
- */
- private boolean webViewIsReadyLocked() {
- return !mWebViewPackageDirty
- && (mNumRelroCreationsStarted == mNumRelroCreationsFinished)
- // The current package might be replaced though we haven't received an intent declaring
- // this yet, the following flag makes anyone loading WebView to wait in this case.
- && mAnyWebViewInstalled;
- }
-
- private void checkIfRelrosDoneLocked() {
- if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
- if (mWebViewPackageDirty) {
- mWebViewPackageDirty = false;
- // If we have changed provider since we started the relro creation we need to
- // redo the whole process using the new package instead.
- PackageInfo newPackage = findPreferredWebViewPackage();
- onWebViewProviderChanged(newPackage);
- } else {
- this.notifyAll();
- }
- }
- }
-
private class BinderService extends IWebViewUpdateService.Stub {
@Override
@@ -581,10 +161,7 @@
long callingId = Binder.clearCallingIdentity();
try {
- synchronized (WebViewUpdateService.this) {
- mNumRelroCreationsFinished++;
- checkIfRelrosDoneLocked();
- }
+ WebViewUpdateService.this.mImpl.notifyRelroCreationCompleted();
} finally {
Binder.restoreCallingIdentity(callingId);
}
@@ -604,34 +181,7 @@
throw new IllegalStateException("Cannot create a WebView from the SystemServer");
}
- PackageInfo webViewPackage = null;
- final long NS_PER_MS = 1000000;
- final long timeoutTimeMs = System.nanoTime() / NS_PER_MS + WAIT_TIMEOUT_MS;
- boolean webViewReady = false;
- int webViewStatus = WebViewFactory.LIBLOAD_SUCCESS;
- synchronized (WebViewUpdateService.this) {
- webViewReady = WebViewUpdateService.this.webViewIsReadyLocked();
- while (!webViewReady) {
- final long timeNowMs = System.nanoTime() / NS_PER_MS;
- if (timeNowMs >= timeoutTimeMs) break;
- try {
- WebViewUpdateService.this.wait(timeoutTimeMs - timeNowMs);
- } catch (InterruptedException e) {}
- webViewReady = WebViewUpdateService.this.webViewIsReadyLocked();
- }
- // Make sure we return the provider that was used to create the relro file
- webViewPackage = WebViewUpdateService.this.mCurrentWebViewPackage;
- if (webViewReady) {
- } else if (!mAnyWebViewInstalled) {
- webViewStatus = WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES;
- } else {
- // Either the current relro creation isn't done yet, or the new relro creatioin
- // hasn't kicked off yet (the last relro creation used an out-of-date WebView).
- webViewStatus = WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO;
- }
- }
- if (!webViewReady) Slog.w(TAG, "creating relro file timed out");
- return new WebViewProviderResponse(webViewPackage, webViewStatus);
+ return WebViewUpdateService.this.mImpl.waitForAndGetProvider();
}
/**
@@ -652,7 +202,8 @@
long callingId = Binder.clearCallingIdentity();
try {
- return WebViewUpdateService.this.changeProviderAndSetting(newProvider);
+ return WebViewUpdateService.this.mImpl.changeProviderAndSetting(
+ newProvider);
} finally {
Binder.restoreCallingIdentity(callingId);
}
@@ -660,26 +211,22 @@
@Override // Binder call
public WebViewProviderInfo[] getValidWebViewPackages() {
- return WebViewUpdateService.this.getValidWebViewPackages();
+ return WebViewUpdateService.this.mImpl.getValidWebViewPackages();
}
@Override // Binder call
public WebViewProviderInfo[] getAllWebViewPackages() {
- return WebViewUpdateService.this.mSystemInterface.getWebViewPackages();
+ return WebViewUpdateService.this.mImpl.getWebViewPackages();
}
@Override // Binder call
public String getCurrentWebViewPackageName() {
- synchronized(WebViewUpdateService.this) {
- if (WebViewUpdateService.this.mCurrentWebViewPackage == null)
- return null;
- return WebViewUpdateService.this.mCurrentWebViewPackage.packageName;
- }
+ return WebViewUpdateService.this.mImpl.getCurrentWebViewPackageName();
}
@Override // Binder call
public boolean isFallbackPackage(String packageName) {
- return WebViewUpdateService.this.isFallbackPackage(packageName);
+ return WebViewUpdateService.this.mImpl.isFallbackPackage(packageName);
}
@Override // Binder call
@@ -695,7 +242,7 @@
throw new SecurityException(msg);
}
- WebViewUpdateService.this.mSystemInterface.enableFallbackLogic(enable);
+ WebViewUpdateService.this.mImpl.enableFallbackLogic(enable);
}
}
}
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
new file mode 100644
index 0000000..cd976e7
--- /dev/null
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
@@ -0,0 +1,590 @@
+/*
+ * 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.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.Signature;
+import android.util.Base64;
+import android.util.Slog;
+import android.webkit.WebViewFactory;
+import android.webkit.WebViewProviderInfo;
+import android.webkit.WebViewProviderResponse;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Implementation of the WebViewUpdateService.
+ * This class doesn't depend on the android system like the actual Service does and can be used
+ * directly by tests (as long as they implement a SystemInterface).
+ * @hide
+ */
+public class WebViewUpdateServiceImpl {
+ private static final String TAG = WebViewUpdateServiceImpl.class.getSimpleName();
+
+ private SystemInterface mSystemInterface;
+ private WebViewUpdater mWebViewUpdater;
+ private Context mContext;
+
+ public WebViewUpdateServiceImpl(Context context, SystemInterface systemInterface) {
+ mContext = context;
+ mSystemInterface = systemInterface;
+ mWebViewUpdater = new WebViewUpdater(mContext, mSystemInterface);
+ }
+
+ void packageStateChanged(String packageName, int changedState) {
+ updateFallbackStateOnPackageChange(packageName, changedState);
+ mWebViewUpdater.packageStateChanged(packageName, changedState);
+ }
+
+ void prepareWebViewInSystemServer() {
+ updateFallbackStateOnBoot();
+ mWebViewUpdater.prepareWebViewInSystemServer();
+ }
+
+ private boolean existsValidNonFallbackProvider(WebViewProviderInfo[] providers) {
+ for (WebViewProviderInfo provider : providers) {
+ if (provider.availableByDefault && !provider.isFallback) {
+ try {
+ PackageInfo packageInfo = mSystemInterface.getPackageInfoForProvider(provider);
+ if (isEnabledPackage(packageInfo)
+ && mWebViewUpdater.isValidProvider(provider, packageInfo)) {
+ return true;
+ }
+ } catch (NameNotFoundException e) {
+ // A non-existent provider is neither valid nor enabled
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Called when a new user has been added to update the state of its fallback package.
+ */
+ void handleNewUser(int userId) {
+ if (!mSystemInterface.isFallbackLogicEnabled()) return;
+
+ WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
+ WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders);
+ if (fallbackProvider == null) return;
+
+ mSystemInterface.enablePackageForUser(fallbackProvider.packageName,
+ !existsValidNonFallbackProvider(webviewProviders), userId);
+ }
+
+ void notifyRelroCreationCompleted() {
+ mWebViewUpdater.notifyRelroCreationCompleted();
+ }
+
+ WebViewProviderResponse waitForAndGetProvider() {
+ return mWebViewUpdater.waitForAndGetProvider();
+ }
+
+ String changeProviderAndSetting(String newProvider) {
+ return mWebViewUpdater.changeProviderAndSetting(newProvider);
+ }
+
+ WebViewProviderInfo[] getValidWebViewPackages() {
+ return mWebViewUpdater.getValidWebViewPackages();
+ }
+
+ WebViewProviderInfo[] getWebViewPackages() {
+ return mSystemInterface.getWebViewPackages();
+ }
+
+ String getCurrentWebViewPackageName() {
+ return mWebViewUpdater.getCurrentWebViewPackageName();
+ }
+
+ void enableFallbackLogic(boolean enable) {
+ mSystemInterface.enableFallbackLogic(enable);
+ }
+
+ private void updateFallbackStateOnBoot() {
+ WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
+ updateFallbackState(webviewProviders, true);
+ }
+
+ /**
+ * 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.
+ */
+ private void updateFallbackStateOnPackageChange(String changedPackage, int changedState) {
+ if (!mSystemInterface.isFallbackLogicEnabled()) return;
+
+ WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
+
+ // A package was changed / updated / downgraded, early out if it is not one of the
+ // webview packages that are available by default.
+ boolean changedPackageAvailableByDefault = false;
+ for (WebViewProviderInfo provider : webviewProviders) {
+ if (provider.packageName.equals(changedPackage)) {
+ if (provider.availableByDefault) {
+ changedPackageAvailableByDefault = true;
+ }
+ break;
+ }
+ }
+ if (!changedPackageAvailableByDefault) return;
+ updateFallbackState(webviewProviders, false);
+ }
+
+ private void updateFallbackState(WebViewProviderInfo[] webviewProviders, boolean isBoot) {
+ // 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);
+
+ boolean isFallbackEnabled = false;
+ try {
+ isFallbackEnabled = isEnabledPackage(
+ mSystemInterface.getPackageInfoForProvider(fallbackProvider));
+ } catch (NameNotFoundException e) {
+ // No fallback package installed -> early out.
+ return;
+ }
+
+ 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.
+ && (isFallbackEnabled || isBoot)) {
+ mSystemInterface.uninstallAndDisablePackageForAllUsers(mContext,
+ fallbackProvider.packageName);
+ } 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.
+ && (!isFallbackEnabled || isBoot)) {
+ // Enable the fallback package for all users.
+ mSystemInterface.enablePackageForAllUsers(mContext,
+ fallbackProvider.packageName, true);
+ }
+ }
+
+ /**
+ * Returns the only fallback provider in the set of given packages, or null if there is none.
+ */
+ private static WebViewProviderInfo getFallbackProvider(WebViewProviderInfo[] webviewPackages) {
+ for (WebViewProviderInfo provider : webviewPackages) {
+ if (provider.isFallback) {
+ return provider;
+ }
+ }
+ return null;
+ }
+
+ boolean isFallbackPackage(String packageName) {
+ if (packageName == null || !mSystemInterface.isFallbackLogicEnabled()) return false;
+
+ WebViewProviderInfo[] webviewPackages = mSystemInterface.getWebViewPackages();
+ WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewPackages);
+ return (fallbackProvider != null
+ && packageName.equals(fallbackProvider.packageName));
+ }
+
+ /**
+ * Class that decides what WebView implementation to use and prepares that implementation for
+ * use.
+ */
+ private static class WebViewUpdater {
+ private Context mContext;
+ private SystemInterface mSystemInterface;
+ private int mMinimumVersionCode = -1;
+
+ public WebViewUpdater(Context context, SystemInterface systemInterface) {
+ mContext = context;
+ mSystemInterface = systemInterface;
+ }
+
+ private static final int WAIT_TIMEOUT_MS = 4500; // KEY_DISPATCHING_TIMEOUT is 5000.
+
+ // Keeps track of the number of running relro creations
+ private int mNumRelroCreationsStarted = 0;
+ private int mNumRelroCreationsFinished = 0;
+ // Implies that we need to rerun relro creation because we are using an out-of-date package
+ private boolean mWebViewPackageDirty = false;
+ private boolean mAnyWebViewInstalled = false;
+
+ private int NUMBER_OF_RELROS_UNKNOWN = Integer.MAX_VALUE;
+
+ // The WebView package currently in use (or the one we are preparing).
+ private PackageInfo mCurrentWebViewPackage = null;
+
+ private Object mLock = new Object();
+
+ public void packageStateChanged(String packageName, int changedState) {
+ for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) {
+ String webviewPackage = provider.packageName;
+
+ if (webviewPackage.equals(packageName)) {
+ boolean updateWebView = false;
+ boolean removedOrChangedOldPackage = false;
+ String oldProviderName = null;
+ PackageInfo newPackage = null;
+ synchronized(mLock) {
+ try {
+ newPackage = findPreferredWebViewPackage();
+ if (mCurrentWebViewPackage != null)
+ oldProviderName = mCurrentWebViewPackage.packageName;
+ // Only trigger update actions if the updated package is the one
+ // that will be used, or the one that was in use before the
+ // update, or if we haven't seen a valid WebView package before.
+ updateWebView =
+ provider.packageName.equals(newPackage.packageName)
+ || provider.packageName.equals(oldProviderName)
+ || mCurrentWebViewPackage == null;
+ // We removed the old package if we received an intent to remove
+ // or replace the old package.
+ removedOrChangedOldPackage =
+ provider.packageName.equals(oldProviderName);
+ if (updateWebView) {
+ onWebViewProviderChanged(newPackage);
+ }
+ } catch (WebViewFactory.MissingWebViewPackageException e) {
+ Slog.e(TAG, "Could not find valid WebView package to create " +
+ "relro with " + e);
+ }
+ }
+ 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
+ // only kills dependents of packages that are being removed.
+ mSystemInterface.killPackageDependents(oldProviderName);
+ }
+ return;
+ }
+ }
+ }
+
+ public void prepareWebViewInSystemServer() {
+ try {
+ synchronized(mLock) {
+ mCurrentWebViewPackage = findPreferredWebViewPackage();
+ onWebViewProviderChanged(mCurrentWebViewPackage);
+ }
+ } catch (Throwable t) {
+ // Log and discard errors at this stage as we must not crash the system server.
+ Slog.e(TAG, "error preparing webview provider from system server", t);
+ }
+ }
+
+ /**
+ * 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).
+ */
+ public String changeProviderAndSetting(String newProviderName) {
+ PackageInfo oldPackage = null;
+ PackageInfo newPackage = null;
+ synchronized(mLock) {
+ oldPackage = mCurrentWebViewPackage;
+ mSystemInterface.updateUserSetting(mContext, newProviderName);
+
+ try {
+ newPackage = findPreferredWebViewPackage();
+ if (oldPackage != null
+ && newPackage.packageName.equals(oldPackage.packageName)) {
+ // If we don't perform the user change, revert the settings change.
+ mSystemInterface.updateUserSetting(mContext, newPackage.packageName);
+ 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 newProviderName;
+ }
+ onWebViewProviderChanged(newPackage);
+ }
+ // Kill apps using the old provider
+ if (oldPackage != null) {
+ mSystemInterface.killPackageDependents(oldPackage.packageName);
+ }
+ return newPackage.packageName;
+ }
+
+ /**
+ * This is called when we change WebView provider, either when the current provider is
+ * updated or a new provider is chosen / takes precedence.
+ */
+ private void onWebViewProviderChanged(PackageInfo newPackage) {
+ synchronized(mLock) {
+ mAnyWebViewInstalled = true;
+ if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
+ mCurrentWebViewPackage = newPackage;
+ mSystemInterface.updateUserSetting(mContext, newPackage.packageName);
+
+ // The relro creations might 'finish' (not start at all) before
+ // WebViewFactory.onWebViewProviderChanged which means we might not know the
+ // number of started creations before they finish.
+ mNumRelroCreationsStarted = NUMBER_OF_RELROS_UNKNOWN;
+ mNumRelroCreationsFinished = 0;
+ mNumRelroCreationsStarted =
+ mSystemInterface.onWebViewProviderChanged(newPackage);
+ // If the relro creations finish before we know the number of started creations
+ // we will have to do any cleanup/notifying here.
+ checkIfRelrosDoneLocked();
+ } else {
+ mWebViewPackageDirty = true;
+ }
+ }
+ }
+
+ private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos() {
+ WebViewProviderInfo[] allProviders = mSystemInterface.getWebViewPackages();
+ List<ProviderAndPackageInfo> providers = new ArrayList<>();
+ for(int n = 0; n < allProviders.length; n++) {
+ try {
+ PackageInfo packageInfo =
+ mSystemInterface.getPackageInfoForProvider(allProviders[n]);
+ if (isValidProvider(allProviders[n], packageInfo)) {
+ providers.add(new ProviderAndPackageInfo(allProviders[n], packageInfo));
+ }
+ } catch (NameNotFoundException e) {
+ // Don't add non-existent packages
+ }
+ }
+ return providers.toArray(new ProviderAndPackageInfo[providers.size()]);
+ }
+
+ /**
+ * Fetch only the currently valid WebView packages.
+ **/
+ public WebViewProviderInfo[] getValidWebViewPackages() {
+ ProviderAndPackageInfo[] providersAndPackageInfos = getValidWebViewPackagesAndInfos();
+ WebViewProviderInfo[] providers =
+ new WebViewProviderInfo[providersAndPackageInfos.length];
+ for(int n = 0; n < providersAndPackageInfos.length; n++) {
+ providers[n] = providersAndPackageInfos[n].provider;
+ }
+ return providers;
+ }
+
+
+ private class ProviderAndPackageInfo {
+ public final WebViewProviderInfo provider;
+ public final PackageInfo packageInfo;
+
+ public ProviderAndPackageInfo(WebViewProviderInfo provider, PackageInfo packageInfo) {
+ this.provider = provider;
+ this.packageInfo = packageInfo;
+ }
+ }
+
+ /**
+ * Returns either the package info of the WebView provider determined in the following way:
+ * If the user has chosen a provider then use that if it is valid,
+ * otherwise use the first package in the webview priority list that is valid.
+ *
+ */
+ private PackageInfo findPreferredWebViewPackage() {
+ ProviderAndPackageInfo[] providers = getValidWebViewPackagesAndInfos();
+
+ String userChosenProvider = mSystemInterface.getUserChosenWebViewProvider(mContext);
+
+ // If the user has chosen provider, use that
+ for (ProviderAndPackageInfo providerAndPackage : providers) {
+ if (providerAndPackage.provider.packageName.equals(userChosenProvider)
+ && isEnabledPackage(providerAndPackage.packageInfo)) {
+ return providerAndPackage.packageInfo;
+ }
+ }
+
+ // User did not choose, or the choice failed; use the most stable provider that is
+ // enabled and available by default (not through user choice).
+ for (ProviderAndPackageInfo providerAndPackage : providers) {
+ if (providerAndPackage.provider.availableByDefault
+ && isEnabledPackage(providerAndPackage.packageInfo)) {
+ return providerAndPackage.packageInfo;
+ }
+ }
+
+ // Could not find any enabled package either, use the most stable provider.
+ for (ProviderAndPackageInfo providerAndPackage : providers) {
+ return providerAndPackage.packageInfo;
+ }
+
+ mAnyWebViewInstalled = false;
+ throw new WebViewFactory.MissingWebViewPackageException(
+ "Could not find a loadable WebView package");
+ }
+
+ public void notifyRelroCreationCompleted() {
+ synchronized (mLock) {
+ mNumRelroCreationsFinished++;
+ checkIfRelrosDoneLocked();
+ }
+ }
+
+ public WebViewProviderResponse waitForAndGetProvider() {
+ PackageInfo webViewPackage = null;
+ final long NS_PER_MS = 1000000;
+ final long timeoutTimeMs = System.nanoTime() / NS_PER_MS + WAIT_TIMEOUT_MS;
+ boolean webViewReady = false;
+ int webViewStatus = WebViewFactory.LIBLOAD_SUCCESS;
+ synchronized (mLock) {
+ webViewReady = webViewIsReadyLocked();
+ while (!webViewReady) {
+ final long timeNowMs = System.nanoTime() / NS_PER_MS;
+ if (timeNowMs >= timeoutTimeMs) break;
+ try {
+ mLock.wait(timeoutTimeMs - timeNowMs);
+ } catch (InterruptedException e) {}
+ webViewReady = webViewIsReadyLocked();
+ }
+ // Make sure we return the provider that was used to create the relro file
+ webViewPackage = mCurrentWebViewPackage;
+ if (webViewReady) {
+ } else if (!mAnyWebViewInstalled) {
+ webViewStatus = WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES;
+ } else {
+ // Either the current relro creation isn't done yet, or the new relro creatioin
+ // hasn't kicked off yet (the last relro creation used an out-of-date WebView).
+ webViewStatus = WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO;
+ }
+ }
+ if (!webViewReady) Slog.w(TAG, "creating relro file timed out");
+ return new WebViewProviderResponse(webViewPackage, webViewStatus);
+ }
+
+ public String getCurrentWebViewPackageName() {
+ synchronized(mLock) {
+ if (mCurrentWebViewPackage == null)
+ return null;
+ return mCurrentWebViewPackage.packageName;
+ }
+ }
+
+ /**
+ * Returns whether WebView is ready and is not going to go through its preparation phase
+ * again directly.
+ */
+ private boolean webViewIsReadyLocked() {
+ return !mWebViewPackageDirty
+ && (mNumRelroCreationsStarted == mNumRelroCreationsFinished)
+ // The current package might be replaced though we haven't received an intent
+ // declaring this yet, the following flag makes anyone loading WebView to wait in
+ // this case.
+ && mAnyWebViewInstalled;
+ }
+
+ private void checkIfRelrosDoneLocked() {
+ if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
+ if (mWebViewPackageDirty) {
+ mWebViewPackageDirty = false;
+ // If we have changed provider since we started the relro creation we need to
+ // redo the whole process using the new package instead.
+ PackageInfo newPackage = findPreferredWebViewPackage();
+ onWebViewProviderChanged(newPackage);
+ } else {
+ mLock.notifyAll();
+ }
+ }
+ }
+
+ /**
+ * Returns whether this provider is valid for use as a WebView provider.
+ */
+ public boolean isValidProvider(WebViewProviderInfo configInfo,
+ PackageInfo packageInfo) {
+ if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
+ && packageInfo.versionCode < getMinimumVersionCode()
+ && !mSystemInterface.systemIsDebuggable()) {
+ // Non-system package webview providers may be downgraded arbitrarily low, prevent
+ // that by enforcing minimum version code. This check is only enforced for user
+ // builds.
+ return false;
+ }
+ if (providerHasValidSignature(configInfo, packageInfo, mSystemInterface) &&
+ WebViewFactory.getWebViewLibrary(packageInfo.applicationInfo) != null) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Gets the minimum version code allowed for a valid provider. It is the minimum versionCode
+ * of all available-by-default and non-fallback WebView provider packages. If there is no
+ * such WebView provider package on the system, then return -1, which means all positive
+ * versionCode WebView packages are accepted.
+ */
+ private int getMinimumVersionCode() {
+ if (mMinimumVersionCode > 0) {
+ return mMinimumVersionCode;
+ }
+
+ for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) {
+ if (provider.availableByDefault && !provider.isFallback) {
+ try {
+ int versionCode =
+ mSystemInterface.getFactoryPackageVersion(provider.packageName);
+ if (mMinimumVersionCode < 0 || versionCode < mMinimumVersionCode) {
+ mMinimumVersionCode = versionCode;
+ }
+ } catch (NameNotFoundException e) {
+ // Safe to ignore.
+ }
+ }
+ }
+
+ return mMinimumVersionCode;
+ }
+ }
+
+ private static boolean providerHasValidSignature(WebViewProviderInfo provider,
+ PackageInfo packageInfo, SystemInterface systemInterface) {
+ if (systemInterface.systemIsDebuggable()) {
+ return true;
+ }
+ Signature[] packageSignatures;
+ // If no signature is declared, instead check whether the package is included in the
+ // system.
+ if (provider.signatures == null || provider.signatures.length == 0) {
+ return packageInfo.applicationInfo.isSystemApp();
+ }
+ packageSignatures = packageInfo.signatures;
+ if (packageSignatures.length != 1)
+ return false;
+
+ final byte[] packageSignature = packageSignatures[0].toByteArray();
+ // Return whether the package signature matches any of the valid signatures
+ for (String signature : provider.signatures) {
+ final byte[] validSignature = Base64.decode(signature, Base64.DEFAULT);
+ if (Arrays.equals(packageSignature, validSignature))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns whether the given package is enabled.
+ * This state can be changed by the user from Settings->Apps
+ */
+ private static boolean isEnabledPackage(PackageInfo packageInfo) {
+ return packageInfo.applicationInfo.enabled;
+ }
+
+}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index bae628a..3ef077b 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -1214,7 +1214,10 @@
window.type = windowState.mAttrs.type;
window.layer = windowState.mLayer;
window.token = windowState.mClient.asBinder();
- window.title = windowState.mAttrs.getTitle();
+ window.title = windowState.mAttrs.accessibilityTitle;
+ if (window.title == null) {
+ window.title = windowState.mAttrs.getTitle();
+ }
window.accessibilityIdOfAnchor = windowState.mAttrs.accessibilityIdOfAnchor;
WindowState attachedWindow = windowState.mAttachedWindow;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index eea0ca0..7b16dbe 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -16,24 +16,17 @@
package com.android.server.wm;
+import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
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.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;
import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.H.RESIZE_TASK;
-import static com.android.server.wm.WindowManagerService.H.SHOW_NON_RESIZEABLE_DOCK_TOAST;
-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;
import android.app.ActivityManager.StackId;
import android.content.pm.ActivityInfo;
@@ -44,7 +37,6 @@
import android.view.DisplayInfo;
import android.view.Surface;
-import com.android.internal.R;
import com.android.server.EventLogTags;
import java.io.PrintWriter;
@@ -94,11 +86,6 @@
// Resize mode of the task. See {@link ActivityInfo#resizeMode}
private int mResizeMode;
- // Whether we need to show toast about the app being non-resizeable when it becomes visible.
- // This flag is set when a non-resizeable task is docked (or side-by-side). It's cleared
- // after we show the toast.
- private boolean mShowNonResizeableDockToast;
-
// Whether the task is currently being drag-resized
private boolean mDragResizing;
private int mDragResizeMode;
@@ -118,30 +105,6 @@
return mStack.getDisplayContent();
}
- void setShowNonResizeableDockToast() {
- mShowNonResizeableDockToast = true;
- }
-
- void scheduleShowNonResizeableDockToastIfNeeded() {
- if (!mShowNonResizeableDockToast) {
- return;
- }
- final DisplayContent displayContent = mStack.getDisplayContent();
- // If docked stack is not yet visible, we don't want to show the toast yet,
- // since we need the visible rect of the docked task to position the toast.
- if (displayContent == null || displayContent.getDockedStackLocked() == null) {
- return;
- }
-
- mShowNonResizeableDockToast = false;
-
- if (mResizeMode == RESIZE_MODE_UNRESIZEABLE) {
- final String text =
- mService.mContext.getString(R.string.dock_non_resizeble_failed_to_dock_text);
- mService.mH.obtainMessage(SHOW_NON_RESIZEABLE_DOCK_TOAST, 0, 0, text).sendToTarget();
- }
- }
-
void addAppToken(int addPos, AppWindowToken wtoken, int resizeMode, boolean homeTask) {
final int lastPos = mAppTokens.size();
if (addPos >= lastPos) {
@@ -595,6 +558,12 @@
if (win.mHasSurface && !resizingWindows.contains(win)) {
if (DEBUG_RESIZE) Slog.d(TAG, "resizeWindows: Resizing " + win);
resizingWindows.add(win);
+
+ // If we are not drag resizing, force recreating of a new surface so updating
+ // the content and positioning that surface will be in sync.
+ if (!win.computeDragResizing()) {
+ win.mResizedWhileNotDragResizing = true;
+ }
}
if (win.isGoneForLayoutLw()) {
win.mResizedWhileGone = true;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 3430ac9..446b74b 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -720,9 +720,9 @@
}
} else {
if (splitHorizontally) {
- outBounds.left = position - dockDividerWidth;
+ outBounds.left = position + dockDividerWidth;
} else {
- outBounds.top = position - dockDividerWidth;
+ outBounds.top = position + dockDividerWidth;
}
}
return;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 664a58b..57f38d1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2935,8 +2935,9 @@
// If we're starting a drag-resize, we'll be changing the surface size as well as
// notifying the client to render to with an offset from the surface's top-left.
- if (win.isDragResizeChanged()) {
+ if (win.isDragResizeChanged() || win.mResizedWhileNotDragResizing) {
win.setDragResizing();
+ win.mResizedWhileNotDragResizing = false;
// We can only change top level windows to the full-screen surface when
// resizing (as we only have one full-screen surface). So there is no need
// to preserve and destroy windows which are attached to another, they
@@ -4192,6 +4193,7 @@
WindowManagerPolicy.TRANSIT_EXIT);
}
}
+ win.mAnimatingExit = true;
changed = true;
win.setDisplayLayoutNeeded();
}
@@ -4939,17 +4941,6 @@
}
}
- public void scheduleShowNonResizeableDockToast(int taskId) {
- synchronized (mWindowMap) {
- Task task = mTaskIdToTask.get(taskId);
- if (task == null) {
- if (DEBUG_STACK) Slog.i(TAG_WM, "scheduleShowToast: could not find taskId=" + taskId);
- return;
- }
- task.setShowNonResizeableDockToast();
- }
- }
-
@Override
public void getStackBounds(int stackId, Rect bounds) {
synchronized (mWindowMap) {
@@ -6034,7 +6025,6 @@
minLayer = Integer.MAX_VALUE;
}
- int retryCount = 0;
WindowState appWin = null;
boolean appIsImTarget;
@@ -6048,193 +6038,172 @@
final int aboveAppLayer = (mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
* TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
- while (true) {
- if (retryCount++ > 0) {
- // Reset max/min layers on retries so we don't accidentally take a screenshot of a
- // layer based on the previous try.
- maxLayer = 0;
- minLayer = Integer.MAX_VALUE;
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- }
- }
- synchronized(mWindowMap) {
- // Figure out the part of the screen that is actually the app.
- appWin = null;
- final WindowList windows = displayContent.getWindowList();
- for (int i = windows.size() - 1; i >= 0; i--) {
- WindowState ws = windows.get(i);
- if (!ws.mHasSurface) {
- continue;
- }
- if (ws.mLayer >= aboveAppLayer) {
- continue;
- }
- if (ws.mIsImWindow) {
- if (!appIsImTarget) {
- continue;
- }
- } else if (ws.mIsWallpaper) {
- if (appWin == null) {
- // We have not ran across the target window yet, so it is probably
- // behind the wallpaper. This can happen when the keyguard is up and
- // all windows are moved behind the wallpaper. We don't want to
- // include the wallpaper layer in the screenshot as it will coverup
- // the layer of the target window.
- continue;
- }
- // Fall through. The target window is in front of the wallpaper. For this
- // case we want to include the wallpaper layer in the screenshot because
- // the target window might have some transparent areas.
- } else if (appToken != null) {
- if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
- // This app window is of no interest if it is not associated with the
- // screenshot app.
- continue;
- }
- appWin = ws;
- }
-
- // Include this window.
-
- final WindowStateAnimator winAnim = ws.mWinAnimator;
- int layer = winAnim.mSurfaceController.getLayer();
- if (maxLayer < layer) {
- maxLayer = layer;
- }
- if (minLayer > layer) {
- minLayer = layer;
- }
-
- // Don't include wallpaper in bounds calculation
- if (!includeFullDisplay && !ws.mIsWallpaper) {
- final Rect wf = ws.mFrame;
- final Rect cr = ws.mContentInsets;
- int left = wf.left + cr.left;
- int top = wf.top + cr.top;
- int right = wf.right - cr.right;
- int bottom = wf.bottom - cr.bottom;
- frame.union(left, top, right, bottom);
- ws.getVisibleBounds(stackBounds);
- if (!Rect.intersects(frame, stackBounds)) {
- // Set frame empty if there's no intersection.
- frame.setEmpty();
- }
- }
-
- if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
- ws.isDisplayedLw() && winAnim.getShown()) {
- screenshotReady = true;
- }
-
- if (ws.isObscuringFullscreen(displayInfo)){
- break;
- }
- }
-
- if (appToken != null && appWin == null) {
- // Can't find a window to snapshot.
- if (DEBUG_SCREENSHOT) Slog.i(TAG_WM,
- "Screenshot: Couldn't find a surface matching " + appToken);
- return null;
- }
-
- if (!screenshotReady) {
- if (retryCount > MAX_SCREENSHOT_RETRIES) {
- Slog.i(TAG_WM, "Screenshot max retries " + retryCount + " of " + appToken +
- " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" +
- appWin.mWinAnimator.mDrawState)));
- return null;
- }
-
- // Delay and hope that window gets drawn.
- if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot: No image ready for " + appToken
- + ", " + appWin + " drawState=" + appWin.mWinAnimator.mDrawState);
+ synchronized(mWindowMap) {
+ // Figure out the part of the screen that is actually the app.
+ appWin = null;
+ final WindowList windows = displayContent.getWindowList();
+ for (int i = windows.size() - 1; i >= 0; i--) {
+ WindowState ws = windows.get(i);
+ if (!ws.mHasSurface) {
continue;
}
-
- // Screenshot is ready to be taken. Everything from here below will continue
- // through the bottom of the loop and return a value. We only stay in the loop
- // because we don't want to release the mWindowMap lock until the screenshot is
- // taken.
-
- if (maxLayer == 0) {
- if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
- + ": returning null maxLayer=" + maxLayer);
- return null;
+ if (ws.mLayer >= aboveAppLayer) {
+ continue;
+ }
+ if (ws.mIsImWindow) {
+ if (!appIsImTarget) {
+ continue;
+ }
+ } else if (ws.mIsWallpaper) {
+ if (appWin == null) {
+ // We have not ran across the target window yet, so it is probably
+ // behind the wallpaper. This can happen when the keyguard is up and
+ // all windows are moved behind the wallpaper. We don't want to
+ // include the wallpaper layer in the screenshot as it will coverup
+ // the layer of the target window.
+ continue;
+ }
+ // Fall through. The target window is in front of the wallpaper. For this
+ // case we want to include the wallpaper layer in the screenshot because
+ // the target window might have some transparent areas.
+ } else if (appToken != null) {
+ if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
+ // This app window is of no interest if it is not associated with the
+ // screenshot app.
+ continue;
+ }
+ appWin = ws;
}
- if (!includeFullDisplay) {
- // Constrain frame to the screen size.
- if (!frame.intersect(0, 0, dw, dh)) {
+ // Include this window.
+
+ final WindowStateAnimator winAnim = ws.mWinAnimator;
+ int layer = winAnim.mSurfaceController.getLayer();
+ if (maxLayer < layer) {
+ maxLayer = layer;
+ }
+ if (minLayer > layer) {
+ minLayer = layer;
+ }
+
+ // Don't include wallpaper in bounds calculation
+ if (!includeFullDisplay && !ws.mIsWallpaper) {
+ final Rect wf = ws.mFrame;
+ final Rect cr = ws.mContentInsets;
+ int left = wf.left + cr.left;
+ int top = wf.top + cr.top;
+ int right = wf.right - cr.right;
+ int bottom = wf.bottom - cr.bottom;
+ frame.union(left, top, right, bottom);
+ ws.getVisibleBounds(stackBounds);
+ if (!Rect.intersects(frame, stackBounds)) {
+ // Set frame empty if there's no intersection.
frame.setEmpty();
}
- } else {
- // Caller just wants entire display.
- frame.set(0, 0, dw, dh);
- }
- if (frame.isEmpty()) {
- return null;
}
- if (width < 0) {
- width = (int) (frame.width() * frameScale);
- }
- if (height < 0) {
- height = (int) (frame.height() * frameScale);
+ if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
+ ws.isDisplayedLw() && winAnim.getShown()) {
+ screenshotReady = true;
}
- // Tell surface flinger what part of the image to crop. Take the top
- // right part of the application, and crop the larger dimension to fit.
- Rect crop = new Rect(frame);
- if (width / (float) frame.width() < height / (float) frame.height()) {
- int cropWidth = (int)((float)width / (float)height * frame.height());
- crop.right = crop.left + cropWidth;
- } else {
- int cropHeight = (int)((float)height / (float)width * frame.width());
- crop.bottom = crop.top + cropHeight;
- }
-
- // The screenshot API does not apply the current screen rotation.
- int rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
-
- if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
- rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
- }
-
- // Surfaceflinger is not aware of orientation, so convert our logical
- // crop to surfaceflinger's portrait orientation.
- convertCropForSurfaceFlinger(crop, rot, dw, dh);
-
- if (DEBUG_SCREENSHOT) {
- Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
- + maxLayer + " appToken=" + appToken);
- for (int i = 0; i < windows.size(); i++) {
- WindowState win = windows.get(i);
- Slog.i(TAG_WM, win + ": " + win.mLayer
- + " animLayer=" + win.mWinAnimator.mAnimLayer
- + " surfaceLayer=" + win.mWinAnimator.mSurfaceController.getLayer());
- }
- }
-
- ScreenRotationAnimation screenRotationAnimation =
- mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
- final boolean inRotation = screenRotationAnimation != null &&
- screenRotationAnimation.isAnimating();
- if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM,
- "Taking screenshot while rotating");
-
- bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
- inRotation, rot);
- if (bm == null) {
- Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh
- + ") to layer " + maxLayer);
- return null;
+ if (ws.isObscuringFullscreen(displayInfo)){
+ break;
}
}
- break;
+ if (appToken != null && appWin == null) {
+ // Can't find a window to snapshot.
+ if (DEBUG_SCREENSHOT) Slog.i(TAG_WM,
+ "Screenshot: Couldn't find a surface matching " + appToken);
+ return null;
+ }
+
+ if (!screenshotReady) {
+ Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken +
+ " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" +
+ appWin.mWinAnimator.mDrawState)));
+ return null;
+ }
+
+ // Screenshot is ready to be taken. Everything from here below will continue
+ // through the bottom of the loop and return a value. We only stay in the loop
+ // because we don't want to release the mWindowMap lock until the screenshot is
+ // taken.
+
+ if (maxLayer == 0) {
+ if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
+ + ": returning null maxLayer=" + maxLayer);
+ return null;
+ }
+
+ if (!includeFullDisplay) {
+ // Constrain frame to the screen size.
+ if (!frame.intersect(0, 0, dw, dh)) {
+ frame.setEmpty();
+ }
+ } else {
+ // Caller just wants entire display.
+ frame.set(0, 0, dw, dh);
+ }
+ if (frame.isEmpty()) {
+ return null;
+ }
+
+ if (width < 0) {
+ width = (int) (frame.width() * frameScale);
+ }
+ if (height < 0) {
+ height = (int) (frame.height() * frameScale);
+ }
+
+ // Tell surface flinger what part of the image to crop. Take the top
+ // right part of the application, and crop the larger dimension to fit.
+ Rect crop = new Rect(frame);
+ if (width / (float) frame.width() < height / (float) frame.height()) {
+ int cropWidth = (int)((float)width / (float)height * frame.height());
+ crop.right = crop.left + cropWidth;
+ } else {
+ int cropHeight = (int)((float)height / (float)width * frame.width());
+ crop.bottom = crop.top + cropHeight;
+ }
+
+ // The screenshot API does not apply the current screen rotation.
+ int rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
+
+ if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
+ rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
+ }
+
+ // Surfaceflinger is not aware of orientation, so convert our logical
+ // crop to surfaceflinger's portrait orientation.
+ convertCropForSurfaceFlinger(crop, rot, dw, dh);
+
+ if (DEBUG_SCREENSHOT) {
+ Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
+ + maxLayer + " appToken=" + appToken);
+ for (int i = 0; i < windows.size(); i++) {
+ WindowState win = windows.get(i);
+ Slog.i(TAG_WM, win + ": " + win.mLayer
+ + " animLayer=" + win.mWinAnimator.mAnimLayer
+ + " surfaceLayer=" + win.mWinAnimator.mSurfaceController.getLayer());
+ }
+ }
+
+ ScreenRotationAnimation screenRotationAnimation =
+ mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
+ final boolean inRotation = screenRotationAnimation != null &&
+ screenRotationAnimation.isAnimating();
+ if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM,
+ "Taking screenshot while rotating");
+
+ bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
+ inRotation, rot);
+ if (bm == null) {
+ Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh
+ + ") to layer " + maxLayer);
+ return null;
+ }
}
if (DEBUG_SCREENSHOT) {
@@ -7634,7 +7603,8 @@
mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
|| volumeDownState > 0;
try {
- if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) {
+ if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0
+ || SystemProperties.getInt(ShutdownThread.RO_SAFEMODE_PROPERTY, 0) != 0) {
int auditSafeMode = SystemProperties.getInt(ShutdownThread.AUDIT_SAFEMODE_PROPERTY, 0);
if (auditSafeMode == 0) {
@@ -7658,6 +7628,7 @@
if (mSafeMode) {
Log.i(TAG_WM, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
+ " dpad=" + dpadState + " trackball=" + trackballState + ")");
+ SystemProperties.set(ShutdownThread.RO_SAFEMODE_PROPERTY, "1");
} else {
Log.i(TAG_WM, "SAFE MODE not enabled");
}
@@ -7769,7 +7740,6 @@
public static final int RESIZE_TASK = 43;
public static final int TWO_FINGER_SCROLL_START = 44;
- public static final int SHOW_NON_RESIZEABLE_DOCK_TOAST = 45;
public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
@@ -8337,16 +8307,6 @@
}
}
break;
- case SHOW_NON_RESIZEABLE_DOCK_TOAST: {
- final Toast toast = Toast.makeText(
- 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;
- toast.setGravity(gravity, xOffset, yOffset);
- toast.show();
- }
- break;
case WINDOW_REPLACEMENT_TIMEOUT: {
final AppWindowToken token = (AppWindowToken) msg.obj;
synchronized (mWindowMap) {
@@ -9023,7 +8983,8 @@
|| winAnimator.mSurfaceResized
|| w.mOutsetsChanged
|| configChanged
- || dragResizingChanged) {
+ || dragResizingChanged
+ || w.mResizedWhileNotDragResizing) {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
Slog.v(TAG_WM, "Resize reasons for w=" + w + ": "
+ " contentInsetsChanged=" + w.mContentInsetsChanged
@@ -9057,7 +9018,8 @@
// the display until this window has been redrawn; to do that,
// we need to go through the process of getting informed by the
// application when it has finished drawing.
- if (w.mOrientationChanging || dragResizingChanged) {
+ if (w.mOrientationChanging || dragResizingChanged
+ || w.mResizedWhileNotDragResizing) {
if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || DEBUG_ORIENTATION || DEBUG_RESIZE) {
Slog.v(TAG_WM, "Orientation or resize start waiting for draw"
+ ", mDrawState=DRAW_PENDING in " + w
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 1eca4d4..c991130 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -468,6 +468,13 @@
*/
boolean mResizedWhileGone = false;
+ /**
+ * Indicates whether we got resized but drag resizing flag was false. In this case, we also
+ * need to recreate the surface and defer surface bound updates in order to make sure the
+ * buffer contents and the positioning/size stay in sync.
+ */
+ boolean mResizedWhileNotDragResizing;
+
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
int viewVisibility, final DisplayContent displayContent) {
@@ -635,13 +642,14 @@
* Subtracts the insets calculated by intersecting {@param layoutFrame} with {@param insetFrame}
* from {@param frame}. In other words, it applies the insets that would result if
* {@param frame} would be shifted to {@param layoutFrame} and then applying the insets from
- * {@param insetFrame}.
+ * {@param insetFrame}. Also it respects {@param displayFrame} in case window has minimum
+ * width/height applied and insets should be overridden.
*/
- private void subtractInsets(Rect frame, Rect layoutFrame, Rect insetFrame) {
- final int left = Math.max(0, insetFrame.left - layoutFrame.left);
- final int top = Math.max(0, insetFrame.top - layoutFrame.top);
- final int right = Math.max(0, layoutFrame.right - insetFrame.right);
- final int bottom = Math.max(0, layoutFrame.bottom - insetFrame.bottom);
+ private void subtractInsets(Rect frame, Rect layoutFrame, Rect insetFrame, Rect displayFrame) {
+ final int left = Math.max(0, insetFrame.left - Math.max(layoutFrame.left, displayFrame.left));
+ final int top = Math.max(0, insetFrame.top - Math.max(layoutFrame.top, displayFrame.top));
+ final int right = Math.max(0, Math.min(layoutFrame.right, displayFrame.right) - insetFrame.right);
+ final int bottom = Math.max(0, Math.min(layoutFrame.bottom, displayFrame.bottom) - insetFrame.bottom);
frame.inset(left, top, right, bottom);
}
@@ -680,8 +688,7 @@
// The offset from the layout containing frame to the actual containing frame.
final int layoutXDiff;
final int layoutYDiff;
- if (mInsetFrame.isEmpty() && (fullscreenTask
- || layoutInParentFrame())) {
+ if (mInsetFrame.isEmpty() && (fullscreenTask || layoutInParentFrame())) {
// We use the parent frame as the containing frame for fullscreen and child windows
mContainingFrame.set(pf);
mDisplayFrame.set(df);
@@ -726,9 +733,13 @@
layoutXDiff = !mInsetFrame.isEmpty() ? mInsetFrame.left - mContainingFrame.left : 0;
layoutYDiff = !mInsetFrame.isEmpty() ? mInsetFrame.top - mContainingFrame.top : 0;
layoutContainingFrame = !mInsetFrame.isEmpty() ? mInsetFrame : mContainingFrame;
- subtractInsets(mDisplayFrame, layoutContainingFrame, df);
- subtractInsets(mContainingFrame, layoutContainingFrame, pf);
- subtractInsets(mInsetFrame, layoutContainingFrame, pf);
+ mTmpRect.set(0, 0, mDisplayContent.getDisplayInfo().logicalWidth,
+ mDisplayContent.getDisplayInfo().logicalHeight);
+ subtractInsets(mDisplayFrame, layoutContainingFrame, df, mTmpRect);
+ if (!layoutInParentFrame()) {
+ subtractInsets(mContainingFrame, layoutContainingFrame, pf, mTmpRect);
+ subtractInsets(mInsetFrame, layoutContainingFrame, pf, mTmpRect);
+ }
layoutDisplayFrame = df;
layoutDisplayFrame.intersect(layoutContainingFrame);
}
@@ -846,8 +857,8 @@
getDisplayContent().getLogicalDisplayRect(mTmpRect);
// Override right and/or bottom insets in case if the frame doesn't fit the screen in
// non-fullscreen mode.
- boolean overrideRightInset = !fullscreenTask && mFrame.right > mTmpRect.right;
- boolean overrideBottomInset = !fullscreenTask && mFrame.bottom > mTmpRect.bottom;
+ boolean overrideRightInset = !fullscreenTask && layoutContainingFrame.right > mTmpRect.right;
+ boolean overrideBottomInset = !fullscreenTask && layoutContainingFrame.bottom > mTmpRect.bottom;
mContentInsets.set(mContentFrame.left - layoutContainingFrame.left,
mContentFrame.top - layoutContainingFrame.top,
overrideRightInset ? mTmpRect.right - mContentFrame.right
@@ -2346,6 +2357,10 @@
return mDragResizing;
}
+ boolean isDockedResizing() {
+ return mDragResizing && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER;
+ }
+
void dump(PrintWriter pw, String prefix, boolean dumpAll) {
final TaskStack stack = getStack();
pw.print(prefix); pw.print("mDisplayId="); pw.print(getDisplayId());
@@ -2577,7 +2592,7 @@
final int ph = containingFrame.height();
final Task task = getTask();
final boolean nonFullscreenTask = isInMultiWindowMode();
- final boolean fitToDisplay = task != null && !task.isFloating() && !layoutInParentFrame();
+ final boolean fitToDisplay = task != null && !nonFullscreenTask && !layoutInParentFrame();
float x, y;
int w,h;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 8fd8bc0..9c25f63 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1125,13 +1125,21 @@
final int top = w.mYOffset + w.mFrame.top;
// Initialize the decor rect to the entire frame.
- if (w.isDragResizing() && w.getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER) {
+ if (w.isDockedResizing() ||
+ (w.isChildWindow() && w.mAttachedWindow.isDockedResizing())) {
// If we are resizing with the divider, the task bounds might be smaller than the
// stack bounds. The system decor is used to clip to the task bounds, which we don't
// want in this case in order to avoid holes.
+ //
+ // We take care to not shrink the width, for surfaces which are larger than
+ // the display region. Of course this area will not eventually be visible
+ // but if we truncate the width now, we will calculate incorrectly
+ // when adjusting to the stack bounds.
final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo();
- mSystemDecorRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
+ mSystemDecorRect.set(0, 0,
+ Math.max(width, displayInfo.logicalWidth),
+ Math.max(height, displayInfo.logicalHeight));
} else {
mSystemDecorRect.set(0, 0, width, height);
}
@@ -1318,6 +1326,11 @@
final WindowState w = mWin;
final Task task = w.getTask();
+ // We got resized, so block all updates until we got the new surface.
+ if (w.mResizedWhileNotDragResizing) {
+ return;
+ }
+
mTmpSize.set(w.mShownPosition.x, w.mShownPosition.y, 0, 0);
calculateSurfaceBounds(w, w.getAttrs());
@@ -1478,11 +1491,6 @@
}
}
w.mToken.hasVisible = true;
-
- final Task task = w.getTask();
- if (task != null) {
- task.scheduleShowNonResizeableDockToastIfNeeded();
- }
}
}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index a5237ca..cd485c5 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -1312,6 +1312,12 @@
}
}
+static void nativeToggleCapsLock(JNIEnv* env, jclass /* clazz */,
+ jlong ptr, jint deviceId) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+ im->getInputManager()->getReader()->toggleCapsLockState(deviceId);
+}
+
static void nativeSetInputWindows(JNIEnv* env, jclass /* clazz */,
jlong ptr, jobjectArray windowHandleObjArray) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
@@ -1508,6 +1514,8 @@
(void*) nativeSetInputFilterEnabled },
{ "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIIII)I",
(void*) nativeInjectInputEvent },
+ { "nativeToggleCapsLock", "(JI)V",
+ (void*) nativeToggleCapsLock },
{ "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V",
(void*) nativeSetInputWindows },
{ "nativeSetFocusedApplication", "(JLcom/android/server/input/InputApplicationHandle;)V",
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index ae05042..78b0844 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1112,7 +1112,7 @@
JavaObject object(env, "android/location/GnssClock");
GpsClockFlags flags = clock->flags;
- SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
+ SET_IF(GPS_CLOCK_HAS_LEAP_SECOND,
LeapSecond,
static_cast<int32_t>(clock->leap_second));
@@ -1121,8 +1121,9 @@
// 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.)
+ // time_ns - full_bias_ns = local estimate of GPS time. Additionally, the
+ // sign of full_bias_ns and bias_ns has flipped between GpsClock &
+ // GnssClock, so that is also handled below.
switch (clock->type) {
case GPS_CLOCK_TYPE_UNKNOWN:
// Clock type unsupported.
@@ -1133,7 +1134,7 @@
break;
case GPS_CLOCK_TYPE_GPS_TIME:
// GPS time, need to convert.
- flags |= GNSS_CLOCK_HAS_FULL_BIAS;
+ flags |= GPS_CLOCK_HAS_FULL_BIAS;
clock->full_bias_ns = clock->time_ns;
clock->time_ns = 0;
SET(HardwareClockDiscontinuityCount,
@@ -1142,16 +1143,20 @@
}
SET(TimeNanos, clock->time_ns);
- SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
+ SET_IF(GPS_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,
+
+ // Definition of sign for full_bias_ns & bias_ns has been changed since N,
+ // so flip signs here.
+ SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, -(clock->full_bias_ns));
+ SET_IF(GPS_CLOCK_HAS_BIAS, BiasNanos, -(clock->bias_ns));
+
+ SET_IF(GPS_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,
+ SET_IF(GPS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
+ SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY,
DriftUncertaintyNanosPerSecond,
clock->drift_uncertainty_nsps);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 42b5705..d229633 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -21,8 +21,6 @@
import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
import static android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES;
-import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
-import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
@@ -57,7 +55,6 @@
import android.app.backup.IBackupManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -85,7 +82,6 @@
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
-import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Environment;
import android.os.FileUtils;
@@ -2065,10 +2061,9 @@
*/
private void sendAdminCommandToSelfAndProfilesLocked(String action, int reqPolicy,
int userHandle) {
- List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
- for (UserInfo ui : profiles) {
- int id = ui.id;
- sendAdminCommandLocked(action, reqPolicy, id);
+ int[] profileIds = mUserManager.getProfileIdsWithDisabled(userHandle);
+ for (int profileId : profileIds) {
+ sendAdminCommandLocked(action, reqPolicy, profileId);
}
}
@@ -3890,9 +3885,6 @@
// back in to the service.
final long ident = mInjector.binderClearCallingIdentity();
try {
- if (isManagedProfile(userHandle)) {
- mLockPatternUtils.setSeparateProfileChallengeEnabled(userHandle, true);
- }
if (!TextUtils.isEmpty(password)) {
mLockPatternUtils.saveLockPassword(password, null, quality, userHandle);
} else {
@@ -3971,9 +3963,9 @@
// moment so we set the screen off timeout regardless of whether it affects the parent user
// or the profile challenge only.
long timeMs = Long.MAX_VALUE;
- List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
- for (UserInfo userInfo : profiles) {
- DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
+ int[] profileIds = mUserManager.getProfileIdsWithDisabled(userHandle);
+ for (int profileId : profileIds) {
+ DevicePolicyData policy = getUserDataUnchecked(profileId);
final int N = policy.mAdminList.size();
for (int i = 0; i < N; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
@@ -3981,6 +3973,15 @@
&& timeMs > admin.maximumTimeToUnlock) {
timeMs = admin.maximumTimeToUnlock;
}
+ // If userInfo.id is a managed profile, we also need to look at
+ // the policies set on the parent.
+ if (admin.hasParentActiveAdmin()) {
+ final ActiveAdmin parentAdmin = admin.getParentActiveAdmin();
+ if (parentAdmin.maximumTimeToUnlock > 0
+ && timeMs > parentAdmin.maximumTimeToUnlock) {
+ timeMs = parentAdmin.maximumTimeToUnlock;
+ }
+ }
}
}
@@ -4014,30 +4015,57 @@
}
enforceFullCrossUsersPermission(userHandle);
synchronized (this) {
- long time = 0;
-
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent);
- return admin != null ? admin.maximumTimeToUnlock : time;
+ return admin != null ? admin.maximumTimeToUnlock : 0;
}
-
// Return the strictest policy across all participating admins.
List<ActiveAdmin> admins = getActiveAdminsForLockscreenPoliciesLocked(
userHandle, parent);
- final int N = admins.size();
- for (int i = 0; i < N; i++) {
- ActiveAdmin admin = admins.get(i);
- if (time == 0) {
- time = admin.maximumTimeToUnlock;
- } else if (admin.maximumTimeToUnlock != 0
- && time > admin.maximumTimeToUnlock) {
- time = admin.maximumTimeToUnlock;
+ return getMaximumTimeToLockPolicyFromAdmins(admins);
+ }
+ }
+
+ @Override
+ public long getMaximumTimeToLockForUserAndProfiles(int userHandle) {
+ if (!mHasFeature) {
+ return 0;
+ }
+ enforceFullCrossUsersPermission(userHandle);
+ synchronized (this) {
+ // All admins for this user.
+ ArrayList<ActiveAdmin> admins = new ArrayList<ActiveAdmin>();
+ for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
+ DevicePolicyData policy = getUserData(userInfo.id);
+ admins.addAll(policy.mAdminList);
+ // If it is a managed profile, it may have parent active admins
+ if (userInfo.isManagedProfile()) {
+ for (ActiveAdmin admin : policy.mAdminList) {
+ if (admin.hasParentActiveAdmin()) {
+ admins.add(admin.getParentActiveAdmin());
+ }
+ }
}
}
- return time;
+ return getMaximumTimeToLockPolicyFromAdmins(admins);
}
}
+ private long getMaximumTimeToLockPolicyFromAdmins(List<ActiveAdmin> admins) {
+ long time = 0;
+ final int N = admins.size();
+ for (int i = 0; i < N; i++) {
+ ActiveAdmin admin = admins.get(i);
+ if (time == 0) {
+ time = admin.maximumTimeToUnlock;
+ } else if (admin.maximumTimeToUnlock != 0
+ && time > admin.maximumTimeToUnlock) {
+ time = admin.maximumTimeToUnlock;
+ }
+ }
+ return time;
+ }
+
@Override
public void lockNow(boolean parent) {
if (!mHasFeature) {
@@ -6675,19 +6703,18 @@
// If we have multiple profiles we return the intersection of the
// permitted lists. This can happen in cases where we have a device
// and profile owner.
- List<UserInfo> profiles = mUserManager.getProfiles(userId);
- final int PROFILES_SIZE = profiles.size();
- for (int i = 0; i < PROFILES_SIZE; ++i) {
+ int[] profileIds = mUserManager.getProfileIdsWithDisabled(userId);
+ for (int profileId : profileIds) {
// Just loop though all admins, only device or profiles
// owners can have permitted lists set.
- DevicePolicyData policy = getUserDataUnchecked(profiles.get(i).id);
+ DevicePolicyData policy = getUserDataUnchecked(profileId);
final int N = policy.mAdminList.size();
for (int j = 0; j < N; j++) {
ActiveAdmin admin = policy.mAdminList.get(j);
List<String> fromAdmin = admin.permittedAccessiblityServices;
if (fromAdmin != null) {
if (result == null) {
- result = new ArrayList<String>(fromAdmin);
+ result = new ArrayList<>(fromAdmin);
} else {
result.retainAll(fromAdmin);
}
@@ -6855,12 +6882,11 @@
// If we have multiple profiles we return the intersection of the
// permitted lists. This can happen in cases where we have a device
// and profile owner.
- List<UserInfo> profiles = mUserManager.getProfiles(userId);
- final int PROFILES_SIZE = profiles.size();
- for (int i = 0; i < PROFILES_SIZE; ++i) {
+ int[] profileIds = mUserManager.getProfileIdsWithDisabled(userId);
+ for (int profileId : profileIds) {
// Just loop though all admins, only device or profiles
// owners can have permitted lists set.
- DevicePolicyData policy = getUserDataUnchecked(profiles.get(i).id);
+ DevicePolicyData policy = getUserDataUnchecked(profileId);
final int N = policy.mAdminList.size();
for (int j = 0; j < N; j++) {
ActiveAdmin admin = policy.mAdminList.get(j);
@@ -8045,7 +8071,8 @@
}
}
}
- return null;
+ // We're not specifying the device admin because there isn't one.
+ return intent;
}
}
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index f430a30..6722332 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -252,15 +252,22 @@
long mLastSeen;
// For debugging only. Offsets into the packet where PIOs are.
- private final ArrayList<Integer> mPrefixOptionOffsets;
+ private final ArrayList<Integer> mPrefixOptionOffsets = new ArrayList<>();
+
+ // For debugging only. Offsets into the packet where RDNSS options are.
+ private final ArrayList<Integer> mRdnssOptionOffsets = new ArrayList<>();
+
// For debugging only. How many times this RA was seen.
int seenCount = 0;
// For debugging only. Returns the hex representation of the last matching packet.
String getLastMatchingPacket() {
- return HexDump.toHexString(mPacket.array(), 0, mPacket.capacity(), false /* lowercase */);
+ return HexDump.toHexString(mPacket.array(), 0, mPacket.capacity(),
+ false /* lowercase */);
}
+ // For debugging only. Returns the string representation of the IPv6 address starting at
+ // position pos in the packet.
private String IPv6AddresstoString(int pos) {
try {
byte[] array = mPacket.array();
@@ -295,19 +302,37 @@
return s & 0xffffffff;
}
+ private void prefixOptionToString(StringBuffer sb, int offset) {
+ String prefix = IPv6AddresstoString(offset + 16);
+ int length = uint8(mPacket.get(offset + 2));
+ long valid = mPacket.getInt(offset + 4);
+ long preferred = mPacket.getInt(offset + 8);
+ sb.append(String.format("%s/%d %ds/%ds ", prefix, length, valid, preferred));
+ }
+
+ private void rdnssOptionToString(StringBuffer sb, int offset) {
+ int optLen = uint8(mPacket.get(offset + 1)) * 8;
+ if (optLen < 24) return; // Malformed or empty.
+ long lifetime = uint32(mPacket.getInt(offset + 4));
+ int numServers = (optLen - 8) / 16;
+ sb.append("DNS ").append(lifetime).append("s");
+ for (int server = 0; server < numServers; server++) {
+ sb.append(" ").append(IPv6AddresstoString(offset + 8 + 16 * server));
+ }
+ }
+
public String toString() {
try {
StringBuffer sb = new StringBuffer();
- sb.append(String.format("RA %s -> %s %d ",
+ sb.append(String.format("RA %s -> %s %ds ",
IPv6AddresstoString(IPV6_SRC_ADDR_OFFSET),
IPv6AddresstoString(IPV6_DEST_ADDR_OFFSET),
uint16(mPacket.getShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET))));
for (int i: mPrefixOptionOffsets) {
- String prefix = IPv6AddresstoString(i + 16);
- int length = uint8(mPacket.get(i + 2));
- long valid = mPacket.getInt(i + 4);
- long preferred = mPacket.getInt(i + 8);
- sb.append(String.format("%s/%d %d/%d ", prefix, length, valid, preferred));
+ prefixOptionToString(sb, i);
+ }
+ for (int i: mRdnssOptionOffsets) {
+ rdnssOptionToString(sb, i);
}
return sb.toString();
} catch (BufferUnderflowException | IndexOutOfBoundsException e) {
@@ -352,8 +377,7 @@
ICMP6_RA_ROUTER_LIFETIME_OFFSET,
ICMP6_RA_ROUTER_LIFETIME_LEN);
- // Parse ICMPv6 options
- mPrefixOptionOffsets = new ArrayList<>();
+ // Ensures that the RA is not truncated.
mPacket.position(ICMP6_RA_OPTION_OFFSET);
while (mPacket.hasRemaining()) {
int optionType = ((int)mPacket.get(mPacket.position())) & 0xff;
@@ -372,8 +396,10 @@
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:
+ mRdnssOptionOffsets.add(mPacket.position());
+ // Fall through.
+ case ICMP6_ROUTE_INFO_OPTION_TYPE:
case ICMP6_DNSSL_OPTION_TYPE:
// Parse lifetime
lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
@@ -520,6 +546,10 @@
@GuardedBy("this")
private byte[] mLastInstalledProgram;
+ // For debugging only. How many times the program was updated since we started.
+ @GuardedBy("this")
+ private int mNumProgramUpdates;
+
/**
* Generate filter code to process ARP packets. Execution of this code ends in either the
* DROP_LABEL or PASS_LABEL and does not fall off the end.
@@ -724,6 +754,8 @@
mLastTimeInstalledProgram = curTime();
mLastInstalledProgramMinLifetime = programMinLifetime;
mLastInstalledProgram = program;
+ mNumProgramUpdates++;
+
if (VDBG) {
hexDump("Installing filter: ", program, program.length);
}
@@ -865,19 +897,20 @@
}
public synchronized void dump(IndentingPrintWriter pw) {
- pw.println("APF caps: " + mApfCapabilities);
+ pw.println("Capabilities: " + mApfCapabilities);
pw.println("Receive thread: " + (mReceiveThread != null ? "RUNNING" : "STOPPED"));
- pw.println("Multicast filtering: " + mMulticastFilter);
+ pw.println("Multicast: " + (mMulticastFilter ? "DROP" : "ALLOW"));
try {
- pw.println("IPv4 address: " + InetAddress.getByAddress(mIPv4Address));
+ pw.println("IPv4 address: " + InetAddress.getByAddress(mIPv4Address).getHostAddress());
} catch (UnknownHostException|NullPointerException e) {}
+
if (mLastTimeInstalledProgram == 0) {
pw.println("No program installed.");
return;
}
-
+ pw.println("Program updates: " + mNumProgramUpdates);
pw.println(String.format(
- "Last program length %d, installed %ds ago, lifetime %d",
+ "Last program length %d, installed %ds ago, lifetime %ds",
mLastInstalledProgram.length, curTime() - mLastTimeInstalledProgram,
mLastInstalledProgramMinLifetime));
@@ -896,6 +929,7 @@
}
pw.decreaseIndent();
}
+ pw.decreaseIndent();
if (DBG) {
pw.println("Last program:");
@@ -903,7 +937,5 @@
pw.println(HexDump.toHexString(mLastInstalledProgram, false /* lowercase */));
pw.decreaseIndent();
}
-
- pw.decreaseIndent();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 8e11511..2f20a4b 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -59,6 +59,7 @@
import android.os.MessageQueue;
import android.os.Messenger;
import android.os.MessageQueue.IdleHandler;
+import android.os.Process;
import android.os.SystemClock;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
@@ -690,6 +691,7 @@
assertEquals(transportToLegacyType(transport), mCm.getActiveNetworkInfo().getType());
// Test getActiveNetwork()
assertNotNull(mCm.getActiveNetwork());
+ assertEquals(mCm.getActiveNetwork(), mCm.getActiveNetworkForUid(Process.myUid()));
switch (transport) {
case TRANSPORT_WIFI:
assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork());
@@ -713,6 +715,7 @@
assertNull(mCm.getActiveNetworkInfo());
// Test getActiveNetwork()
assertNull(mCm.getActiveNetwork());
+ assertNull(mCm.getActiveNetworkForUid(Process.myUid()));
// Test getAllNetworks()
assertEquals(0, mCm.getAllNetworks().length);
}
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 60d7382..f6e35f5 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -39,7 +39,6 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
-import android.os.storage.StorageManager;
import android.telephony.TelephonyManager;
import android.test.mock.MockContentResolver;
import android.test.mock.MockContext;
@@ -343,31 +342,25 @@
@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;
+ return getProfiles(userId);
}
}
);
+ when(userManager.getProfileIdsWithDisabled(anyInt())).thenAnswer(
+ new Answer<int[]>() {
+ @Override
+ public int[] answer(InvocationOnMock invocation) throws Throwable {
+ final int userId = (int) invocation.getArguments()[0];
+ List<UserInfo> profiles = getProfiles(userId);
+ int[] results = new int[profiles.size()];
+ for (int i = 0; i < results.length; i++) {
+ results[i] = profiles.get(i).id;
+ }
+ return results;
+ }
+ }
+ );
+
// Create a data directory.
final File dir = new File(dataDir, "user" + userId);
@@ -377,6 +370,31 @@
return dir;
}
+ private List<UserInfo> getProfiles(int userId) {
+ 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;
+ }
+
/**
* Add multiple users at once. They'll all have flag 0.
*/
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsCollectionTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsCollectionTest.java
index 6026644..9f53c87 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsCollectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsCollectionTest.java
@@ -162,7 +162,7 @@
final NetworkStats.Entry entry = new NetworkStats.Entry();
final NetworkIdentitySet identSet = new NetworkIdentitySet();
identSet.add(new NetworkIdentity(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- TEST_IMSI, null, false));
+ TEST_IMSI, null, false, true));
int myUid = Process.myUid();
int otherUidInSameUser = Process.myUid() + 1;
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java
index 82c6b6d..cff5876 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java
@@ -283,7 +283,7 @@
NetworkIdentitySet identSet = new NetworkIdentitySet();
identSet.add(new NetworkIdentity(
TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- IMSI_1, null /* networkId */, false /* roaming */));
+ IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
mActiveIfaces.put(TEST_IFACE, identSet);
// Baseline
@@ -315,7 +315,7 @@
NetworkIdentitySet identSet = new NetworkIdentitySet();
identSet.add(new NetworkIdentity(
TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- IMSI_1, null /* networkId */, false /* roaming */));
+ IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
mActiveIfaces.put(TEST_IFACE, identSet);
// Baseline
@@ -354,7 +354,7 @@
NetworkIdentitySet identSet = new NetworkIdentitySet();
identSet.add(new NetworkIdentity(
TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- IMSI_1, null /* networkId */, false /* roaming */));
+ IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
mActiveIfaces.put(TEST_IFACE, identSet);
// Baseline
@@ -393,13 +393,13 @@
NetworkIdentitySet identSet1 = new NetworkIdentitySet();
identSet1.add(new NetworkIdentity(
TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- IMSI_1, null /* networkId */, false /* roaming */));
+ IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
mActiveIfaces.put(TEST_IFACE, identSet1);
NetworkIdentitySet identSet2 = new NetworkIdentitySet();
identSet2.add(new NetworkIdentity(
TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- IMSI_2, null /* networkId */, false /* roaming */));
+ IMSI_2, null /* networkId */, false /* roaming */, true /* metered */));
mActiveIfaces.put(TEST_IFACE2, identSet2);
// Baseline
@@ -441,7 +441,7 @@
NetworkIdentitySet identSet = new NetworkIdentitySet();
identSet.add(new NetworkIdentity(
TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- IMSI_1, null /* networkId */, false /* roaming */));
+ IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
mActiveUidIfaces.put(TEST_IFACE, identSet);
// Baseline
@@ -481,7 +481,7 @@
NetworkIdentitySet identSet = new NetworkIdentitySet();
identSet.add(new NetworkIdentity(
TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- IMSI_1, null /* networkId */, false /* roaming */));
+ IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
mActiveUidIfaces.put(TEST_IFACE, identSet);
// Baseline
@@ -521,7 +521,7 @@
NetworkIdentitySet identSet = new NetworkIdentitySet();
identSet.add(new NetworkIdentity(
TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- IMSI_1, null /* networkId */, false /* roaming */));
+ IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
mActiveUidIfaces.put(TEST_IFACE, identSet);
// Baseline
@@ -561,7 +561,7 @@
NetworkIdentitySet identSet = new NetworkIdentitySet();
identSet.add(new NetworkIdentity(
TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- IMSI_1, null /* networkId */, false /* roaming */));
+ IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
mActiveUidIfaces.put(TEST_IFACE, identSet);
// Baseline
@@ -601,7 +601,7 @@
NetworkIdentitySet identSet = new NetworkIdentitySet();
identSet.add(new NetworkIdentity(
TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
- IMSI_1, null /* networkId */, false /* roaming */));
+ IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
mActiveUidIfaces.put(TEST_IFACE, identSet);
// Baseline
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
index baa5d36..b08bd72 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
@@ -172,6 +172,11 @@
public String getPackageName() {
return mInjectedClientPackage;
}
+
+ @Override
+ public int getUserId() {
+ return getCallingUserId();
+ }
}
/** Context used in the service side */
@@ -190,6 +195,11 @@
public void startActivityAsUser(@RequiresPermission Intent intent, @Nullable Bundle options,
UserHandle userId) {
}
+
+ @Override
+ public int getUserId() {
+ return UserHandle.USER_SYSTEM;
+ }
}
/** ShortcutService with injection override methods. */
@@ -1152,9 +1162,25 @@
return intentCaptor.getValue();
}
+ private Intent launchShortcutAndGetIntent_withShortcutInfo(
+ @NonNull String packageName, @NonNull String shortcutId, int userId) {
+ reset(mServiceContext);
+
+ assertTrue(mLauncherApps.startShortcut(
+ getShortcutInfoAsLauncher(packageName, shortcutId, userId), null, null));
+
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mServiceContext).startActivityAsUser(
+ intentCaptor.capture(),
+ any(Bundle.class),
+ eq(UserHandle.of(userId)));
+ return intentCaptor.getValue();
+ }
+
private void assertShortcutLaunchable(@NonNull String packageName, @NonNull String shortcutId,
int userId) {
assertNotNull(launchShortcutAndGetIntent(packageName, shortcutId, userId));
+ assertNotNull(launchShortcutAndGetIntent_withShortcutInfo(packageName, shortcutId, userId));
}
private void assertShortcutNotLaunchable(@NonNull String packageName,
@@ -1193,6 +1219,14 @@
return getLauncherShortcuts(launcher, userId, ShortcutQuery.FLAG_GET_PINNED);
}
+ private ShortcutInfo getShortcutInfoAsLauncher(String packageName, String shortcutId,
+ int userId) {
+ final List<ShortcutInfo> infoList =
+ mLauncherApps.getShortcutInfo(packageName, list(shortcutId),
+ UserHandle.of(userId));
+ assertEquals("No shortcutInfo found (or too many of them)", 1, infoList.size());
+ return infoList.get(0);
+ }
private Intent genPackageDeleteIntent(String pakcageName, int userId) {
Intent i = new Intent(Intent.ACTION_PACKAGE_REMOVED);
@@ -1728,6 +1762,16 @@
"res64x64",
"none");
+ // Different profile. Note the names and the contents don't match.
+ setCaller(CALLING_PACKAGE_1, USER_P0);
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcutWithIcon("res32x32", res512x512),
+ makeShortcutWithIcon("bmp32x32", bmp512x512)
+ )));
+ assertShortcutIds(assertAllNotHaveIcon(mManager.getDynamicShortcuts()),
+ "res32x32",
+ "bmp32x32");
+
// Re-initialize and load from the files.
mService.saveDirtyInfo();
initService();
@@ -1737,61 +1781,90 @@
setCaller(LAUNCHER_1);
// Check hasIconResource()/hasIconFile().
- assertShortcutIds(assertAllHaveIconResId(mLauncherApps.getShortcutInfo(
- CALLING_PACKAGE_1, list("res32x32"),
- getCallingUser())), "res32x32");
+ assertShortcutIds(assertAllHaveIconResId(
+ list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res32x32", USER_0))),
+ "res32x32");
- assertShortcutIds(assertAllHaveIconResId(mLauncherApps.getShortcutInfo(
- CALLING_PACKAGE_1, list("res64x64"), getCallingUser())),
+ assertShortcutIds(assertAllHaveIconResId(
+ list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res64x64", USER_0))),
"res64x64");
- assertShortcutIds(assertAllHaveIconFile(mLauncherApps.getShortcutInfo(
- CALLING_PACKAGE_1, list("bmp32x32"), getCallingUser())),
+ assertShortcutIds(assertAllHaveIconFile(
+ list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_0))),
"bmp32x32");
- assertShortcutIds(assertAllHaveIconFile(mLauncherApps.getShortcutInfo(
- CALLING_PACKAGE_1, list("bmp64x64"), getCallingUser())),
+ assertShortcutIds(assertAllHaveIconFile(
+ list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp64x64", USER_0))),
"bmp64x64");
- assertShortcutIds(assertAllHaveIconFile(mLauncherApps.getShortcutInfo(
- CALLING_PACKAGE_1, list("bmp512x512"), getCallingUser())),
+ assertShortcutIds(assertAllHaveIconFile(
+ list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp512x512", USER_0))),
"bmp512x512");
+ assertShortcutIds(assertAllHaveIconResId(
+ list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res32x32", USER_P0))),
+ "res32x32");
+ assertShortcutIds(assertAllHaveIconFile(
+ list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_P0))),
+ "bmp32x32");
+
// Check
assertEquals(
R.drawable.black_32x32,
mLauncherApps.getShortcutIconResId(
- makePackageShortcut(CALLING_PACKAGE_1, "res32x32"), getCallingUser()));
+ getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res32x32", USER_0)));
assertEquals(
R.drawable.black_64x64,
mLauncherApps.getShortcutIconResId(
-
- makePackageShortcut(CALLING_PACKAGE_1, "res64x64"), getCallingUser()));
+ getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res64x64", USER_0)));
assertEquals(
0, // because it's not a resource
mLauncherApps.getShortcutIconResId(
- makePackageShortcut(CALLING_PACKAGE_1, "bmp32x32"), getCallingUser()));
+ getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_0)));
assertEquals(
0, // because it's not a resource
mLauncherApps.getShortcutIconResId(
- makePackageShortcut(CALLING_PACKAGE_1, "bmp64x64"), getCallingUser()));
+ getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp64x64", USER_0)));
assertEquals(
0, // because it's not a resource
mLauncherApps.getShortcutIconResId(
- makePackageShortcut(CALLING_PACKAGE_1, "bmp512x512"), getCallingUser()));
+ getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp512x512", USER_0)));
bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
- makePackageShortcut(CALLING_PACKAGE_1, "bmp32x32"), getCallingUser()));
+ getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_0)));
assertBitmapSize(32, 32, bmp);
bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
- makePackageShortcut(CALLING_PACKAGE_1, "bmp64x64"), getCallingUser()));
+ getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp64x64", USER_0)));
assertBitmapSize(64, 64, bmp);
bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
- makePackageShortcut(CALLING_PACKAGE_1, "bmp512x512"), getCallingUser()));
+ getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp512x512", USER_0)));
+ assertBitmapSize(128, 128, bmp);
+
+ assertEquals(
+ R.drawable.black_512x512,
+ mLauncherApps.getShortcutIconResId(
+ getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res32x32", USER_P0)));
+ // Should be 512x512, so shrunk.
+ bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
+ getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_P0)));
+ assertBitmapSize(128, 128, bmp);
+
+ // Also check the overload APIs too.
+ assertEquals(
+ R.drawable.black_32x32,
+ mLauncherApps.getShortcutIconResId(CALLING_PACKAGE_1, "res32x32", HANDLE_USER_0));
+ assertEquals(
+ R.drawable.black_64x64,
+ mLauncherApps.getShortcutIconResId(CALLING_PACKAGE_1, "res64x64", HANDLE_USER_0));
+ assertEquals(
+ R.drawable.black_512x512,
+ mLauncherApps.getShortcutIconResId(CALLING_PACKAGE_1, "res32x32", HANDLE_USER_P0));
+ bmp = pfdToBitmap(
+ mLauncherApps.getShortcutIconFd(CALLING_PACKAGE_1, "bmp32x32", HANDLE_USER_P0));
assertBitmapSize(128, 128, bmp);
// TODO Test the content URI case too.
@@ -2034,9 +2107,16 @@
private static ShortcutQuery buildQuery(long changedSince,
String packageName, ComponentName componentName,
/* @ShortcutQuery.QueryFlags */ int flags) {
+ return buildQuery(changedSince, packageName, null, componentName, flags);
+ }
+
+ private static ShortcutQuery buildQuery(long changedSince,
+ String packageName, List<String> shortcutIds, ComponentName componentName,
+ /* @ShortcutQuery.QueryFlags */ int flags) {
final ShortcutQuery q = new ShortcutQuery();
q.setChangedSince(changedSince);
q.setPackage(packageName);
+ q.setShortcutIds(shortcutIds);
q.setActivity(componentName);
q.setQueryFlags(flags);
return q;
@@ -2110,6 +2190,36 @@
getCallingUser())),
"s2", "s3"))));
+ // With ID.
+ assertAllDynamic(assertAllNotHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
+ assertAllKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
+ /* time =*/ 1000, CALLING_PACKAGE_2, list("s3"),
+ /* activity =*/ null,
+ ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY),
+ getCallingUser())),
+ "s3"))));
+ assertAllDynamic(assertAllNotHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
+ assertAllKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
+ /* time =*/ 1000, CALLING_PACKAGE_2, list("s3", "s2", "ss"),
+ /* activity =*/ null,
+ ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY),
+ getCallingUser())),
+ "s2", "s3"))));
+ assertAllDynamic(assertAllNotHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
+ assertAllKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
+ /* time =*/ 1000, CALLING_PACKAGE_2, list("s3x", "s2x"),
+ /* activity =*/ null,
+ ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY),
+ getCallingUser()))
+ /* empty */))));
+ assertAllDynamic(assertAllNotHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
+ assertAllKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
+ /* time =*/ 1000, CALLING_PACKAGE_2, list(),
+ /* activity =*/ null,
+ ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY),
+ getCallingUser()))
+ /* empty */))));
+
// Pin some shortcuts.
mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
list("s3", "s4"), getCallingUser());
@@ -2132,6 +2242,13 @@
getCallingUser())),
"s1", "s3");
+ TestUtils.assertExpectException(
+ IllegalArgumentException.class, "package name must also be set", () -> {
+ mLauncherApps.getShortcuts(buildQuery(
+ /* time =*/ 0, /* package= */ null, list("id"),
+ /* activity =*/ null, /* flags */ 0), getCallingUser());
+ });
+
// TODO More tests: pinned but dynamic, filter by activity
}
@@ -5063,12 +5180,15 @@
}
public void testShortcutInfoParcel() {
- ShortcutInfo si = parceled(new ShortcutInfo.Builder(getTestContext())
+ setCaller(CALLING_PACKAGE_1, USER_10);
+ ShortcutInfo si = parceled(new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setTitle("title")
.setIntent(makeIntent("action", ShortcutActivity.class))
.build());
- assertEquals(getTestContext().getPackageName(), si.getPackageName());
+ assertEquals(mClientContext.getPackageName(), si.getPackageName());
+ assertEquals(USER_10, si.getUserId());
+ assertEquals(HANDLE_USER_10, si.getUserHandle());
assertEquals("id", si.getId());
assertEquals("title", si.getTitle());
assertEquals("action", si.getIntent().getAction());
@@ -5109,9 +5229,11 @@
}
public void testShortcutInfoClone() {
+ setCaller(CALLING_PACKAGE_1, USER_11);
+
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
- ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
+ ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setActivityComponent(new ComponentName("a", "b"))
.setIcon(Icon.createWithContentUri("content://a.b.c/"))
@@ -5127,7 +5249,9 @@
ShortcutInfo si = sorig.clone(/* clone flags*/ 0);
- assertEquals(getTestContext().getPackageName(), si.getPackageName());
+ assertEquals(USER_11, si.getUserId());
+ assertEquals(HANDLE_USER_11, si.getUserHandle());
+ assertEquals(mClientContext.getPackageName(), si.getPackageName());
assertEquals("id", si.getId());
assertEquals(new ComponentName("a", "b"), si.getActivityComponent());
assertEquals("content://a.b.c/", si.getIcon().getUriString());
@@ -5144,7 +5268,7 @@
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
- assertEquals(getTestContext().getPackageName(), si.getPackageName());
+ assertEquals(mClientContext.getPackageName(), si.getPackageName());
assertEquals("id", si.getId());
assertEquals(new ComponentName("a", "b"), si.getActivityComponent());
assertEquals(null, si.getIcon());
@@ -5161,7 +5285,7 @@
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
- assertEquals(getTestContext().getPackageName(), si.getPackageName());
+ assertEquals(mClientContext.getPackageName(), si.getPackageName());
assertEquals("id", si.getId());
assertEquals(new ComponentName("a", "b"), si.getActivityComponent());
assertEquals(null, si.getIcon());
@@ -5177,7 +5301,7 @@
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO);
- assertEquals(getTestContext().getPackageName(), si.getPackageName());
+ assertEquals(mClientContext.getPackageName(), si.getPackageName());
assertEquals("id", si.getId());
assertEquals(null, si.getActivityComponent());
assertEquals(null, si.getIcon());
@@ -5267,7 +5391,7 @@
}
public void testShortcutInfoSaveAndLoad() throws InterruptedException {
- setCaller(CALLING_PACKAGE_1, USER_0);
+ setCaller(CALLING_PACKAGE_1, USER_10);
final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
getTestContext().getResources(), R.drawable.black_32x32));
@@ -5293,11 +5417,13 @@
// Save and load.
mService.saveDirtyInfo();
initService();
- mService.handleUnlockUser(USER_0);
+ mService.handleUnlockUser(USER_10);
ShortcutInfo si;
- si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_0);
+ si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10);
+ assertEquals(USER_10, si.getUserId());
+ assertEquals(HANDLE_USER_10, si.getUserHandle());
assertEquals(CALLING_PACKAGE_1, si.getPackageName());
assertEquals("id", si.getId());
assertEquals(ShortcutActivity2.class.getName(), si.getActivityComponent().getClassName());
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index beec40f..0aeb96f 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -144,6 +144,7 @@
private long mLastAppIdleParoledTime;
private volatile boolean mPendingOneTimeCheckIdleStates;
+ private boolean mSystemServicesReady = false;
@GuardedBy("mLock")
private AppIdleHistory mAppIdleHistory;
@@ -232,6 +233,8 @@
if (mPendingOneTimeCheckIdleStates) {
postOneTimeCheckIdleStates();
}
+
+ mSystemServicesReady = true;
} else if (phase == PHASE_BOOT_COMPLETED) {
setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging());
}
@@ -810,28 +813,30 @@
// retain this for safety).
return false;
}
- try {
- // We allow all whitelisted apps, including those that don't want to be whitelisted
- // for idle mode, because app idle (aka app standby) is really not as big an issue
- // for controlling who participates vs. doze mode.
- if (mDeviceIdleController.isPowerSaveWhitelistExceptIdleApp(packageName)) {
+ if (mSystemServicesReady) {
+ try {
+ // We allow all whitelisted apps, including those that don't want to be whitelisted
+ // for idle mode, because app idle (aka app standby) is really not as big an issue
+ // for controlling who participates vs. doze mode.
+ if (mDeviceIdleController.isPowerSaveWhitelistExceptIdleApp(packageName)) {
+ return false;
+ }
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+
+ if (isActiveDeviceAdmin(packageName, userId)) {
return false;
}
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- if (isActiveDeviceAdmin(packageName, userId)) {
- return false;
- }
+ if (isActiveNetworkScorer(packageName)) {
+ return false;
+ }
- if (isActiveNetworkScorer(packageName)) {
- return false;
- }
-
- if (mAppWidgetManager != null
- && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) {
- return false;
+ if (mAppWidgetManager != null
+ && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) {
+ return false;
+ }
}
if (!isAppIdleUnfiltered(packageName, userId, elapsedRealtime)) {
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 40687b0..f13e019 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -41,6 +41,7 @@
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Slog;
+import com.android.internal.logging.MetricsLogger;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -56,7 +57,6 @@
* (ii) Generic sound-trigger models: Supports multiple of these.
*
* Currently this just acts as an abstraction over all SoundTrigger API calls.
- *
* @hide
*/
public class SoundTriggerHelper implements SoundTrigger.StatusListener {
@@ -84,25 +84,23 @@
private final PhoneStateListener mPhoneStateListener;
private final PowerManager mPowerManager;
- // TODO: Since the voice layer currently only handles one recognition
- // we simplify things by assuming one listener here too.
- private IRecognitionStatusCallback mKeyphraseListener;
-
// The SoundTriggerManager layer handles multiple generic recognition models. We store the
// ModelData here in a hashmap.
private final HashMap<UUID, ModelData> mGenericModelDataMap;
- // Note: KeyphraseId is not really used.
+ // This ModelData instance ensures that the keyphrase sound model is a singleton and
+ // all other sound models are of type Generic. Any keyphrase sound model will be stored here
+ // and any previously running instances will be replaced. This restriction was earlier
+ // implemented by three instance variables which stored data about the keyphrase
+ // model. That data now gets encapsulated in this ModelData instance.
+ private ModelData mKeyphraseModelData;
+
+ // The keyphrase ID for keyphrase sound models. We store this specially here since ModelData
+ // does not support this.
+ // TODO: The role of the keyphrase ID is a bit unclear. Its just used to ensure that
+ // recognition events have the correct keyphrase ID check.
private int mKeyphraseId = INVALID_VALUE;
- // Current voice sound model handle. We only allow one voice model to run at any given time.
- private int mCurrentKeyphraseModelHandle = INVALID_VALUE;
- private KeyphraseSoundModel mCurrentSoundModel = null;
- // FIXME: Ideally this should not be stored if allowMultipleTriggers happens at a lower layer.
- private RecognitionConfig mRecognitionConfig = null;
-
- // Whether we are requesting recognition to start.
- private boolean mRequested = false;
private boolean mCallActive = false;
private boolean mIsPowerSaveMode = false;
// Indicates if the native sound trigger service is disabled or not.
@@ -112,8 +110,6 @@
// Whether we have ANY recognition (keyphrase or generic) running.
private boolean mRecognitionRunning = false;
- // Keeps track of whether the keyphrase recognition is running.
- private boolean mKeyphraseStarted = false;
private boolean mRecognitionAborted = false;
private PowerSaveModeListener mPowerSaveModeListener;
@@ -136,26 +132,89 @@
}
/**
- * Starts recognition for the given generic sound model ID.
+ * Starts recognition for the given generic sound model ID. This is a wrapper around {@link
+ * startRecognition()}.
*
- * @param soundModel The sound model to use for recognition.
- * @param listener The listener for the recognition events related to the given keyphrase.
+ * @param modelId UUID of the sound model.
+ * @param soundModel The generic sound model to use for recognition.
+ * @param callback Callack for the recognition events related to the given keyphrase.
+ * @param recognitionConfig Instance of RecognitionConfig containing the parameters for the
+ * recognition.
* @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
*/
int startGenericRecognition(UUID modelId, GenericSoundModel soundModel,
IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig) {
- if (soundModel == null || callback == null || recognitionConfig == null) {
+ MetricsLogger.count(mContext, "sth_start_recognition", 1);
+ if (modelId == null || soundModel == null || callback == null ||
+ recognitionConfig == null) {
Slog.w(TAG, "Passed in bad data to startGenericRecognition().");
return STATUS_ERROR;
}
synchronized (mLock) {
+ ModelData modelData = getOrCreateGenericModelDataLocked(modelId);
+ return startRecognition(soundModel, modelData, callback, recognitionConfig,
+ INVALID_VALUE /* keyphraseId */);
+ }
+ }
+ /**
+ * Starts recognition for the given keyphraseId.
+ *
+ * @param keyphraseId The identifier of the keyphrase for which
+ * the recognition is to be started.
+ * @param soundModel The sound model to use for recognition.
+ * @param callback The callback for the recognition events related to the given keyphrase.
+ * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
+ */
+ int startKeyphraseRecognition(int keyphraseId, KeyphraseSoundModel soundModel,
+ IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig) {
+ synchronized (mLock) {
+ MetricsLogger.count(mContext, "sth_start_recognition", 1);
+ if (soundModel == null || callback == null || recognitionConfig == null) {
+ return STATUS_ERROR;
+ }
+
+ if (DBG) {
+ Slog.d(TAG, "startKeyphraseRecognition for keyphraseId=" + keyphraseId
+ + " soundModel=" + soundModel + ", callback=" + callback.asBinder()
+ + ", recognitionConfig=" + recognitionConfig);
+ Slog.d(TAG, "moduleProperties=" + mModuleProperties);
+ if (mKeyphraseModelData != null) {
+ Slog.d(TAG, mKeyphraseModelData.toString());
+ } else {
+ Slog.d(TAG, "Null KeyphraseModelData.");
+ }
+ }
+ if (mKeyphraseModelData == null) {
+ mKeyphraseModelData = ModelData.createKeyphraseModelData(soundModel.uuid);
+ }
+ return startRecognition(soundModel, mKeyphraseModelData, callback, recognitionConfig,
+ keyphraseId);
+ }
+ }
+
+ /**
+ * Starts recognition for the given sound model. A single routine for both keyphrase and
+ * generic sound models.
+ *
+ * @param soundModel The sound model to use for recognition.
+ * @param modelData Instance of {@link #ModelData} for the given model.
+ * @param callback Callback for the recognition events related to the given keyphrase.
+ * @param recognitionConfig Instance of {@link RecognitionConfig} containing the parameters
+ * @param keyphraseId Keyphrase ID for keyphrase models only. Pass in INVALID_VALUE for other
+ * models.
+ * for the recognition.
+ * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
+ */
+ int startRecognition(SoundModel soundModel, ModelData modelData,
+ IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig,
+ int keyphraseId) {
+ synchronized (mLock) {
if (mModuleProperties == null) {
Slog.w(TAG, "Attempting startRecognition without the capability");
return STATUS_ERROR;
}
-
if (mModule == null) {
mModule = SoundTrigger.attachModule(mModuleProperties.id, this, null);
if (mModule == null) {
@@ -169,13 +228,43 @@
initializeTelephonyAndPowerStateListeners();
}
- // Fetch a ModelData instance from the hash map. Creates a new one if none
- // exists.
- ModelData modelData = getOrCreateGenericModelDataLocked(modelId);
+ // If the previous model is different (for the same UUID), ensure that its unloaded
+ // and stopped before proceeding. This works for both keyphrase and generic models.
+ // Specifically for keyphrase since we have 'mKeyphraseModelData' holding a single
+ // allowed instance of such a model, this ensures that a previously loaded (or started)
+ // keyphrase model is appropriately stopped. This ensures no regression with the
+ // previous version of this code as given in the startKeyphrase() routine.
+ //
+ // For generic sound models, all this means is that if we are given a different sound
+ // model with the same UUID, then we will "replace" it.
+ if (modelData.getSoundModel() != null) {
+ boolean stopModel = false; // Stop the model after checking that its started.
+ boolean unloadModel = false;
+ if (modelData.getSoundModel().equals(soundModel) && modelData.isModelStarted()) {
+ // The model has not changed, but the previous model is "started".
+ // Stop the previously running model.
+ stopModel = true;
+ unloadModel = false; // No need to unload if the model hasn't changed.
+ } else if (!modelData.getSoundModel().equals(soundModel)) {
+ // We have a different model for this UUID. Stop and unload if needed. This
+ // helps maintain the singleton restriction for keyphrase sound models.
+ stopModel = modelData.isModelStarted();
+ unloadModel = modelData.isModelLoaded();
+ }
+ if (stopModel || unloadModel) {
+ int status = tryStopAndUnloadLocked(modelData, stopModel, unloadModel);
+ if (status != STATUS_OK) {
+ Slog.w(TAG, "Unable to stop or unload previous model: " +
+ modelData.toString());
+ return status;
+ }
+ }
+ }
IRecognitionStatusCallback oldCallback = modelData.getCallback();
- if (oldCallback != null) {
- Slog.w(TAG, "Canceling previous recognition for model id: " + modelId);
+ if (oldCallback != null && oldCallback.asBinder() != callback.asBinder()) {
+ Slog.w(TAG, "Canceling previous recognition for model id: " +
+ modelData.getModelId());
try {
oldCallback.onError(STATUS_ERROR);
} catch (RemoteException e) {
@@ -199,182 +288,49 @@
}
modelData.setHandle(handle[0]);
modelData.setLoaded();
- Slog.d(TAG, "Generic sound model loaded with handle:" + handle[0]);
+ Slog.d(TAG, "Sound model loaded with handle:" + handle[0]);
}
modelData.setCallback(callback);
+ if (modelData.isKeyphraseModel()) {
+ mKeyphraseId = keyphraseId;
+ }
+ modelData.setRequested(true);
modelData.setRecognitionConfig(recognitionConfig);
+ modelData.setSoundModel(soundModel);
- // Don't notify for synchronous calls.
- return startGenericRecognitionLocked(modelData, false);
+ return startRecognitionLocked(modelData,
+ false /* Don't notify for synchronous calls */);
}
}
/**
- * Starts recognition for the given keyphraseId.
- *
- * @param keyphraseId The identifier of the keyphrase for which
- * the recognition is to be started.
- * @param soundModel The sound model to use for recognition.
- * @param listener The listener for the recognition events related to the given keyphrase.
- * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
- */
- int startKeyphraseRecognition(int keyphraseId,
- KeyphraseSoundModel soundModel,
- IRecognitionStatusCallback listener,
- RecognitionConfig recognitionConfig) {
- if (soundModel == null || listener == null || recognitionConfig == null) {
- return STATUS_ERROR;
- }
-
- synchronized (mLock) {
- if (DBG) {
- Slog.d(TAG, "startKeyphraseRecognition for keyphraseId=" + keyphraseId
- + " soundModel=" + soundModel + ", listener=" + listener.asBinder()
- + ", recognitionConfig=" + recognitionConfig);
- Slog.d(TAG, "moduleProperties=" + mModuleProperties);
- Slog.d(TAG, "current listener="
- + (mKeyphraseListener == null ? "null" : mKeyphraseListener.asBinder()));
- Slog.d(TAG, "current SoundModel handle=" + mCurrentKeyphraseModelHandle);
- Slog.d(TAG, "current SoundModel UUID="
- + (mCurrentSoundModel == null ? null : mCurrentSoundModel.uuid));
- }
-
- if (!mRecognitionRunning) {
- initializeTelephonyAndPowerStateListeners();
- }
-
- if (mModuleProperties == null) {
- 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, "startKeyphraseRecognition cannot attach to sound trigger module");
- return STATUS_ERROR;
- }
- }
-
- // Unload the previous model if the current one isn't invalid
- // and, it's not the same as the new one.
- // This helps use cache and reuse the model and just start/stop it when necessary.
- if (mCurrentKeyphraseModelHandle != INVALID_VALUE
- && !soundModel.equals(mCurrentSoundModel)) {
- Slog.w(TAG, "Unloading previous sound model");
- int status = mModule.unloadSoundModel(mCurrentKeyphraseModelHandle);
- if (status != SoundTrigger.STATUS_OK) {
- Slog.w(TAG, "unloadSoundModel call failed with " + status);
- }
- internalClearKeyphraseSoundModelLocked();
- mKeyphraseStarted = false;
- }
-
- // If the previous recognition was by a different listener,
- // Notify them that it was stopped.
- if (mKeyphraseListener != null && mKeyphraseListener.asBinder() != listener.asBinder()) {
- Slog.w(TAG, "Canceling previous recognition");
- try {
- mKeyphraseListener.onError(STATUS_ERROR);
- } catch (RemoteException e) {
- Slog.w(TAG, "RemoteException in onDetectionStopped", e);
- }
- mKeyphraseListener = null;
- }
-
- // Load the sound model if the current one is null.
- int soundModelHandle = mCurrentKeyphraseModelHandle;
- if (mCurrentKeyphraseModelHandle == INVALID_VALUE
- || mCurrentSoundModel == null) {
- int[] handle = new int[] { INVALID_VALUE };
- int status = mModule.loadSoundModel(soundModel, handle);
- if (status != SoundTrigger.STATUS_OK) {
- Slog.w(TAG, "loadSoundModel call failed with " + status);
- return status;
- }
- if (handle[0] == INVALID_VALUE) {
- Slog.w(TAG, "loadSoundModel call returned invalid sound model handle");
- return STATUS_ERROR;
- }
- soundModelHandle = handle[0];
- } else {
- if (DBG) Slog.d(TAG, "Reusing previously loaded sound model");
- }
-
- // Start the recognition.
- mRequested = true;
- mKeyphraseId = keyphraseId;
- mCurrentKeyphraseModelHandle = soundModelHandle;
- mCurrentSoundModel = soundModel;
- mRecognitionConfig = recognitionConfig;
- // Register the new listener. This replaces the old one.
- // There can only be a maximum of one active listener at any given time.
- mKeyphraseListener = listener;
-
- return updateRecognitionLocked(false /* don't notify for synchronous calls */);
- }
- }
-
- /**
- * Stops recognition for the given generic sound model.
+ * Stops recognition for the given generic sound model. This is a wrapper for {@link
+ * #stopRecognition}.
*
* @param modelId The identifier of the generic sound model for which
* the recognition is to be stopped.
- * @param listener The listener for the recognition events related to the given sound model.
+ * @param callback The callback for the recognition events related to the given sound model.
*
* @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
*/
- int stopGenericRecognition(UUID modelId, IRecognitionStatusCallback listener) {
- if (listener == null) {
- return STATUS_ERROR;
- }
-
+ int stopGenericRecognition(UUID modelId, IRecognitionStatusCallback callback) {
synchronized (mLock) {
+ MetricsLogger.count(mContext, "sth_stop_recognition", 1);
+ if (callback == null || modelId == null) {
+ Slog.e(TAG, "Null callbackreceived for stopGenericRecognition() for modelid:" +
+ modelId);
+ return STATUS_ERROR;
+ }
+
ModelData modelData = mGenericModelDataMap.get(modelId);
if (modelData == null) {
Slog.w(TAG, "Attempting stopRecognition on invalid model with id:" + modelId);
return STATUS_ERROR;
}
- IRecognitionStatusCallback currentCallback = modelData.getCallback();
- if (DBG) {
- Slog.d(TAG, "stopRecognition for modelId=" + modelId
- + ", listener=" + listener.asBinder());
- Slog.d(TAG, "current callback ="
- + (currentCallback == null ? "null" : currentCallback.asBinder()));
- }
-
- if (mModuleProperties == null || mModule == null) {
- Slog.w(TAG, "Attempting stopRecognition without the capability");
- return STATUS_ERROR;
- }
-
- 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 stopGenericRecognition for another recognition");
- return STATUS_ERROR;
- }
-
- int status = stopGenericRecognitionLocked(modelData,
- false /* don't notify for synchronous calls */);
+ int status = stopRecognition(modelData, callback);
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.setLoaded();
- modelData.clearCallback();
- if (!computeRecognitionRunningLocked()) {
- internalClearGlobalStateLocked();
}
return status;
}
@@ -382,47 +338,30 @@
/**
* Stops recognition for the given {@link Keyphrase} if a recognition is
- * currently active.
+ * currently active. This is a wrapper for {@link #stopRecognition()}.
*
* @param keyphraseId The identifier of the keyphrase for which
* the recognition is to be stopped.
- * @param listener The listener for the recognition events related to the given keyphrase.
+ * @param callback The callback for the recognition events related to the given keyphrase.
*
* @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
*/
- int stopKeyphraseRecognition(int keyphraseId, IRecognitionStatusCallback listener) {
- if (listener == null) {
- return STATUS_ERROR;
- }
-
+ int stopKeyphraseRecognition(int keyphraseId, IRecognitionStatusCallback callback) {
synchronized (mLock) {
+ MetricsLogger.count(mContext, "sth_stop_recognition", 1);
+ if (callback == null) {
+ Slog.e(TAG, "Null callback received for stopKeyphraseRecognition() for keyphraseId:" +
+ keyphraseId);
+ return STATUS_ERROR;
+ }
+
if (DBG) {
- Slog.d(TAG, "stopRecognition for keyphraseId=" + keyphraseId
- + ", listener=" + listener.asBinder());
- Slog.d(TAG, "current listener="
- + (mKeyphraseListener == null ? "null" : mKeyphraseListener.asBinder()));
+ Slog.d(TAG, "stopRecognition for keyphraseId=" + keyphraseId + ", callback =" +
+ callback.asBinder());
+ Slog.d(TAG, "current callback=" + (mKeyphraseModelData == null ? "null" :
+ mKeyphraseModelData.getCallback().asBinder()));
}
-
- if (mModuleProperties == null || mModule == null) {
- Slog.w(TAG, "Attempting stopRecognition without the capability");
- return STATUS_ERROR;
- }
-
- if (mKeyphraseListener == null) {
- // startRecognition hasn't been called or it failed.
- Slog.w(TAG, "Attempting stopRecognition without a successful startRecognition");
- return STATUS_ERROR;
- }
- if (mKeyphraseListener.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");
- return STATUS_ERROR;
- }
-
- // Stop recognition if it's the current one, ignore otherwise.
- mRequested = false;
- int status = updateRecognitionLocked(false /* don't notify for synchronous calls */);
+ int status = stopRecognition(mKeyphraseModelData, callback);
if (status != SoundTrigger.STATUS_OK) {
return status;
}
@@ -431,25 +370,115 @@
// back.
// Also clear the internal state once the recognition has been stopped.
internalClearKeyphraseStateLocked();
- internalClearGlobalStateLocked();
return status;
}
}
/**
+ * Stops recognition for the given ModelData instance.
+ *
+ * @param modelData Instance of {@link #ModelData} sound model.
+ * @param callback The callback for the recognition events related to the given keyphrase.
+ * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
+ */
+ private int stopRecognition(ModelData modelData, IRecognitionStatusCallback callback) {
+ synchronized (mLock) {
+ if (callback == null) {
+ return STATUS_ERROR;
+ }
+ if (mModuleProperties == null || mModule == null) {
+ Slog.w(TAG, "Attempting stopRecognition without the capability");
+ return STATUS_ERROR;
+ }
+
+ IRecognitionStatusCallback currentCallback = modelData.getCallback();
+ if (modelData == null || 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() != callback.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");
+ return STATUS_ERROR;
+ }
+
+ // Request stop recognition via the update() method.
+ modelData.setRequested(false);
+ int status = updateRecognitionLocked(modelData, isRecognitionAllowed(),
+ false /* don't notify for synchronous calls */);
+ if (status != SoundTrigger.STATUS_OK) {
+ 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.setLoaded();
+ modelData.clearCallback();
+ modelData.setRecognitionConfig(null);
+
+ if (!computeRecognitionRunningLocked()) {
+ internalClearGlobalStateLocked();
+ }
+
+ if (modelData.isKeyphraseModel()) {
+ mKeyphraseId = INVALID_VALUE;
+ }
+ return status;
+ }
+ }
+
+ // Stop a previously started model if it was started. Optionally, unload if the previous model
+ // is stale and is about to be replaced.
+ // Needs to be called with the mLock held.
+ private int tryStopAndUnloadLocked(ModelData modelData, boolean stopModel,
+ boolean unloadModel) {
+ int status = STATUS_OK;
+ if (modelData.isModelNotLoaded()) {
+ return status;
+ }
+ if (stopModel && modelData.isModelStarted()) {
+ status = stopRecognitionLocked(modelData,
+ false /* don't notify for synchronous calls */);
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "stopRecognition failed: " + status);
+ return status;
+ }
+ }
+
+ if (unloadModel && modelData.isModelLoaded()) {
+ Slog.d(TAG, "Unloading previously loaded stale model.");
+ status = mModule.unloadSoundModel(modelData.getHandle());
+ MetricsLogger.count(mContext, "sth_unloading_stale_model", 1);
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "unloadSoundModel call failed with " + status);
+ } else {
+ // Clear the ModelData state if successful.
+ modelData.clearState();
+ modelData.clearCallback();
+ modelData.setRecognitionConfig(null);
+ }
+ }
+ return status;
+ }
+
+ /**
* Stops all recognitions active currently and clears the internal state.
*/
void stopAllRecognitions() {
synchronized (mLock) {
+ MetricsLogger.count(mContext, "sth_stop_all_recognitions", 1);
if (mModuleProperties == null || mModule == null) {
return;
}
// Stop Keyphrase recognition if one exists.
- if (mCurrentKeyphraseModelHandle != INVALID_VALUE) {
-
- mRequested = false;
- int status = updateRecognitionLocked(
+ if (mKeyphraseModelData != null && mKeyphraseModelData.getHandle() != INVALID_VALUE) {
+ mKeyphraseModelData.setRequested(false);
+ int status = updateRecognitionLocked(mKeyphraseModelData, isRecognitionAllowed(),
false /* don't notify for synchronous calls */);
internalClearKeyphraseStateLocked();
}
@@ -457,7 +486,7 @@
// Stop all generic recognition models.
for (ModelData model : mGenericModelDataMap.values()) {
if (model.isModelStarted()) {
- int status = stopGenericRecognitionLocked(model,
+ int status = stopRecognitionLocked(model,
false /* do not notify for synchronous calls */);
if (status != STATUS_OK) {
// What else can we do if there is an error here.
@@ -476,39 +505,40 @@
}
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) {
+ MetricsLogger.count(mContext, "sth_unload_keyphrase_sound_model", 1);
+ if (mModule == null || mKeyphraseModelData == null ||
+ mKeyphraseModelData.getHandle() == INVALID_VALUE) {
+ return STATUS_ERROR;
+ }
+
// Stop recognition if it's the current one.
- mRequested = false;
- int status = updateRecognitionLocked(false /* don't notify */);
+ mKeyphraseModelData.setRequested(false);
+ int status = updateRecognitionLocked(mKeyphraseModelData, isRecognitionAllowed(),
+ false /* don't notify */);
if (status != SoundTrigger.STATUS_OK) {
Slog.w(TAG, "Stop recognition failed for keyphrase ID:" + status);
}
- status = mModule.unloadSoundModel(mCurrentKeyphraseModelHandle);
+ status = mModule.unloadSoundModel(mKeyphraseModelData.getHandle());
if (status != SoundTrigger.STATUS_OK) {
Slog.w(TAG, "unloadKeyphraseSoundModel call failed with " + status);
}
- internalClearKeyphraseSoundModelLocked();
+ mKeyphraseModelData.clearState();
return status;
}
}
int unloadGenericSoundModel(UUID modelId) {
- if (modelId == null || mModule == null) {
- return STATUS_ERROR;
- }
synchronized (mLock) {
+ MetricsLogger.count(mContext, "sth_unload_generic_sound_model", 1);
+ 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);
+ Slog.w(TAG, "Unload error: Attempting unload invalid generic model with id:" +
+ modelId);
return STATUS_ERROR;
}
if (!modelData.isModelLoaded()) {
@@ -517,7 +547,7 @@
return STATUS_OK;
}
if (modelData.isModelStarted()) {
- int status = stopGenericRecognitionLocked(modelData,
+ int status = stopRecognitionLocked(modelData,
false /* don't notify for synchronous calls */);
if (status != SoundTrigger.STATUS_OK) {
Slog.w(TAG, "stopGenericRecognition failed: " + status);
@@ -577,6 +607,7 @@
}
private void onGenericRecognitionSuccessLocked(GenericRecognitionEvent event) {
+ MetricsLogger.count(mContext, "sth_generic_recognition_event", 1);
if (event.status != SoundTrigger.RECOGNITION_STATUS_SUCCESS) {
return;
}
@@ -608,9 +639,11 @@
return;
}
+ model.setRequested(config.allowMultipleTriggers);
// TODO: Remove this block if the lower layer supports multiple triggers.
- if (config.allowMultipleTriggers) {
- startGenericRecognitionLocked(model, true /* notify */);
+ if (model.getRequested()) {
+ updateRecognitionLocked(model, isRecognitionAllowed() /* isAllowed */,
+ true /* notify */);
}
}
@@ -622,6 +655,7 @@
}
if (DBG) Slog.d(TAG, "onSoundModelUpdate: " + event);
synchronized (mLock) {
+ MetricsLogger.count(mContext, "sth_sound_model_updated", 1);
onSoundModelUpdatedLocked(event);
}
}
@@ -637,6 +671,7 @@
@Override
public void onServiceDied() {
Slog.e(TAG, "onServiceDied!!");
+ MetricsLogger.count(mContext, "sth_service_died", 1);
synchronized (mLock) {
onServiceDiedLocked();
}
@@ -649,7 +684,7 @@
return;
}
mCallActive = callActive;
- updateRecognitionLocked(true /* notify */);
+ updateAllRecognitionsLocked(true /* notify */);
}
private void onPowerSaveModeChangedLocked(boolean isPowerSaveMode) {
@@ -657,7 +692,7 @@
return;
}
mIsPowerSaveMode = isPowerSaveMode;
- updateRecognitionLocked(true /* notify */);
+ updateAllRecognitionsLocked(true /* notify */);
}
private void onSoundModelUpdatedLocked(SoundModelEvent event) {
@@ -669,11 +704,12 @@
return;
}
mServiceDisabled = disabled;
- updateRecognitionLocked(true /* notify */);
+ updateAllRecognitionsLocked(true /* notify */);
}
private void onRecognitionAbortLocked() {
Slog.w(TAG, "Recognition aborted");
+ MetricsLogger.count(mContext, "sth_recognition_aborted", 1);
// If abort has been called, the hardware has already stopped recognition, so we shouldn't
// call it again when we process the state change.
mRecognitionAborted = true;
@@ -681,23 +717,29 @@
private void onRecognitionFailureLocked() {
Slog.w(TAG, "Recognition failure");
+ MetricsLogger.count(mContext, "sth_recognition_failure_event", 1);
try {
- if (mKeyphraseListener != null) {
- mKeyphraseListener.onError(STATUS_ERROR);
- }
+ sendErrorCallbacksToAll(STATUS_ERROR);
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onError", e);
} finally {
internalClearKeyphraseStateLocked();
+ internalClearGenericModelStateLocked();
internalClearGlobalStateLocked();
}
}
private void onKeyphraseRecognitionSuccessLocked(KeyphraseRecognitionEvent event) {
Slog.i(TAG, "Recognition success");
+ MetricsLogger.count(mContext, "sth_keyphrase_recognition_event", 1);
- if (mKeyphraseListener == null) {
- Slog.w(TAG, "received onRecognition event without any listener for it");
+ if (mKeyphraseModelData == null) {
+ Slog.e(TAG, "Received onRecognition event for null keyphrase model data.");
+ return;
+ }
+
+ if (mKeyphraseModelData.getCallback() == null) {
+ Slog.w(TAG, "Received onRecognition event without any listener for it.");
return;
}
@@ -714,30 +756,62 @@
}
try {
- if (mKeyphraseListener != null) {
- mKeyphraseListener.onKeyphraseDetected((KeyphraseRecognitionEvent) event);
- }
+ mKeyphraseModelData.getCallback().onKeyphraseDetected(
+ (KeyphraseRecognitionEvent) event);
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onKeyphraseDetected", e);
}
- mKeyphraseStarted = false;
- mRequested = mRecognitionConfig.allowMultipleTriggers;
+ mKeyphraseModelData.setStopped();
+
+ RecognitionConfig config = mKeyphraseModelData.getRecognitionConfig();
+ if (config != null) {
+ // Whether we should continue by starting this again.
+ mKeyphraseModelData.setRequested(config.allowMultipleTriggers);
+ }
// TODO: Remove this block if the lower layer supports multiple triggers.
- if (mRequested) {
- updateRecognitionLocked(true /* notify */);
+ if (mKeyphraseModelData.getRequested()) {
+ updateRecognitionLocked(mKeyphraseModelData, isRecognitionAllowed(),
+ true /* notify */);
+ }
+ }
+
+ private void updateAllRecognitionsLocked(boolean notify) {
+ boolean isAllowed = isRecognitionAllowed();
+ // Keyphrase model.
+ if (mKeyphraseModelData != null) {
+ updateRecognitionLocked(mKeyphraseModelData, isAllowed, notify);
+ }
+ for (UUID modelId : mGenericModelDataMap.keySet()) {
+ ModelData modelData = mGenericModelDataMap.get(modelId);
+ updateRecognitionLocked(modelData, isAllowed, notify);
+ }
+ }
+
+ private int updateRecognitionLocked(ModelData model, boolean isAllowed,
+ boolean notify) {
+ boolean start = model.getRequested() && isAllowed;
+ if (start == model.isModelStarted()) {
+ // No-op.
+ return STATUS_OK;
+ }
+ if (start) {
+ return startRecognitionLocked(model, notify);
+ } else {
+ return stopRecognitionLocked(model, notify);
}
}
private void onServiceDiedLocked() {
try {
- if (mKeyphraseListener != null) {
- mKeyphraseListener.onError(SoundTrigger.STATUS_DEAD_OBJECT);
- }
+ MetricsLogger.count(mContext, "sth_service_died", 1);
+ sendErrorCallbacksToAll(SoundTrigger.STATUS_DEAD_OBJECT);
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onError", e);
} finally {
- internalClearKeyphraseSoundModelLocked();
+ if (mKeyphraseModelData != null) {
+ mKeyphraseModelData.clearState();
+ }
internalClearKeyphraseStateLocked();
internalClearGenericModelStateLocked();
internalClearGlobalStateLocked();
@@ -748,78 +822,6 @@
}
}
- private int updateRecognitionLocked(boolean notify) {
- if (mModule == null || mModuleProperties == null
- || mCurrentKeyphraseModelHandle == INVALID_VALUE || mKeyphraseListener == null) {
- // Nothing to do here.
- return STATUS_OK;
- }
-
- boolean start = mRequested && !mCallActive && !mServiceDisabled && !mIsPowerSaveMode;
- if (start == mKeyphraseStarted) {
- // No-op.
- return STATUS_OK;
- }
-
- // See if the recognition needs to be started.
- if (start) {
- // Start recognition.
- int status = mModule.startRecognition(mCurrentKeyphraseModelHandle,
- mRecognitionConfig);
- if (status != SoundTrigger.STATUS_OK) {
- Slog.w(TAG, "startKeyphraseRecognition failed with " + status);
- // Notify of error if needed.
- if (notify) {
- try {
- mKeyphraseListener.onError(status);
- } catch (RemoteException e) {
- Slog.w(TAG, "RemoteException in onError", e);
- }
- }
- } else {
- mKeyphraseStarted = true;
- // Notify of resume if needed.
- if (notify) {
- try {
- mKeyphraseListener.onRecognitionResumed();
- } catch (RemoteException e) {
- Slog.w(TAG, "RemoteException in onRecognitionResumed", e);
- }
- }
- }
- return status;
- } else {
- // Stop recognition (only if we haven't been aborted).
- int status = STATUS_OK;
- if (!mRecognitionAborted) {
- status = mModule.stopRecognition(mCurrentKeyphraseModelHandle);
- } else {
- mRecognitionAborted = false;
- }
- if (status != SoundTrigger.STATUS_OK) {
- Slog.w(TAG, "stopRecognition call failed with " + status);
- if (notify) {
- try {
- mKeyphraseListener.onError(status);
- } catch (RemoteException e) {
- Slog.w(TAG, "RemoteException in onError", e);
- }
- }
- } else {
- mKeyphraseStarted = false;
- // Notify of pause if needed.
- if (notify) {
- try {
- mKeyphraseListener.onRecognitionPaused();
- } catch (RemoteException e) {
- Slog.w(TAG, "RemoteException in onRecognitionPaused", e);
- }
- }
- }
- return status;
- }
- }
-
// internalClearGlobalStateLocked() gets split into two routines. Cleanup that is
// specific to keyphrase sound models named as internalClearKeyphraseStateLocked() and
// internalClearGlobalStateLocked() for global state. The global cleanup routine will be used
@@ -836,12 +838,14 @@
}
private void internalClearKeyphraseStateLocked() {
- mKeyphraseStarted = false;
- mRequested = false;
+ if (mKeyphraseModelData != null) {
+ mKeyphraseModelData.setStopped();
+ mKeyphraseModelData.setRequested(false);
+ mKeyphraseModelData.setRecognitionConfig(null);
+ mKeyphraseModelData.setCallback(null);
+ }
mKeyphraseId = INVALID_VALUE;
- mRecognitionConfig = null;
- mKeyphraseListener = null;
}
private void internalClearGenericModelStateLocked() {
@@ -852,13 +856,6 @@
}
}
- // This routine is a replacement for internalClearSoundModelLocked(). However, we
- // should see why this should be different from internalClearKeyphraseStateLocked().
- private void internalClearKeyphraseSoundModelLocked() {
- mCurrentKeyphraseModelHandle = INVALID_VALUE;
- mCurrentSoundModel = null;
- }
-
class MyCallStateListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String arg1) {
@@ -888,17 +885,13 @@
pw.print(" module properties=");
pw.println(mModuleProperties == null ? "null" : mModuleProperties);
pw.print(" keyphrase ID="); pw.println(mKeyphraseId);
- pw.print(" sound model handle="); pw.println(mCurrentKeyphraseModelHandle);
- pw.print(" sound model UUID=");
- pw.println(mCurrentSoundModel == null ? "null" : mCurrentSoundModel.uuid);
- pw.print(" current listener=");
- pw.println(mKeyphraseListener == null ? "null" : mKeyphraseListener.asBinder());
- pw.print(" requested="); pw.println(mRequested);
- pw.print(" started="); pw.println(mKeyphraseStarted);
pw.print(" call active="); pw.println(mCallActive);
pw.print(" power save mode active="); pw.println(mIsPowerSaveMode);
pw.print(" service disabled="); pw.println(mServiceDisabled);
+ if (mKeyphraseModelData != null) {
+ pw.println(mKeyphraseModelData.toString());
+ }
}
}
@@ -919,11 +912,25 @@
mIsPowerSaveMode = mPowerManager.isPowerSaveMode();
}
+ // Sends an error callback to all models with a valid registered callback.
+ private void sendErrorCallbacksToAll(int errorCode) throws RemoteException {
+ IRecognitionStatusCallback keyphraseListener = mKeyphraseModelData.getCallback();
+ if (keyphraseListener != null) {
+ keyphraseListener.onError(STATUS_ERROR);
+ }
+ for (UUID modelId: mGenericModelDataMap.keySet()) {
+ ModelData modelData = mGenericModelDataMap.get(modelId);
+ IRecognitionStatusCallback keyphraseCallback = mKeyphraseModelData.getCallback();
+ if (keyphraseCallback != null) {
+ keyphraseCallback.onError(STATUS_ERROR);
+ }
+ }
+ }
+
private ModelData getOrCreateGenericModelDataLocked(UUID modelId) {
ModelData modelData = mGenericModelDataMap.get(modelId);
if (modelData == null) {
- modelData = new ModelData(modelId);
- modelData.setTypeGeneric();
+ modelData = ModelData.createGenericModelData(modelId);
mGenericModelDataMap.put(modelId, modelData);
}
return modelData;
@@ -949,25 +956,30 @@
return !mCallActive && !mServiceDisabled && !mIsPowerSaveMode;
}
- private int startGenericRecognitionLocked(ModelData modelData, boolean notify) {
+ // A single routine that implements the start recognition logic for both generic and keyphrase
+ // models.
+ private int startRecognitionLocked(ModelData modelData, boolean notify) {
IRecognitionStatusCallback callback = modelData.getCallback();
int handle = modelData.getHandle();
RecognitionConfig config = modelData.getRecognitionConfig();
if (callback == null || handle == INVALID_VALUE || config == null) {
// Nothing to do here.
- Slog.w(TAG, "startGenericRecognition: Bad data passed in.");
+ Slog.w(TAG, "startRecognition: Bad data passed in.");
+ MetricsLogger.count(mContext, "sth_start_recognition_error", 1);
return STATUS_ERROR;
}
if (!isRecognitionAllowed()) {
// Nothing to do here.
- Slog.w(TAG, "startGenericRecognition requested but not allowed.");
+ Slog.w(TAG, "startRecognition requested but not allowed.");
+ MetricsLogger.count(mContext, "sth_start_recognition_not_allowed", 1);
return STATUS_OK;
}
int status = mModule.startRecognition(handle, config);
if (status != SoundTrigger.STATUS_OK) {
- Slog.w(TAG, "startGenericRecognition failed with " + status);
+ Slog.w(TAG, "startRecognition failed with " + status);
+ MetricsLogger.count(mContext, "sth_start_recognition_error", 1);
// Notify of error if needed.
if (notify) {
try {
@@ -978,6 +990,7 @@
}
} else {
Slog.i(TAG, "startRecognition successful.");
+ MetricsLogger.count(mContext, "sth_start_recognition_success", 1);
modelData.setStarted();
// Notify of resume if needed.
if (notify) {
@@ -988,17 +1001,31 @@
}
}
}
- if (DBG) dumpGenericModelStateLocked();
+ if (DBG) {
+ Slog.d(TAG, "Model being started :" + modelData.toString());
+ }
return status;
}
- private int stopGenericRecognitionLocked(ModelData modelData, boolean notify) {
+ private int stopRecognitionLocked(ModelData modelData, boolean notify) {
IRecognitionStatusCallback callback = modelData.getCallback();
// Stop recognition (only if we haven't been aborted).
- int status = mModule.stopRecognition(modelData.getHandle());
+ int status = STATUS_OK;
+
+ // This logic for "recognition aborted" now works for both generic and keyphrase models.
+ // The idea here is to "skip" the stopRecognition() call if the lower layer has
+ // aborted recognition. Also we "consume" the abort state as well, so if there is another
+ // stopRecognition() request, it will go through -- this seems to have been the previously
+ // intended design.
+ if (!mRecognitionAborted) {
+ status = mModule.stopRecognition(modelData.getHandle());
+ } else {
+ mRecognitionAborted = false;
+ }
if (status != SoundTrigger.STATUS_OK) {
Slog.w(TAG, "stopRecognition call failed with " + status);
+ MetricsLogger.count(mContext, "sth_stop_recognition_error", 1);
if (notify) {
try {
callback.onError(status);
@@ -1008,6 +1035,7 @@
}
} else {
modelData.setStopped();
+ MetricsLogger.count(mContext, "sth_stop_recognition_success", 1);
// Notify of pause if needed.
if (notify) {
try {
@@ -1017,7 +1045,9 @@
}
}
}
- if (DBG) dumpGenericModelStateLocked();
+ if (DBG) {
+ Slog.d(TAG, "Model being stopped :" + modelData.toString());
+ }
return status;
}
@@ -1035,8 +1065,9 @@
mRecognitionRunning = false;
return mRecognitionRunning;
}
- if (mKeyphraseListener != null && mKeyphraseStarted &&
- mCurrentKeyphraseModelHandle != INVALID_VALUE && mCurrentSoundModel != null) {
+ if (mKeyphraseModelData != null && mKeyphraseModelData.getCallback() != null &&
+ mKeyphraseModelData.isModelStarted() &&
+ mKeyphraseModelData.getHandle() != INVALID_VALUE) {
mRecognitionRunning = true;
return mRecognitionRunning;
}
@@ -1065,26 +1096,55 @@
// One of MODEL_NOTLOADED, MODEL_LOADED, MODEL_STARTED (which implies loaded).
private int mModelState;
-
private UUID mModelId;
+ // mRequested captures the explicit intent that a start was requested for this model. We
+ // continue to capture and retain this state even after the model gets started, so that we
+ // know when a model gets stopped due to "other" reasons, that we should start it again.
+ // This was the intended behavior of the "mRequested" variable in the previous version of
+ // this code that we are replicating here.
+ //
+ // The "other" reasons include power save, abort being called from the lower layer (due
+ // to concurrent capture not being supported) and phone call state. Once we recover from
+ // these transient disruptions, we would start such models again where mRequested == true.
+ // Thus, mRequested gets reset only when there is an explicit intent to stop the model
+ // coming from the SoundTriggerService layer that uses this class (and thus eventually
+ // from the app that manages this model).
+ private boolean mRequested = false;
+
// One of SoundModel.TYPE_GENERIC or SoundModel.TYPE_KEYPHRASE. Initially set
// to SoundModel.TYPE_UNKNOWN;
private int mModelType = SoundModel.TYPE_UNKNOWN;
+
private IRecognitionStatusCallback mCallback = null;
private RecognitionConfig mRecognitionConfig = null;
-
// Model handle is an integer used by the HAL as an identifier for sound
// models.
private int mModelHandle = INVALID_VALUE;
- ModelData(UUID modelId) {
+ // The SoundModel instance, one of KeyphraseSoundModel or GenericSoundModel.
+ private SoundModel mSoundModel = null;
+
+ private ModelData(UUID modelId, int modelType) {
mModelId = modelId;
+ // Private constructor, since we require modelType to be one of TYPE_GENERIC,
+ // TYPE_KEYPHRASE or TYPE_UNKNOWN.
+ mModelType = modelType;
}
- synchronized void setTypeGeneric() {
- mModelType = SoundModel.TYPE_GENERIC_SOUND;
+ static ModelData createKeyphraseModelData(UUID modelId) {
+ return new ModelData(modelId, SoundModel.TYPE_KEYPHRASE);
+ }
+
+ static ModelData createGenericModelData(UUID modelId) {
+ return new ModelData(modelId, SoundModel.TYPE_GENERIC_SOUND);
+ }
+
+ // Note that most of the functionality in this Java class will not work for
+ // SoundModel.TYPE_UNKNOWN nevertheless we have it since lower layers support it.
+ static ModelData createModelDataOfUnknownType(UUID modelId) {
+ return new ModelData(modelId, SoundModel.TYPE_UNKNOWN);
}
synchronized void setCallback(IRecognitionStatusCallback callback) {
@@ -1099,6 +1159,10 @@
return (mModelState == MODEL_LOADED || mModelState == MODEL_STARTED);
}
+ synchronized boolean isModelNotLoaded() {
+ return mModelState == MODEL_NOTLOADED;
+ }
+
synchronized void setStarted() {
mModelState = MODEL_STARTED;
}
@@ -1136,11 +1200,40 @@
return mModelHandle;
}
+ synchronized UUID getModelId() {
+ return mModelId;
+ }
+
synchronized RecognitionConfig getRecognitionConfig() {
return mRecognitionConfig;
}
- String stateToString() {
+ // Whether a start recognition was requested.
+ synchronized boolean getRequested() {
+ return mRequested;
+ }
+
+ synchronized void setRequested(boolean requested) {
+ mRequested = requested;
+ }
+
+ synchronized void setSoundModel(SoundModel soundModel) {
+ mSoundModel = soundModel;
+ }
+
+ synchronized SoundModel getSoundModel() {
+ return mSoundModel;
+ }
+
+ synchronized int getModelType() {
+ return mModelType;
+ }
+
+ synchronized boolean isKeyphraseModel() {
+ return mModelType == SoundModel.TYPE_KEYPHRASE;
+ }
+
+ synchronized String stateToString() {
switch(mModelState) {
case MODEL_NOTLOADED: return "NOT_LOADED";
case MODEL_LOADED: return "LOADED";
@@ -1149,8 +1242,24 @@
return "Unknown state";
}
- public String toString() {
- return "Handle: " + mModelHandle + "ModelState: " + stateToString();
+ synchronized String requestedToString() {
+ return "Requested: " + (mRequested ? "Yes" : "No");
+ }
+
+ synchronized String callbackToString() {
+ return "Callback: " + (mCallback != null ? mCallback.asBinder() : "null");
+ }
+
+ synchronized String uuidToString() {
+ return "UUID: " + mModelId;
+ }
+
+ synchronized public String toString() {
+ return "Handle: " + mModelHandle + "\n" +
+ "ModelState: " + stateToString() + "\n" +
+ requestedToString() + "\n" +
+ callbackToString() + "\n" +
+ uuidToString();
}
}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 461611d..adc7c21 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -419,6 +419,13 @@
public static final String KEY_CARRIER_DATA_CALL_APN_DELAY_FASTER_LONG =
"carrier_data_call_apn_delay_faster_long";
+ /**
+ * Default APN types that are metered by the carrier
+ * @hide
+ */
+ public static final String KEY_CARRIER_METERED_APN_TYPES_STRINGS =
+ "carrier_metered_apn_types_strings";
+
/* The following 3 fields are related to carrier visual voicemail. */
/**
@@ -699,6 +706,8 @@
sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_DEFAULT_LONG, 20000);
sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_FASTER_LONG, 3000);
sDefaults.putInt(KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT, 7200);
+ sDefaults.putStringArray(KEY_CARRIER_METERED_APN_TYPES_STRINGS,
+ new String[]{"default", "mms", "dun", "supl"});
sDefaults.putStringArray(KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY, null);
sDefaults.putStringArray(KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY, null);
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 0da1bb1..6c8be39 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -86,6 +86,155 @@
}
private Test[] mTests = new Test[] {
+ new Test("Post a group") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("Min priority group 1")
+ .setLights(0xff0000ff, 1, 0)
+ .setPriority(Notification.PRIORITY_MIN)
+ .setGroup("group1")
+ .build();
+ mNM.notify(6000, n);
+ n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("low priority group 1")
+ .setLights(0xff0000ff, 1, 0)
+ .setPriority(Notification.PRIORITY_LOW)
+ .setGroup("group1")
+ .build();
+ mNM.notify(6001, n);
+ n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("default priority group 1")
+ .setLights(0xff0000ff, 1, 0)
+ .setPriority(Notification.PRIORITY_DEFAULT)
+ .setGroup("group1")
+ .build();
+ mNM.notify(6002, n);
+ n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("summary group 1")
+ .setLights(0xff0000ff, 1, 0)
+ .setPriority(Notification.PRIORITY_MIN)
+ .setGroup("group1")
+ .setGroupSummary(true)
+ .build();
+ mNM.notify(6003, n);
+ }
+ },
+ new Test("Post a group (2) w/o summary") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("Min priority group 2")
+ .setLights(0xff0000ff, 1, 0)
+ .setPriority(Notification.PRIORITY_MIN)
+ .setGroup("group2")
+ .build();
+ mNM.notify(6100, n);
+ n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("low priority group 2")
+ .setLights(0xff0000ff, 1, 0)
+ .setPriority(Notification.PRIORITY_LOW)
+ .setGroup("group2")
+ .build();
+ mNM.notify(6101, n);
+ n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("default priority group 2")
+ .setLights(0xff0000ff, 1, 0)
+ .setPriority(Notification.PRIORITY_DEFAULT)
+ .setGroup("group2")
+ .build();
+ mNM.notify(6102, n);
+ }
+ },
+ new Test("Summary for group 2") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("summary group 2")
+ .setLights(0xff0000ff, 1, 0)
+ .setPriority(Notification.PRIORITY_MIN)
+ .setGroup("group2")
+ .setGroupSummary(true)
+ .build();
+ mNM.notify(6103, n);
+ }
+ },
+ new Test("Group up public-secret") {
+ 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)
+ .setGroup("public-secret")
+ .build();
+ mNM.notify("public", 7009, n);
+ 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)
+ .setGroup("public-secret")
+ .build();
+ mNM.notify("no public", 7010, n);
+ 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)
+ .setGroup("public-secret")
+ .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("priv with pub", 7011, n);
+ 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)
+ .setGroup("public-secret")
+ .build();
+ mNM.notify("secret", 7012, n);
+
+ Notification s = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("summary group public-secret")
+ .setLights(0xff0000ff, 1, 0)
+ .setPriority(Notification.PRIORITY_MIN)
+ .setGroup("public-secret")
+ .setGroupSummary(true)
+ .build();
+ mNM.notify(7113, s);
+ }
+ },
+ new Test("Cancel priority autogroup") {
+ public void run()
+ {
+ try {
+ mNM.cancel(Integer.MAX_VALUE);
+ } catch (Exception e) {
+ Toast.makeText(NotificationTestList.this, "cancel failed (yay)",
+ Toast.LENGTH_LONG).show();
+ }
+ }
+ },
new Test("Min priority") {
public void run()
{
@@ -95,7 +244,7 @@
.setLights(0xff0000ff, 1, 0)
.setPriority(Notification.PRIORITY_MIN)
.build();
- mNM.notify(7000, n);
+ mNM.notify("min", 7000, n);
}
},
new Test("Min priority, high pri flag") {
@@ -123,7 +272,7 @@
.setLights(0xff0000ff, 1, 0)
.setPriority(Notification.PRIORITY_LOW)
.build();
- mNM.notify(7002, n);
+ mNM.notify("low", 7002, n);
}
},
new Test("Default priority") {
@@ -135,7 +284,7 @@
.setLights(0xff0000ff, 1, 0)
.setPriority(Notification.PRIORITY_DEFAULT)
.build();
- mNM.notify(7004, n);
+ mNM.notify("default", 7004, n);
}
},
new Test("High priority") {
@@ -150,7 +299,7 @@
getPackageName() + "/raw/ringer"))
.setPriority(Notification.PRIORITY_HIGH)
.build();
- mNM.notify(7006, n);
+ mNM.notify("high", 7006, n);
}
},
new Test("Max priority") {
@@ -166,7 +315,7 @@
.setPriority(Notification.PRIORITY_MAX)
.setFullScreenIntent(makeIntent2(), false)
.build();
- mNM.notify(7007, n);
+ mNM.notify("max", 7007, n);
}
},
new Test("Max priority with delay") {
@@ -199,7 +348,7 @@
.setPriority(Notification.PRIORITY_DEFAULT)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.build();
- mNM.notify(7009, n);
+ mNM.notify("public", 7009, n);
}
},
new Test("private notification, no public") {
@@ -212,7 +361,7 @@
.setPriority(Notification.PRIORITY_DEFAULT)
.setVisibility(Notification.VISIBILITY_PRIVATE)
.build();
- mNM.notify(7010, n);
+ mNM.notify("no public", 7010, n);
}
},
new Test("private notification, has public") {
@@ -231,7 +380,7 @@
.setVisibility(Notification.VISIBILITY_PUBLIC)
.build())
.build();
- mNM.notify(7011, n);
+ mNM.notify("priv with pub", 7011, n);
}
},
new Test("secret notification") {
@@ -244,7 +393,7 @@
.setPriority(Notification.PRIORITY_DEFAULT)
.setVisibility(Notification.VISIBILITY_SECRET)
.build();
- mNM.notify(7012, n);
+ mNM.notify("secret", 7012, n);
}
},
new Test("Off") {
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 0bb88a7..db40416 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -492,6 +492,21 @@
SortedVector<String8> reasons;
};
+struct Feature {
+ Feature() : required(false), version(-1) {}
+ Feature(bool required, int32_t version = -1) : required(required), version(version) {}
+
+ /**
+ * Whether the feature is required.
+ */
+ bool required;
+
+ /**
+ * What version of the feature is requested.
+ */
+ int32_t version;
+};
+
/**
* Represents a <feature-group> tag in the AndroidManifest.xml
*/
@@ -506,7 +521,7 @@
/**
* Explicit features defined in the group
*/
- KeyedVector<String8, bool> features;
+ KeyedVector<String8, Feature> features;
/**
* OpenGL ES version required
@@ -541,11 +556,18 @@
const size_t numFeatures = grp.features.size();
for (size_t i = 0; i < numFeatures; i++) {
- const bool required = grp.features[i];
+ const Feature& feature = grp.features[i];
+ const bool required = feature.required;
+ const int32_t version = feature.version;
const String8& featureName = grp.features.keyAt(i);
- printf(" uses-feature%s: name='%s'\n", (required ? "" : "-not-required"),
+ printf(" uses-feature%s: name='%s'", (required ? "" : "-not-required"),
ResTable::normalizeForOutput(featureName.string()).string());
+
+ if (version > 0) {
+ printf(" version='%d'", version);
+ }
+ printf("\n");
}
const size_t numImpliedFeatures =
@@ -590,15 +612,15 @@
static void addParentFeatures(FeatureGroup* grp, const String8& name) {
if (name == "android.hardware.camera.autofocus" ||
name == "android.hardware.camera.flash") {
- grp->features.add(String8("android.hardware.camera"), true);
+ grp->features.add(String8("android.hardware.camera"), Feature(true));
} else if (name == "android.hardware.location.gps" ||
name == "android.hardware.location.network") {
- grp->features.add(String8("android.hardware.location"), true);
+ grp->features.add(String8("android.hardware.location"), Feature(true));
} else if (name == "android.hardware.touchscreen.multitouch") {
- grp->features.add(String8("android.hardware.touchscreen"), true);
+ grp->features.add(String8("android.hardware.touchscreen"), Feature(true));
} else if (name == "android.hardware.touchscreen.multitouch.distinct") {
- grp->features.add(String8("android.hardware.touchscreen.multitouch"), true);
- grp->features.add(String8("android.hardware.touchscreen"), true);
+ grp->features.add(String8("android.hardware.touchscreen.multitouch"), Feature(true));
+ grp->features.add(String8("android.hardware.touchscreen"), Feature(true));
} else if (name == "android.hardware.opengles.aep") {
const int openGLESVersion31 = 0x00030001;
if (openGLESVersion31 > grp->openGLESVersion) {
@@ -727,6 +749,9 @@
return 1;
}
+ // Source for AndroidManifest.xml
+ const String8 manifestFile = String8::format("%s@AndroidManifest.xml", filename);
+
// The dynamicRefTable can be null if there are no resources for this asset cookie.
// This fine.
const DynamicRefTable* dynamicRefTable = res.getDynamicRefTableForCookie(assetsCookie);
@@ -1424,10 +1449,28 @@
} else if (tag == "uses-feature") {
String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);
if (name != "" && error == "") {
- int req = AaptXml::getIntegerAttribute(tree,
- REQUIRED_ATTR, 1);
+ const char* androidSchema =
+ "http://schemas.android.com/apk/res/android";
- commonFeatures.features.add(name, req);
+ int32_t req = AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1,
+ &error);
+ if (error != "") {
+ SourcePos(manifestFile, tree.getLineNumber()).error(
+ "failed to read attribute 'android:required': %s",
+ error.string());
+ goto bail;
+ }
+
+ int32_t version = AaptXml::getIntegerAttribute(tree, androidSchema,
+ "version", 0, &error);
+ if (error != "") {
+ SourcePos(manifestFile, tree.getLineNumber()).error(
+ "failed to read attribute 'android:version': %s",
+ error.string());
+ goto bail;
+ }
+
+ commonFeatures.features.add(name, Feature(req != 0, version));
if (req) {
addParentFeatures(&commonFeatures, name);
}
@@ -1751,12 +1794,27 @@
}
}
} else if (withinFeatureGroup && tag == "uses-feature") {
+ const String8 androidSchema("http://schemas.android.com/apk/res/android");
FeatureGroup& top = featureGroups.editTop();
String8 name = AaptXml::getResolvedAttribute(res, tree, NAME_ATTR, &error);
if (name != "" && error == "") {
- top.features.add(name, true);
+ Feature feature(true);
+
+ int32_t featureVers = AaptXml::getIntegerAttribute(
+ tree, androidSchema.string(), "version", 0, &error);
+ if (error == "") {
+ feature.version = featureVers;
+ } else {
+ SourcePos(manifestFile, tree.getLineNumber()).error(
+ "failed to read attribute 'android:version': %s",
+ error.string());
+ goto bail;
+ }
+
+ top.features.add(name, feature);
addParentFeatures(&top, name);
+
} else {
int vers = AaptXml::getIntegerAttribute(tree, GL_ES_VERSION_ATTR,
&error);
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index ef11d66..3a1e2bb 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -131,33 +131,40 @@
libbase \
libprotobuf-cpp-lite_static
-# Do not add any shared libraries. AAPT2 is built to run on many
-# environments that may not have the required dependencies.
-hostSharedLibs :=
-ifneq ($(strip $(USE_MINGW)),)
- hostStaticLibs += libz
-else
- hostLdLibs += -lz
-endif
+# Statically link libz for MinGW (Win SDK under Linux),
+# and dynamically link for all others.
+hostStaticLibs_windows := libz
+hostLdLibs_linux := -lz
+hostLdLibs_darwin := -lz
cFlags := -Wall -Werror -Wno-unused-parameter -UNDEBUG
-cppFlags := -std=c++14 -Wno-missing-field-initializers -fno-exceptions -fno-rtti
+cFlags_darwin := -D_DARWIN_UNLIMITED_STREAMS
+cFlags_windows := -Wno-maybe-uninitialized # Incorrectly marking use of Maybe.value() as error.
+cppFlags := -std=c++11 -Wno-missing-field-initializers -fno-exceptions -fno-rtti
protoIncludes := $(call generated-sources-dir-for,STATIC_LIBRARIES,libaapt2,HOST)
# ==========================================================
+# NOTE: Do not add any shared libraries.
+# AAPT2 is built to run on many environments
+# that may not have the required dependencies.
+# ==========================================================
+
+# ==========================================================
# Build the host static library: libaapt2
# ==========================================================
include $(CLEAR_VARS)
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
LOCAL_MODULE := libaapt2
-
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE_HOST_OS := darwin linux windows
+LOCAL_CFLAGS := $(cFlags)
+LOCAL_CFLAGS_darwin := $(cFlags_darwin)
+LOCAL_CFLAGS_windows := $(cFlags_windows)
+LOCAL_CPPFLAGS := $(cppFlags)
+LOCAL_C_INCLUDES := $(protoIncludes)
LOCAL_SRC_FILES := $(sources)
-LOCAL_STATIC_LIBRARIES += $(hostStaticLibs)
-LOCAL_CFLAGS += $(cFlags)
-LOCAL_CPPFLAGS += $(cppFlags)
-LOCAL_C_INCLUDES += $(protoIncludes)
-
+LOCAL_STATIC_LIBRARIES := $(hostStaticLibs)
+LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows)
include $(BUILD_HOST_STATIC_LIBRARY)
# ==========================================================
@@ -166,16 +173,18 @@
include $(CLEAR_VARS)
LOCAL_MODULE := libaapt2_tests
LOCAL_MODULE_TAGS := tests
-
+LOCAL_MODULE_HOST_OS := darwin linux windows
+LOCAL_CFLAGS := $(cFlags)
+LOCAL_CFLAGS_darwin := $(cFlags_darwin)
+LOCAL_CFLAGS_windows := $(cFlags_windows)
+LOCAL_CPPFLAGS := $(cppFlags)
+LOCAL_C_INCLUDES := $(protoIncludes)
LOCAL_SRC_FILES := $(testSources)
-
-LOCAL_STATIC_LIBRARIES += libaapt2 $(hostStaticLibs)
-LOCAL_SHARED_LIBRARIES += $(hostSharedLibs)
-LOCAL_LDLIBS += $(hostLdLibs)
-LOCAL_CFLAGS += $(cFlags)
-LOCAL_CPPFLAGS += $(cppFlags)
-LOCAL_C_INCLUDES += $(protoIncludes)
-
+LOCAL_STATIC_LIBRARIES := libaapt2 $(hostStaticLibs)
+LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows)
+LOCAL_LDLIBS := $(hostLdLibs)
+LOCAL_LDLIBS_darwin := $(hostLdLibs_darwin)
+LOCAL_LDLIBS_linux := $(hostLdLibs_linux)
include $(BUILD_HOST_NATIVE_TEST)
# ==========================================================
@@ -183,16 +192,18 @@
# ==========================================================
include $(CLEAR_VARS)
LOCAL_MODULE := aapt2
-
+LOCAL_MODULE_HOST_OS := darwin linux windows
+LOCAL_CFLAGS := $(cFlags)
+LOCAL_CFLAGS_darwin := $(cFlags_darwin)
+LOCAL_CFLAGS_windows := $(cFlags_windows)
+LOCAL_CPPFLAGS := $(cppFlags)
+LOCAL_C_INCLUDES := $(protoIncludes)
LOCAL_SRC_FILES := $(main) $(toolSources)
-
-LOCAL_STATIC_LIBRARIES += libaapt2 $(hostStaticLibs)
-LOCAL_SHARED_LIBRARIES += $(hostSharedLibs)
-LOCAL_LDLIBS += $(hostLdLibs)
-LOCAL_CFLAGS += $(cFlags)
-LOCAL_CPPFLAGS += $(cppFlags)
-LOCAL_C_INCLUDES += $(protoIncludes)
-
+LOCAL_STATIC_LIBRARIES := libaapt2 $(hostStaticLibs)
+LOCAL_STATIC_LIBRARIES_windows := $(hostStaticLibs_windows)
+LOCAL_LDLIBS := $(hostLdLibs)
+LOCAL_LDLIBS_darwin := $(hostLdLibs_darwin)
+LOCAL_LDLIBS_linux := $(hostLdLibs_linux)
include $(BUILD_HOST_EXECUTABLE)
ifeq ($(ONE_SHOT_MAKEFILE),)
diff --git a/tools/aapt2/StringPool_test.cpp b/tools/aapt2/StringPool_test.cpp
index e93c2fba..2b2d348 100644
--- a/tools/aapt2/StringPool_test.cpp
+++ b/tools/aapt2/StringPool_test.cpp
@@ -20,8 +20,6 @@
#include <gtest/gtest.h>
#include <string>
-using namespace android;
-
namespace aapt {
TEST(StringPoolTest, InsertOneString) {
@@ -171,24 +169,28 @@
}
TEST(StringPoolTest, FlattenEmptyStringPoolUtf8) {
+ using namespace android; // For NO_ERROR on Windows.
+
StringPool pool;
BigBuffer buffer(1024);
StringPool::flattenUtf8(&buffer, pool);
std::unique_ptr<uint8_t[]> data = util::copy(buffer);
- android::ResStringPool test;
- ASSERT_EQ(test.setTo(data.get(), buffer.size()), android::NO_ERROR);
+ ResStringPool test;
+ ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
}
TEST(StringPoolTest, FlattenOddCharactersUtf16) {
+ using namespace android; // For NO_ERROR on Windows.
+
StringPool pool;
pool.makeRef(u"\u093f");
BigBuffer buffer(1024);
StringPool::flattenUtf16(&buffer, pool);
std::unique_ptr<uint8_t[]> data = util::copy(buffer);
- android::ResStringPool test;
- ASSERT_EQ(test.setTo(data.get(), buffer.size()), android::NO_ERROR);
+ ResStringPool test;
+ ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
size_t len = 0;
const char16_t* str = test.stringAt(0, &len);
EXPECT_EQ(1u, len);
@@ -199,6 +201,8 @@
constexpr const char16_t* sLongString = u"バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンスを抑え、バイブレーション、位置情報サービス、大半のバックグラウンドデータを制限します。メール、SMSや、同期を使 用するその他のアプリは、起動しても更新されないことがあります。バッテリーセーバーは端末の充電中は自動的にOFFになります。";
TEST(StringPoolTest, FlattenUtf8) {
+ using namespace android; // For NO_ERROR on Windows.
+
StringPool pool;
StringPool::Ref ref1 = pool.makeRef(u"hello");
@@ -219,8 +223,8 @@
std::unique_ptr<uint8_t[]> data = util::copy(buffer);
{
- android::ResStringPool test;
- ASSERT_EQ(test.setTo(data.get(), buffer.size()), android::NO_ERROR);
+ ResStringPool test;
+ ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
EXPECT_EQ(util::getString(test, 0), u"hello");
EXPECT_EQ(util::getString(test, 1), u"goodbye");
diff --git a/tools/aapt2/compile/PseudolocaleGenerator.cpp b/tools/aapt2/compile/PseudolocaleGenerator.cpp
index be26b52..99c2077 100644
--- a/tools/aapt2/compile/PseudolocaleGenerator.cpp
+++ b/tools/aapt2/compile/PseudolocaleGenerator.cpp
@@ -20,6 +20,8 @@
#include "compile/PseudolocaleGenerator.h"
#include "compile/Pseudolocalizer.h"
+#include <algorithm>
+
namespace aapt {
std::unique_ptr<StyledString> pseudolocalizeStyledString(StyledString* string,
diff --git a/tools/aapt2/flatten/TableFlattener.cpp b/tools/aapt2/flatten/TableFlattener.cpp
index da81046..28a7928 100644
--- a/tools/aapt2/flatten/TableFlattener.cpp
+++ b/tools/aapt2/flatten/TableFlattener.cpp
@@ -24,6 +24,7 @@
#include "util/BigBuffer.h"
#include <android-base/macros.h>
+#include <algorithm>
#include <type_traits>
#include <numeric>
diff --git a/tools/aapt2/flatten/XmlFlattener.cpp b/tools/aapt2/flatten/XmlFlattener.cpp
index 3eac633..570cd96 100644
--- a/tools/aapt2/flatten/XmlFlattener.cpp
+++ b/tools/aapt2/flatten/XmlFlattener.cpp
@@ -21,6 +21,7 @@
#include "xml/XmlDom.h"
#include <androidfw/ResourceTypes.h>
+#include <algorithm>
#include <utils/misc.h>
#include <vector>
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index fef5ca3..4e6eb81 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -46,6 +46,8 @@
::testing::AssertionResult flatten(xml::XmlResource* doc, android::ResXMLTree* outTree,
XmlFlattenerOptions options = {}) {
+ using namespace android; // For NO_ERROR on windows because it is a macro.
+
BigBuffer buffer(1024);
XmlFlattener flattener(&buffer, options);
if (!flattener.consume(mContext.get(), doc)) {
@@ -53,7 +55,7 @@
}
std::unique_ptr<uint8_t[]> data = util::copy(buffer);
- if (outTree->setTo(data.get(), buffer.size(), true) != android::NO_ERROR) {
+ if (outTree->setTo(data.get(), buffer.size(), true) != NO_ERROR) {
return ::testing::AssertionFailure() << "flattened XML is corrupt";
}
return ::testing::AssertionSuccess();
diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp
index ba74439..b7e7f90 100644
--- a/tools/aapt2/java/AnnotationProcessor.cpp
+++ b/tools/aapt2/java/AnnotationProcessor.cpp
@@ -21,7 +21,7 @@
namespace aapt {
-void AnnotationProcessor::appendCommentLine(const std::string& comment) {
+void AnnotationProcessor::appendCommentLine(std::string& comment) {
static const std::string sDeprecated = "@deprecated";
static const std::string sSystemApi = "@SystemApi";
@@ -29,8 +29,14 @@
mAnnotationBitMask |= kDeprecated;
}
- if (comment.find(sSystemApi) != std::string::npos) {
+ std::string::size_type idx = comment.find(sSystemApi);
+ if (idx != std::string::npos) {
mAnnotationBitMask |= kSystemApi;
+ comment.erase(comment.begin() + idx, comment.begin() + idx + sSystemApi.size());
+ }
+
+ if (util::trimWhitespace(comment).empty()) {
+ return;
}
if (!mHasComments) {
@@ -46,7 +52,8 @@
for (StringPiece16 line : util::tokenize(comment, u'\n')) {
line = util::trimWhitespace(line);
if (!line.empty()) {
- appendCommentLine(util::utf16ToUtf8(line));
+ std::string utf8Line = util::utf16ToUtf8(line);
+ appendCommentLine(utf8Line);
}
}
}
@@ -55,7 +62,8 @@
for (StringPiece line : util::tokenize(comment, '\n')) {
line = util::trimWhitespace(line);
if (!line.empty()) {
- appendCommentLine(line.toString());
+ std::string utf8Line = line.toString();
+ appendCommentLine(utf8Line);
}
}
}
diff --git a/tools/aapt2/java/AnnotationProcessor.h b/tools/aapt2/java/AnnotationProcessor.h
index 0fc5b08..8309dd9 100644
--- a/tools/aapt2/java/AnnotationProcessor.h
+++ b/tools/aapt2/java/AnnotationProcessor.h
@@ -43,7 +43,6 @@
* /\*
* * This is meant to be hidden because
* * It is system api. Also it is @deprecated
- * * @SystemApi
* *\/
*
* Output Annotations:
@@ -79,7 +78,7 @@
bool mHasComments = false;
uint32_t mAnnotationBitMask = 0;
- void appendCommentLine(const std::string& line);
+ void appendCommentLine(std::string& line);
};
} // namespace aapt
diff --git a/tools/aapt2/java/AnnotationProcessor_test.cpp b/tools/aapt2/java/AnnotationProcessor_test.cpp
index da96b84..5a39add 100644
--- a/tools/aapt2/java/AnnotationProcessor_test.cpp
+++ b/tools/aapt2/java/AnnotationProcessor_test.cpp
@@ -14,57 +14,18 @@
* limitations under the License.
*/
-#include "ResourceParser.h"
-#include "ResourceTable.h"
-#include "ResourceValues.h"
#include "java/AnnotationProcessor.h"
-#include "test/Builders.h"
-#include "test/Context.h"
-#include "xml/XmlPullParser.h"
-
-#include <gtest/gtest.h>
+#include "test/Test.h"
namespace aapt {
-struct AnnotationProcessorTest : public ::testing::Test {
- std::unique_ptr<IAaptContext> mContext;
- ResourceTable mTable;
-
- void SetUp() override {
- mContext = test::ContextBuilder().build();
- }
-
- ::testing::AssertionResult parse(const StringPiece& str) {
- ResourceParserOptions options;
- ResourceParser parser(mContext->getDiagnostics(), &mTable, Source{}, ConfigDescription{},
- options);
- std::stringstream in;
- in << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" << str;
- xml::XmlPullParser xmlParser(in);
- if (parser.parse(&xmlParser)) {
- return ::testing::AssertionSuccess();
- }
- return ::testing::AssertionFailure();
- }
-};
-
-TEST_F(AnnotationProcessorTest, EmitsDeprecated) {
- ASSERT_TRUE(parse(R"EOF(
- <resources>
- <declare-styleable name="foo">
- <!-- Some comment, and it should contain
- a marker word, something that marks
- this resource as nor needed.
- {@deprecated That's the marker! } -->
- <attr name="autoText" format="boolean" />
- </declare-styleable>
- </resources>)EOF"));
-
- Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/autoText");
- ASSERT_NE(nullptr, attr);
+TEST(AnnotationProcessorTest, EmitsDeprecated) {
+ const char* comment = "Some comment, and it should contain a marker word, "
+ "something that marks this resource as nor needed. "
+ "{@deprecated That's the marker! }";
AnnotationProcessor processor;
- processor.appendComment(attr->getComment());
+ processor.appendComment(comment);
std::stringstream result;
processor.writeToStream(&result, "");
@@ -73,6 +34,19 @@
EXPECT_NE(std::string::npos, annotations.find("@Deprecated"));
}
+TEST(AnnotationProcessorTest, EmitsSystemApiAnnotationAndRemovesFromComment) {
+ AnnotationProcessor processor;
+ processor.appendComment("@SystemApi This is a system API");
+
+ std::stringstream result;
+ processor.writeToStream(&result, "");
+ std::string annotations = result.str();
+
+ EXPECT_NE(std::string::npos, annotations.find("@android.annotation.SystemApi"));
+ EXPECT_EQ(std::string::npos, annotations.find("@SystemApi"));
+ EXPECT_NE(std::string::npos, annotations.find("This is a system API"));
+}
+
} // namespace aapt
diff --git a/tools/aapt2/java/ClassDefinition.h b/tools/aapt2/java/ClassDefinition.h
index 53e0f6f..d45328f 100644
--- a/tools/aapt2/java/ClassDefinition.h
+++ b/tools/aapt2/java/ClassDefinition.h
@@ -125,7 +125,7 @@
void writeToStream(const StringPiece& prefix, bool final, std::ostream* out) const override {
ClassMember::writeToStream(prefix, final, out);
- *out << "public static final int[] " << mName << "={";
+ *out << prefix << "public static final int[] " << mName << "={";
const auto begin = mElements.begin();
const auto end = mElements.end();
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 092bab24..24347a1 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -188,8 +188,8 @@
struct StyleableAttr {
const Reference* attrRef;
- std::shared_ptr<Attribute> attribute;
std::string fieldName;
+ std::unique_ptr<SymbolTable::Symbol> symbol;
};
static bool lessStyleableAttr(const StyleableAttr& lhs, const StyleableAttr& rhs) {
@@ -245,8 +245,9 @@
// legal values for this attribute.
const SymbolTable::Symbol* symbol = mContext->getExternalSymbols()->findByReference(
mangledReference);
- if (symbol) {
- styleableAttr.attribute = symbol->attribute;
+ if (symbol && symbol->attribute) {
+ // Copy the symbol data structure because the returned instance can be destroyed.
+ styleableAttr.symbol = util::make_unique<SymbolTable::Symbol>(*symbol);
}
sortedAttributes.push_back(std::move(styleableAttr));
}
@@ -273,6 +274,16 @@
"<tr><th>Attribute</th><th>Description</th></tr>\n";
for (const StyleableAttr& entry : sortedAttributes) {
+ if (!entry.symbol) {
+ continue;
+ }
+
+ if (mOptions.types == JavaClassGeneratorOptions::SymbolTypes::kPublic &&
+ !entry.symbol->isPublic) {
+ // Don't write entries for non-public attributes.
+ continue;
+ }
+
const ResourceName& attrName = entry.attrRef->name.value();
styleableComment << "<tr><td>";
styleableComment << "<code>{@link #"
@@ -284,14 +295,30 @@
styleableComment << "</td>";
styleableComment << "<td>";
- if (entry.attribute) {
- styleableComment << entry.attribute->getComment();
+
+ // Only use the comment up until the first '.'. This is to stay compatible with
+ // the way old AAPT did it (presumably to keep it short and to avoid including
+ // annotations like @hide which would affect this Styleable).
+ StringPiece16 attrCommentLine = entry.symbol->attribute->getComment();
+ auto iter = std::find(attrCommentLine.begin(), attrCommentLine.end(), u'.');
+ if (iter != attrCommentLine.end()) {
+ attrCommentLine = attrCommentLine.substr(
+ 0, (iter - attrCommentLine.begin()) + 1);
}
- styleableComment << "</td></tr>\n";
+ styleableComment << attrCommentLine << "</td></tr>\n";
}
styleableComment << "</table>\n";
for (const StyleableAttr& entry : sortedAttributes) {
+ if (!entry.symbol) {
+ continue;
+ }
+
+ if (mOptions.types == JavaClassGeneratorOptions::SymbolTypes::kPublic &&
+ !entry.symbol->isPublic) {
+ // Don't write entries for non-public attributes.
+ continue;
+ }
styleableComment << "@see #" << entry.fieldName << "\n";
}
@@ -310,6 +337,17 @@
// Now we emit the indices into the array.
for (size_t i = 0; i < attrCount; i++) {
const StyleableAttr& styleableAttr = sortedAttributes[i];
+
+ if (!styleableAttr.symbol) {
+ continue;
+ }
+
+ if (mOptions.types == JavaClassGeneratorOptions::SymbolTypes::kPublic &&
+ !styleableAttr.symbol->isPublic) {
+ // Don't write entries for non-public attributes.
+ continue;
+ }
+
const ResourceName& attrName = styleableAttr.attrRef->name.value();
StringPiece16 packageName = attrName.package;
@@ -318,13 +356,13 @@
}
std::unique_ptr<IntMember> indexMember = util::make_unique<IntMember>(
- sortedAttributes[i].fieldName, i);
+ sortedAttributes[i].fieldName, static_cast<uint32_t>(i));
AnnotationProcessor* attrProcessor = indexMember->getCommentBuilder();
StringPiece16 comment = styleableAttr.attrRef->getComment();
- if (styleableAttr.attribute && comment.empty()) {
- comment = styleableAttr.attribute->getComment();
+ if (styleableAttr.symbol->attribute && comment.empty()) {
+ comment = styleableAttr.symbol->attribute->getComment();
}
if (!comment.empty()) {
@@ -342,10 +380,8 @@
attrProcessor->appendNewLine();
- if (styleableAttr.attribute) {
- addAttributeFormatDoc(attrProcessor, styleableAttr.attribute.get());
- attrProcessor->appendNewLine();
- }
+ addAttributeFormatDoc(attrProcessor, styleableAttr.symbol->attribute.get());
+ attrProcessor->appendNewLine();
std::stringstream doclavaName;
doclavaName << "@attr name " << packageName << ":" << attrName.entry;;
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index 4f041b8..7d0aa83 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -43,7 +43,8 @@
std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
.setPackageId(u"android", 0x01)
.addSimple(u"@android:id/hey-man", ResourceId(0x01020000))
- .addSimple(u"@android:attr/cool.attr", ResourceId(0x01010000))
+ .addValue(u"@android:attr/cool.attr", ResourceId(0x01010000),
+ test::AttributeBuilder(false).build())
.addValue(u"@android:styleable/hey.dude", ResourceId(0x01030000),
test::StyleableBuilder()
.addItem(u"@android:attr/cool.attr", ResourceId(0x01010000))
@@ -199,8 +200,10 @@
std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
.setPackageId(u"android", 0x01)
.setPackageId(u"com.lib", 0x02)
- .addSimple(u"@android:attr/bar", ResourceId(0x01010000))
- .addSimple(u"@com.lib:attr/bar", ResourceId(0x02010000))
+ .addValue(u"@android:attr/bar", ResourceId(0x01010000),
+ test::AttributeBuilder(false).build())
+ .addValue(u"@com.lib:attr/bar", ResourceId(0x02010000),
+ test::AttributeBuilder(false).build())
.addValue(u"@android:styleable/foo", ResourceId(0x01030000),
test::StyleableBuilder()
.addItem(u"@android:attr/bar", ResourceId(0x01010000))
@@ -239,13 +242,15 @@
ASSERT_TRUE(generator.generate(u"android", &out));
std::string actual = out.str();
- EXPECT_NE(std::string::npos, actual.find(
- R"EOF(/**
+ const char* expectedText =
+R"EOF(/**
* This is a comment
* @deprecated
*/
@Deprecated
- public static final int foo=0x01010000;)EOF"));
+ public static final int foo=0x01010000;)EOF";
+
+ EXPECT_NE(std::string::npos, actual.find(expectedText));
}
TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) {
diff --git a/tools/aapt2/java/ManifestClassGenerator_test.cpp b/tools/aapt2/java/ManifestClassGenerator_test.cpp
index a9ec318..d3bca70 100644
--- a/tools/aapt2/java/ManifestClassGenerator_test.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator_test.cpp
@@ -104,28 +104,33 @@
std::string actual;
ASSERT_TRUE(getManifestClassText(context.get(), manifest.get(), &actual));
- EXPECT_NE(std::string::npos, actual.find(
+ const char* expectedAccessInternet =
R"EOF( /**
* Required to access the internet.
* Added in API 1.
*/
- public static final String ACCESS_INTERNET="android.permission.ACCESS_INTERNET";)EOF"));
+ public static final String ACCESS_INTERNET="android.permission.ACCESS_INTERNET";)EOF";
- EXPECT_NE(std::string::npos, actual.find(
+ EXPECT_NE(std::string::npos, actual.find(expectedAccessInternet));
+
+ const char* expectedPlayOutside =
R"EOF( /**
* @deprecated This permission is for playing outside.
*/
@Deprecated
- public static final String PLAY_OUTSIDE="android.permission.PLAY_OUTSIDE";)EOF"));
+ public static final String PLAY_OUTSIDE="android.permission.PLAY_OUTSIDE";)EOF";
- EXPECT_NE(std::string::npos, actual.find(
+ EXPECT_NE(std::string::npos, actual.find(expectedPlayOutside));
+
+ const char* expectedSecret =
R"EOF( /**
* This is a private permission for system only!
* @hide
- * @SystemApi
*/
@android.annotation.SystemApi
- public static final String SECRET="android.permission.SECRET";)EOF"));
+ public static final String SECRET="android.permission.SECRET";)EOF";
+
+ EXPECT_NE(std::string::npos, actual.find(expectedSecret));
}
} // namespace aapt
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index b994664..3779638 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -168,6 +168,8 @@
return true;
});
+ manifestAction[u"eat-comment"];
+ manifestAction[u"protected-broadcast"];
manifestAction[u"uses-permission"];
manifestAction[u"permission"];
manifestAction[u"permission-tree"];
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index 0a6a4a5..e684bb0 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -51,9 +51,28 @@
class SymbolTable {
public:
struct Symbol {
+ Symbol() : Symbol(Maybe<ResourceId>{}) {
+ }
+
+ Symbol(const Maybe<ResourceId>& i) : Symbol(i, nullptr) {
+ }
+
+ Symbol(const Maybe<ResourceId>& i, const std::shared_ptr<Attribute>& attr) :
+ Symbol(i, attr, false) {
+ }
+
+ Symbol(const Maybe<ResourceId>& i, const std::shared_ptr<Attribute>& attr, bool pub) :
+ id(i), attribute(attr), isPublic(pub) {
+ }
+
+ Symbol(const Symbol&) = default;
+ Symbol(Symbol&&) = default;
+ Symbol& operator=(const Symbol&) = default;
+ Symbol& operator=(Symbol&&) = default;
+
Maybe<ResourceId> id;
std::shared_ptr<Attribute> attribute;
- bool isPublic;
+ bool isPublic = false;
};
SymbolTable() : mCache(200), mIdCache(200) {
diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp
index 86883f8..82e4fb0 100644
--- a/tools/aapt2/proto/TableProtoDeserializer.cpp
+++ b/tools/aapt2/proto/TableProtoDeserializer.cpp
@@ -388,6 +388,10 @@
std::unique_ptr<ResourceTable> deserializeTableFromPb(const pb::ResourceTable& pbTable,
const Source& source,
IDiagnostics* diag) {
+ // We import the android namespace because on Windows NO_ERROR is a macro, not an enum, which
+ // causes errors when qualifying it with android::
+ using namespace android;
+
std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
if (!pbTable.has_string_pool()) {
@@ -395,29 +399,29 @@
return {};
}
- android::ResStringPool valuePool;
- android::status_t result = valuePool.setTo(pbTable.string_pool().data().data(),
- pbTable.string_pool().data().size());
- if (result != android::NO_ERROR) {
+ ResStringPool valuePool;
+ status_t result = valuePool.setTo(pbTable.string_pool().data().data(),
+ pbTable.string_pool().data().size());
+ if (result != NO_ERROR) {
diag->error(DiagMessage(source) << "invalid string pool");
return {};
}
- android::ResStringPool sourcePool;
+ ResStringPool sourcePool;
if (pbTable.has_source_pool()) {
result = sourcePool.setTo(pbTable.source_pool().data().data(),
pbTable.source_pool().data().size());
- if (result != android::NO_ERROR) {
+ if (result != NO_ERROR) {
diag->error(DiagMessage(source) << "invalid source pool");
return {};
}
}
- android::ResStringPool symbolPool;
+ ResStringPool symbolPool;
if (pbTable.has_symbol_pool()) {
result = symbolPool.setTo(pbTable.symbol_pool().data().data(),
pbTable.symbol_pool().data().size());
- if (result != android::NO_ERROR) {
+ if (result != NO_ERROR) {
diag->error(DiagMessage(source) << "invalid symbol pool");
return {};
}
diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp
index 0f7649b..4bfdb12 100644
--- a/tools/aapt2/split/TableSplitter.cpp
+++ b/tools/aapt2/split/TableSplitter.cpp
@@ -18,6 +18,7 @@
#include "ResourceTable.h"
#include "split/TableSplitter.h"
+#include <algorithm>
#include <map>
#include <set>
#include <unordered_map>
diff --git a/tools/aapt2/unflatten/BinaryResourceParser.cpp b/tools/aapt2/unflatten/BinaryResourceParser.cpp
index 33b505e..ec46751 100644
--- a/tools/aapt2/unflatten/BinaryResourceParser.cpp
+++ b/tools/aapt2/unflatten/BinaryResourceParser.cpp
@@ -26,7 +26,7 @@
#include <androidfw/ResourceTypes.h>
#include <androidfw/TypeWrappers.h>
#include <android-base/macros.h>
-
+#include <algorithm>
#include <map>
#include <string>
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index 6428e98..bb093ab 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -17,6 +17,7 @@
#include "util/Files.h"
#include "util/Util.h"
+#include <algorithm>
#include <cerrno>
#include <cstdio>
#include <dirent.h>
diff --git a/tools/aapt2/util/Maybe.h b/tools/aapt2/util/Maybe.h
index 10a2803..595db96 100644
--- a/tools/aapt2/util/Maybe.h
+++ b/tools/aapt2/util/Maybe.h
@@ -17,6 +17,8 @@
#ifndef AAPT_MAYBE_H
#define AAPT_MAYBE_H
+#include "util/TypeTraits.h"
+
#include <cassert>
#include <type_traits>
#include <utility>
@@ -276,13 +278,15 @@
}
/**
- * Define the == operator between Maybe<T> and Maybe<U> if the operator T == U is defined.
- * Otherwise this won't be defined and the compiler will yell at the callsite instead of inside
- * Maybe.h.
+ * Define the == operator between Maybe<T> and Maybe<U> only if the operator T == U is defined.
+ * That way the compiler will show an error at the callsite when comparing two Maybe<> objects
+ * whose inner types can't be compared.
*/
template <typename T, typename U>
-auto operator==(const Maybe<T>& a, const Maybe<U>& b)
--> decltype(std::declval<T> == std::declval<U>) {
+typename std::enable_if<
+ has_eq_op<T, U>::value,
+ bool
+>::type operator==(const Maybe<T>& a, const Maybe<U>& b) {
if (a && b) {
return a.value() == b.value();
} else if (!a && !b) {
@@ -295,8 +299,10 @@
* Same as operator== but negated.
*/
template <typename T, typename U>
-auto operator!=(const Maybe<T>& a, const Maybe<U>& b)
--> decltype(std::declval<T> == std::declval<U>) {
+typename std::enable_if<
+ has_eq_op<T, U>::value,
+ bool
+>::type operator!=(const Maybe<T>& a, const Maybe<U>& b) {
return !(a == b);
}
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index d27b62fd..0ce333a 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -228,20 +228,24 @@
std::unique_ptr<XmlResource> inflate(const void* data, size_t dataLen, IDiagnostics* diag,
const Source& source) {
+ // We import the android namespace because on Windows NO_ERROR is a macro, not an enum, which
+ // causes errors when qualifying it with android::
+ using namespace android;
+
std::unique_ptr<Node> root;
std::stack<Node*> nodeStack;
- android::ResXMLTree tree;
- if (tree.setTo(data, dataLen) != android::NO_ERROR) {
+ ResXMLTree tree;
+ if (tree.setTo(data, dataLen) != NO_ERROR) {
return {};
}
- android::ResXMLParser::event_code_t code;
- while ((code = tree.next()) != android::ResXMLParser::BAD_DOCUMENT &&
- code != android::ResXMLParser::END_DOCUMENT) {
+ ResXMLParser::event_code_t code;
+ while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT &&
+ code != ResXMLParser::END_DOCUMENT) {
std::unique_ptr<Node> newNode;
switch (code) {
- case android::ResXMLParser::START_NAMESPACE: {
+ case ResXMLParser::START_NAMESPACE: {
std::unique_ptr<Namespace> node = util::make_unique<Namespace>();
size_t len;
const char16_t* str16 = tree.getNamespacePrefix(&len);
@@ -257,7 +261,7 @@
break;
}
- case android::ResXMLParser::START_TAG: {
+ case ResXMLParser::START_TAG: {
std::unique_ptr<Element> node = util::make_unique<Element>();
size_t len;
const char16_t* str16 = tree.getElementNamespace(&len);
@@ -276,7 +280,7 @@
break;
}
- case android::ResXMLParser::TEXT: {
+ case ResXMLParser::TEXT: {
std::unique_ptr<Text> node = util::make_unique<Text>();
size_t len;
const char16_t* str16 = tree.getText(&len);
@@ -287,8 +291,8 @@
break;
}
- case android::ResXMLParser::END_NAMESPACE:
- case android::ResXMLParser::END_TAG:
+ case ResXMLParser::END_NAMESPACE:
+ case ResXMLParser::END_TAG:
assert(!nodeStack.empty());
nodeStack.pop();
break;
diff --git a/tools/aapt2/xml/XmlUtil_test.cpp b/tools/aapt2/xml/XmlUtil_test.cpp
index 7796b3e..319e770 100644
--- a/tools/aapt2/xml/XmlUtil_test.cpp
+++ b/tools/aapt2/xml/XmlUtil_test.cpp
@@ -33,22 +33,22 @@
xml::extractPackageFromNamespace(u"http://schemas.android.com/apk/res/a");
AAPT_ASSERT_TRUE(p);
EXPECT_EQ(std::u16string(u"a"), p.value().package);
- EXPECT_EQ(false, p.value().privateNamespace);
+ EXPECT_FALSE(p.value().privateNamespace);
p = xml::extractPackageFromNamespace(u"http://schemas.android.com/apk/prv/res/android");
AAPT_ASSERT_TRUE(p);
EXPECT_EQ(std::u16string(u"android"), p.value().package);
- EXPECT_EQ(true, p.value().privateNamespace);
+ EXPECT_TRUE(p.value().privateNamespace);
p = xml::extractPackageFromNamespace(u"http://schemas.android.com/apk/prv/res/com.test");
AAPT_ASSERT_TRUE(p);
EXPECT_EQ(std::u16string(u"com.test"), p.value().package);
- EXPECT_EQ(true, p.value().privateNamespace);
+ EXPECT_TRUE(p.value().privateNamespace);
p = xml::extractPackageFromNamespace(u"http://schemas.android.com/apk/res-auto");
AAPT_ASSERT_TRUE(p);
EXPECT_EQ(std::u16string(), p.value().package);
- EXPECT_EQ(true, p.value().privateNamespace);
+ EXPECT_TRUE(p.value().privateNamespace);
}
} // namespace aapt
diff --git a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
index 30512aa..ea9a255 100644
--- a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
+++ b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
@@ -44,6 +44,11 @@
private static final float PERPENDICULAR_ANGLE = 90f;
public static void paintShadow(Outline viewOutline, float elevation, Canvas canvas) {
+ Rect outline = new Rect();
+ if (!viewOutline.getRect(outline)) {
+ throw new IllegalArgumentException("Outline is not a rect shadow");
+ }
+
float shadowSize = elevationToShadow(elevation);
int saved = modifyCanvas(canvas, shadowSize);
if (saved == -1) {
@@ -54,8 +59,7 @@
cornerPaint.setStyle(Style.FILL);
Paint edgePaint = new Paint(cornerPaint);
edgePaint.setAntiAlias(false);
- Rect outline = viewOutline.mRect;
- float radius = viewOutline.mRadius;
+ float radius = viewOutline.getRadius();
float outerArcRadius = radius + shadowSize;
int[] colors = {START_COLOR, START_COLOR, END_COLOR};
cornerPaint.setShader(new RadialGradient(0, 0, outerArcRadius, colors,
diff --git a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
index 51d32e3..23caaf8 100644
--- a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
@@ -64,7 +64,7 @@
private static void drawShadow(ViewGroup parent, Canvas canvas, View child,
Outline outline) {
float elevation = getElevation(child, parent);
- if(outline.mRect != null) {
+ if(outline.mMode == Outline.MODE_ROUND_RECT && outline.mRect != null) {
RectShadowPainter.paintShadow(outline, elevation, canvas);
return;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 2399b3a..89272fa 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -639,7 +639,8 @@
}
// Add value to defaultPropsMap if needed
if (typeArrayAndPropertiesPair.getSecond() != null) {
- Object key = getCurrentParser().getViewCookie();
+ BridgeXmlBlockParser parser = getCurrentParser();
+ Object key = parser != null ? parser.getViewCookie() : null;
if (key != null) {
PropertiesMap defaultPropMap = mDefaultPropMaps.get(key);
if (defaultPropMap == null) {
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
index d8ead23..0e788e0c 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
index 65d1dc5..bad296b 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
index 2da2cb9..adb58a3 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
@@ -197,6 +197,14 @@
android:inputType="numberPassword"
android:text="numeric password" />
+ <ToggleButton
+ android:id="@+id/toggleButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignTop="@id/editText4"
+ android:layout_toEndOf="@id/editText4"
+ android:text="New ToggleButton" />
+
<EditText
android:id="@id/editText5"
android:layout_width="wrap_content"
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 034c8b2..8f570ae 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
@@ -31,8 +31,8 @@
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.android.RenderParamsFlags;
-import com.android.layoutlib.bridge.impl.RenderAction;
import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.layoutlib.bridge.impl.RenderAction;
import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
import com.android.layoutlib.bridge.intensive.setup.LayoutLibTestCallback;
import com.android.layoutlib.bridge.intensive.setup.LayoutPullParser;
@@ -42,8 +42,12 @@
import com.android.utils.ILogger;
import org.junit.AfterClass;
+import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -56,9 +60,12 @@
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
+import com.google.android.collect.Lists;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -105,6 +112,21 @@
private static ILogger sLogger;
private static Bridge sBridge;
+ /** List of log messages generated by a render call. It can be used to find specific errors */
+ private static ArrayList<String> sRenderMessages = Lists.newArrayList();
+
+ @Rule
+ public static TestWatcher sRenderMessageWatcher = new TestWatcher() {
+ @Override
+ protected void succeeded(Description description) {
+ // We only check error messages if the rest of the test case was successful.
+ if (!sRenderMessages.isEmpty()) {
+ fail(description.getMethodName() + " render error message: " + sRenderMessages.get
+ (0));
+ }
+ }
+ };
+
static {
// Test that System Properties are properly set.
PLATFORM_DIR = getPlatformDir();
@@ -279,6 +301,11 @@
ConfigGenerator.getEnumMap(attrs), getLayoutLog());
}
+ @Before
+ public void beforeTestCase() {
+ sRenderMessages.clear();
+ }
+
/** Test activity.xml */
@Test
public void testActivity() throws ClassNotFoundException {
@@ -289,6 +316,9 @@
@Test
public void testAllWidgets() throws ClassNotFoundException {
renderAndVerify("allwidgets.xml", "allwidgets.png");
+
+ // We expect fidelity warnings for Path.isConvex. Fail for anything else.
+ sRenderMessages.removeIf(message -> message.equals("Path.isConvex is not supported."));
}
@Test
@@ -299,6 +329,9 @@
@Test
public void testAllWidgetsTablet() throws ClassNotFoundException {
renderAndVerify("allwidgets.xml", "allwidgets_tab.png", ConfigGenerator.NEXUS_7_2012);
+
+ // We expect fidelity warnings for Path.isConvex. Fail for anything else.
+ sRenderMessages.removeIf(message -> message.equals("Path.isConvex is not supported."));
}
private static void gc() {
@@ -649,6 +682,6 @@
}
private static void failWithMsg(@NonNull String msgFormat, Object... args) {
- fail(args == null ? "" : String.format(msgFormat, args));
+ sRenderMessages.add(args == null ? msgFormat : String.format(msgFormat, args));
}
}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 1c7a308..0f84506 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -149,12 +149,11 @@
void setAllowScansWithTraffic(int enabled);
int getAllowScansWithTraffic();
- void setHalBasedAutojoinOffload(int enabled);
- int getHalBasedAutojoinOffload();
-
boolean enableAutoJoinWhenAssociated(boolean enabled);
boolean getEnableAutoJoinWhenAssociated();
+ void enableWifiConnectivityManager(boolean enabled);
+
WifiConnectionStatistics getConnectionStatistics();
void disableEphemeralNetwork(String SSID);
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 9e15d60..394934f 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -719,7 +719,7 @@
* Get CA certificates.
*/
@Nullable public X509Certificate[] getCaCertificates() {
- if (mCaCerts != null || mCaCerts.length > 0) {
+ if (mCaCerts != null && mCaCerts.length > 0) {
return mCaCerts;
} else {
return null;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 8c1fbc3..6984fe2 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -28,7 +28,6 @@
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
-import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
@@ -43,7 +42,6 @@
import com.android.server.net.NetworkPinner;
import java.net.InetAddress;
-import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
@@ -2721,25 +2719,14 @@
throw e.rethrowFromSystemServer();
}
}
- /**
- * Set setting for enabling autojoin Offload thru Wifi HAL layer
- * @hide
- */
- public void setHalBasedAutojoinOffload(int enabled) {
- try {
- mService.setHalBasedAutojoinOffload(enabled);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
/**
- * Get setting for enabling autojoin Offload thru Wifi HAL layer
+ * Enable/disable WifiConnectivityManager
* @hide
*/
- public int getHalBasedAutojoinOffload() {
+ public void enableWifiConnectivityManager(boolean enabled) {
try {
- return mService.getHalBasedAutojoinOffload();
+ mService.enableWifiConnectivityManager(enabled);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 73ddbbc..f8c1ea3 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -810,19 +810,17 @@
}
/**
* 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) {
+ public void stopPnoScan(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);
+ sAsyncChannel.sendMessage(CMD_STOP_PNO_SCAN, 0, key);
}
/** specifies information about an access point of interest */