Merge "ExifInterface: return only a JPEG-compressed thumbnail of RAW images" into nyc-dev
diff --git a/Android.mk b/Android.mk
index ae5d67e..2017404 100644
--- a/Android.mk
+++ b/Android.mk
@@ -442,8 +442,6 @@
telephony/java/com/android/internal/telephony/ISms.aidl \
telephony/java/com/android/internal/telephony/ISub.aidl \
telephony/java/com/android/internal/telephony/ITelephony.aidl \
- telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl \
- telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl \
telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
wifi/java/android/net/wifi/IWifiManager.aidl \
diff --git a/api/current.txt b/api/current.txt
index 3444597..f924b5b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -891,6 +891,7 @@
field public static final int notificationTimeout = 16843651; // 0x1010383
field public static final int numColumns = 16843032; // 0x1010118
field public static final int numStars = 16843076; // 0x1010144
+ field public static final int numberPickerStyle = 16844071; // 0x1010527
field public static final int numbersBackgroundColor = 16843938; // 0x10104a2
field public static final int numbersInnerTextColor = 16844001; // 0x10104e1
field public static final int numbersSelectorColor = 16843939; // 0x10104a3
@@ -2534,6 +2535,7 @@
field public static final int Widget_Material_Light_ListView = 16974513; // 0x10302b1
field public static final int Widget_Material_Light_ListView_DropDown = 16974514; // 0x10302b2
field public static final int Widget_Material_Light_MediaRouteButton = 16974515; // 0x10302b3
+ field public static final int Widget_Material_Light_NumberPicker = 16974557; // 0x10302dd
field public static final int Widget_Material_Light_PopupMenu = 16974516; // 0x10302b4
field public static final int Widget_Material_Light_PopupMenu_Overflow = 16974517; // 0x10302b5
field public static final int Widget_Material_Light_PopupWindow = 16974518; // 0x10302b6
@@ -2566,6 +2568,7 @@
field public static final int Widget_Material_ListView = 16974448; // 0x1030270
field public static final int Widget_Material_ListView_DropDown = 16974449; // 0x1030271
field public static final int Widget_Material_MediaRouteButton = 16974450; // 0x1030272
+ field public static final int Widget_Material_NumberPicker = 16974556; // 0x10302dc
field public static final int Widget_Material_PopupMenu = 16974451; // 0x1030273
field public static final int Widget_Material_PopupMenu_Overflow = 16974452; // 0x1030274
field public static final int Widget_Material_PopupWindow = 16974453; // 0x1030275
@@ -3578,6 +3581,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);
@@ -4479,6 +4483,7 @@
method public void startActivity(android.content.Intent, android.os.Bundle);
method public void startActivityForResult(android.content.Intent, int);
method public void startActivityForResult(android.content.Intent, int, android.os.Bundle);
+ method public void startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
method public void unregisterForContextMenu(android.view.View);
}
@@ -4570,6 +4575,7 @@
method public void onRequestPermissionsFromFragment(android.app.Fragment, java.lang.String[], int);
method public boolean onShouldSaveFragmentState(android.app.Fragment);
method public void onStartActivityFromFragment(android.app.Fragment, android.content.Intent, int, android.os.Bundle);
+ method public void onStartIntentSenderFromFragment(android.app.Fragment, android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
method public boolean onUseFragmentManagerInflaterFactory();
}
@@ -5030,13 +5036,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 boolean getHintLaunchesActivity();
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 setHintLaunchesActivity(boolean);
method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence);
}
@@ -5896,11 +5902,11 @@
method public java.lang.CharSequence getDeviceOwnerLockScreenInfo();
method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
method public int getKeyguardDisabledFeatures(android.content.ComponentName);
- method public java.lang.String getLongSupportMessage(android.content.ComponentName);
+ method public java.lang.CharSequence getLongSupportMessage(android.content.ComponentName);
method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
method public long getMaximumTimeToLock(android.content.ComponentName);
method public int getOrganizationColor(android.content.ComponentName);
- method public java.lang.String getOrganizationName(android.content.ComponentName);
+ method public java.lang.CharSequence getOrganizationName(android.content.ComponentName);
method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
method public long getPasswordExpiration(android.content.ComponentName);
method public long getPasswordExpirationTimeout(android.content.ComponentName);
@@ -5919,7 +5925,7 @@
method public java.util.List<java.lang.String> getPermittedAccessibilityServices(android.content.ComponentName);
method public java.util.List<java.lang.String> getPermittedInputMethods(android.content.ComponentName);
method public boolean getScreenCaptureDisabled(android.content.ComponentName);
- method public java.lang.String getShortSupportMessage(android.content.ComponentName);
+ method public java.lang.CharSequence getShortSupportMessage(android.content.ComponentName);
method public boolean getStorageEncryption(android.content.ComponentName);
method public int getStorageEncryptionStatus();
method public android.app.admin.SystemUpdatePolicy getSystemUpdatePolicy();
@@ -5970,12 +5976,12 @@
method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException;
- method public void setLongSupportMessage(android.content.ComponentName, java.lang.String);
+ method public void setLongSupportMessage(android.content.ComponentName, java.lang.CharSequence);
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
method public void setMaximumTimeToLock(android.content.ComponentName, long);
method public void setOrganizationColor(android.content.ComponentName, int);
- method public void setOrganizationName(android.content.ComponentName, java.lang.String);
+ method public void setOrganizationName(android.content.ComponentName, java.lang.CharSequence);
method public java.lang.String[] setPackagesSuspended(android.content.ComponentName, java.lang.String[], boolean);
method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
method public void setPasswordHistoryLength(android.content.ComponentName, int);
@@ -5998,7 +6004,7 @@
method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean);
- method public void setShortSupportMessage(android.content.ComponentName, java.lang.String);
+ method public void setShortSupportMessage(android.content.ComponentName, java.lang.CharSequence);
method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
method public int setStorageEncryption(android.content.ComponentName, boolean);
method public void setSystemUpdatePolicy(android.content.ComponentName, android.app.admin.SystemUpdatePolicy);
@@ -6312,6 +6318,8 @@
method public static final long getMinimumPeriod();
method public int getNetworkType();
method public android.content.ComponentName getService();
+ method public long getTriggerContentMaxDelay();
+ method public long getTriggerContentUpdateDelay();
method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
method public boolean isPeriodic();
method public boolean isPersisted();
@@ -6342,6 +6350,8 @@
method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean);
+ method public android.app.job.JobInfo.Builder setTriggerContentMaxDelay(long);
+ method public android.app.job.JobInfo.Builder setTriggerContentUpdateDelay(long);
}
public static final class JobInfo.TriggerContentUri implements android.os.Parcelable {
@@ -8614,6 +8624,7 @@
field public static final java.lang.String ACTION_SENDTO = "android.intent.action.SENDTO";
field public static final java.lang.String ACTION_SEND_MULTIPLE = "android.intent.action.SEND_MULTIPLE";
field public static final java.lang.String ACTION_SET_WALLPAPER = "android.intent.action.SET_WALLPAPER";
+ field public static final java.lang.String ACTION_SHOW_APP_INFO = "android.intent.action.SHOW_APP_INFO";
field public static final java.lang.String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";
field public static final java.lang.String ACTION_SYNC = "android.intent.action.SYNC";
field public static final java.lang.String ACTION_SYSTEM_TUTORIAL = "android.intent.action.SYSTEM_TUTORIAL";
@@ -8708,6 +8719,7 @@
field public static final java.lang.String EXTRA_MIME_TYPES = "android.intent.extra.MIME_TYPES";
field public static final java.lang.String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
field public static final java.lang.String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
+ field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";
field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
field public static final java.lang.String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT";
field public static final java.lang.String EXTRA_PROCESS_TEXT_READONLY = "android.intent.extra.PROCESS_TEXT_READONLY";
@@ -9496,10 +9508,8 @@
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 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);
@@ -9511,6 +9521,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);
}
@@ -9532,6 +9543,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
@@ -10038,13 +10050,16 @@
public final class ShortcutInfo implements android.os.Parcelable {
method public int describeContents();
method public android.content.ComponentName getActivityComponent();
+ method public java.util.List<java.lang.String> getCategories();
method public android.os.PersistableBundle getExtras();
+ method public int getIconResourceId();
method public java.lang.String getId();
method public android.content.Intent getIntent();
method public long getLastChangedTimestamp();
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();
@@ -10061,12 +10076,14 @@
field public static final int FLAG_HAS_ICON_RES = 4; // 0x4
field public static final int FLAG_KEY_FIELDS_ONLY = 16; // 0x10
field public static final int FLAG_PINNED = 2; // 0x2
+ field public static final java.lang.String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation";
}
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivityComponent(android.content.ComponentName);
+ method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.List<java.lang.String>);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
method public android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
@@ -10077,15 +10094,15 @@
}
public class ShortcutManager {
- method public boolean addDynamicShortcut(android.content.pm.ShortcutInfo);
- method public void deleteAllDynamicShortcuts();
- method public void deleteDynamicShortcut(java.lang.String);
+ method public boolean addDynamicShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
method public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
method public int getIconMaxDimensions();
method public int getMaxDynamicShortcutCount();
method public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
method public long getRateLimitResetTime();
method public int getRemainingCallCount();
+ method public void removeAllDynamicShortcuts();
+ method public void removeDynamicShortcuts(java.util.List<java.lang.String>);
method public boolean setDynamicShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
method public boolean updateShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
}
@@ -14431,13 +14448,13 @@
public final class OutputConfiguration implements android.os.Parcelable {
ctor public OutputConfiguration(android.view.Surface);
+ ctor public OutputConfiguration(int, android.view.Surface);
method public int describeContents();
method public android.view.Surface getSurface();
- method public int getSurfaceSetId();
- method public void setSurfaceSetId(int);
+ method public int getSurfaceGroupId();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.hardware.camera2.params.OutputConfiguration> CREATOR;
- field public static final int SURFACE_SET_ID_INVALID = -1; // 0xffffffff
+ field public static final int SURFACE_GROUP_ID_NONE = -1; // 0xffffffff
}
public final class RggbChannelVector {
@@ -19852,8 +19869,8 @@
public class AudioRecord implements android.media.AudioRouting {
ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException;
+ method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener, android.os.Handler);
- method public void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public int getAudioFormat();
method public int getAudioSessionId();
method public int getAudioSource();
@@ -19878,8 +19895,8 @@
method public int read(java.nio.ByteBuffer, int);
method public int read(java.nio.ByteBuffer, int, int);
method public void release();
+ method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
method public deprecated void removeOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener);
- method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
method public int setNotificationMarkerPosition(int);
method public int setPositionNotificationPeriod(int);
method public boolean setPreferredDevice(android.media.AudioDeviceInfo);
@@ -19913,8 +19930,9 @@
method public abstract void onPeriodicNotification(android.media.AudioRecord);
}
- public static abstract interface AudioRecord.OnRoutingChangedListener {
+ public static abstract deprecated interface AudioRecord.OnRoutingChangedListener implements android.media.AudioRouting.OnRoutingChangedListener {
method public abstract void onRoutingChanged(android.media.AudioRecord);
+ method public default void onRoutingChanged(android.media.AudioRouting);
}
public final class AudioRecordingConfiguration implements android.os.Parcelable {
@@ -19929,10 +19947,10 @@
}
public abstract interface AudioRouting {
- method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
+ method public abstract void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public abstract android.media.AudioDeviceInfo getPreferredDevice();
method public abstract android.media.AudioDeviceInfo getRoutedDevice();
- method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
+ method public abstract void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo);
}
@@ -19952,8 +19970,8 @@
ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
+ method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
- method public void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public int attachAuxEffect(int);
method public void flush();
method public int getAudioFormat();
@@ -19985,8 +20003,8 @@
method public void play() throws java.lang.IllegalStateException;
method public void release();
method public int reloadStaticData();
+ method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
method public deprecated void removeOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener);
- method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
method public int setAuxEffectSendLevel(float);
method public int setBufferSizeInFrames(int);
method public int setLoopPoints(int, int, int);
@@ -20040,8 +20058,9 @@
method public abstract void onPeriodicNotification(android.media.AudioTrack);
}
- public static abstract deprecated interface AudioTrack.OnRoutingChangedListener {
- method public abstract deprecated void onRoutingChanged(android.media.AudioTrack);
+ public static abstract deprecated interface AudioTrack.OnRoutingChangedListener implements android.media.AudioRouting.OnRoutingChangedListener {
+ method public abstract void onRoutingChanged(android.media.AudioTrack);
+ method public default void onRoutingChanged(android.media.AudioRouting);
}
public class CamcorderProfile {
@@ -20717,10 +20736,12 @@
field public static final int VP9Level6 = 1024; // 0x400
field public static final int VP9Level61 = 2048; // 0x800
field public static final int VP9Level62 = 4096; // 0x1000
- field public static final int VP9Profile0 = 0; // 0x0
- field public static final int VP9Profile1 = 1; // 0x1
- field public static final int VP9Profile2 = 2; // 0x2
- field public static final int VP9Profile3 = 3; // 0x3
+ field public static final int VP9Profile0 = 1; // 0x1
+ field public static final int VP9Profile1 = 2; // 0x2
+ field public static final int VP9Profile2 = 4; // 0x4
+ field public static final int VP9Profile2HDR = 4096; // 0x1000
+ field public static final int VP9Profile3 = 8; // 0x8
+ field public static final int VP9Profile3HDR = 8192; // 0x2000
field public int level;
field public int profile;
}
@@ -22877,6 +22898,7 @@
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+ field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
@@ -22957,6 +22979,7 @@
method public android.content.Intent createSettingsIntent();
method public android.content.Intent createSetupIntent();
method public int describeContents();
+ method public android.os.Bundle getExtras();
method public java.lang.String getId();
method public java.lang.String getParentId();
method public android.content.pm.ServiceInfo getServiceInfo();
@@ -22986,6 +23009,7 @@
ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName);
method public android.media.tv.TvInputInfo build() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean);
+ method public android.media.tv.TvInputInfo.Builder setExtras(android.os.Bundle);
method public android.media.tv.TvInputInfo.Builder setTunerCount(int);
}
@@ -29575,6 +29599,7 @@
public class StorageManager {
method public java.lang.String getMountedObbPath(java.lang.String);
method public android.os.storage.StorageVolume getPrimaryStorageVolume();
+ method public android.os.storage.StorageVolume getStorageVolume(java.io.File);
method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes();
method public boolean isEncrypted(java.io.File);
method public boolean isObbMounted(java.lang.String);
@@ -34936,6 +34961,7 @@
method public void onDestroy();
method public boolean[] onGetSupportedCommands(java.lang.String[]);
method public void onHandleAssist(android.os.Bundle, android.app.assist.AssistStructure, android.app.assist.AssistContent);
+ method public void onHandleAssistSecondary(android.os.Bundle, android.app.assist.AssistStructure, android.app.assist.AssistContent, int, int);
method public void onHandleScreenshot(android.graphics.Bitmap);
method public void onHide();
method public boolean onKeyDown(int, android.view.KeyEvent);
@@ -49052,6 +49078,7 @@
ctor public BufferedReader(java.io.Reader, int);
ctor public BufferedReader(java.io.Reader);
method public void close() throws java.io.IOException;
+ method public java.util.stream.Stream<java.lang.String> lines();
method public int read(char[], int, int) throws java.io.IOException;
method public java.lang.String readLine() throws java.io.IOException;
}
@@ -49922,6 +49949,11 @@
ctor public UTFDataFormatException(java.lang.String);
}
+ public class UncheckedIOException extends java.lang.RuntimeException {
+ ctor public UncheckedIOException(java.lang.String, java.io.IOException);
+ ctor public UncheckedIOException(java.io.IOException);
+ }
+
public class UnsupportedEncodingException extends java.io.IOException {
ctor public UnsupportedEncodingException();
ctor public UnsupportedEncodingException(java.lang.String);
@@ -57578,6 +57610,7 @@
method public void set(int, int);
method public void set(int, int, boolean);
method public int size();
+ method public java.util.stream.IntStream stream();
method public byte[] toByteArray();
method public long[] toLongArray();
method public static java.util.BitSet valueOf(long[]);
@@ -58033,6 +58066,7 @@
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
method public boolean replace(K, V, V);
+ method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
}
public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
@@ -58076,6 +58110,7 @@
method public synchronized boolean remove(java.lang.Object, java.lang.Object);
method public synchronized boolean replace(K, V, V);
method public synchronized V replace(K, V);
+ method public synchronized void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
method public synchronized int size();
method public java.util.Collection<V> values();
}
@@ -58616,6 +58651,18 @@
public class Random implements java.io.Serializable {
ctor public Random();
ctor public Random(long);
+ method public java.util.stream.DoubleStream doubles(long);
+ method public java.util.stream.DoubleStream doubles();
+ method public java.util.stream.DoubleStream doubles(long, double, double);
+ method public java.util.stream.DoubleStream doubles(double, double);
+ method public java.util.stream.IntStream ints(long);
+ method public java.util.stream.IntStream ints();
+ method public java.util.stream.IntStream ints(long, int, int);
+ method public java.util.stream.IntStream ints(int, int);
+ method public java.util.stream.LongStream longs(long);
+ method public java.util.stream.LongStream longs();
+ method public java.util.stream.LongStream longs(long, long, long);
+ method public java.util.stream.LongStream longs(long, long);
method protected int next(int);
method public boolean nextBoolean();
method public void nextBytes(byte[]);
@@ -59057,6 +59104,7 @@
method public java.util.NavigableSet<K> navigableKeySet();
method public java.util.Map.Entry<K, V> pollFirstEntry();
method public java.util.Map.Entry<K, V> pollLastEntry();
+ method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
method public java.util.NavigableMap<K, V> subMap(K, boolean, K, boolean);
method public java.util.SortedMap<K, V> subMap(K, K);
method public java.util.NavigableMap<K, V> tailMap(K, boolean);
@@ -59158,6 +59206,7 @@
ctor public WeakHashMap(java.util.Map<? extends K, ? extends V>);
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+ method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
}
}
@@ -60131,18 +60180,6 @@
public class ThreadLocalRandom extends java.util.Random {
method public static java.util.concurrent.ThreadLocalRandom current();
- method public java.util.stream.DoubleStream doubles(long);
- method public java.util.stream.DoubleStream doubles();
- method public java.util.stream.DoubleStream doubles(long, double, double);
- method public java.util.stream.DoubleStream doubles(double, double);
- method public java.util.stream.IntStream ints(long);
- method public java.util.stream.IntStream ints();
- method public java.util.stream.IntStream ints(long, int, int);
- method public java.util.stream.IntStream ints(int, int);
- method public java.util.stream.LongStream longs(long);
- method public java.util.stream.LongStream longs();
- method public java.util.stream.LongStream longs(long, long, long);
- method public java.util.stream.LongStream longs(long, long);
method public double nextDouble(double);
method public double nextDouble(double, double);
method public int nextInt(int, int);
@@ -61515,6 +61552,7 @@
}
public final class Pattern implements java.io.Serializable {
+ method public java.util.function.Predicate<java.lang.String> asPredicate();
method public static java.util.regex.Pattern compile(java.lang.String);
method public static java.util.regex.Pattern compile(java.lang.String, int) throws java.util.regex.PatternSyntaxException;
method public int flags();
@@ -61524,6 +61562,7 @@
method public static java.lang.String quote(java.lang.String);
method public java.lang.String[] split(java.lang.CharSequence, int);
method public java.lang.String[] split(java.lang.CharSequence);
+ method public java.util.stream.Stream<java.lang.String> splitAsStream(java.lang.CharSequence);
field public static final int CANON_EQ = 128; // 0x80
field public static final int CASE_INSENSITIVE = 2; // 0x2
field public static final int COMMENTS = 4; // 0x4
diff --git a/api/system-current.txt b/api/system-current.txt
index a4927f2..915ceb2 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -217,6 +217,7 @@
field public static final java.lang.String SIGNAL_PERSISTENT_PROCESSES = "android.permission.SIGNAL_PERSISTENT_PROCESSES";
field public static final java.lang.String STATUS_BAR = "android.permission.STATUS_BAR";
field public static final java.lang.String STOP_APP_SWITCHES = "android.permission.STOP_APP_SWITCHES";
+ field public static final java.lang.String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME";
field public static final java.lang.String SYSTEM_ALERT_WINDOW = "android.permission.SYSTEM_ALERT_WINDOW";
field public static final java.lang.String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED";
field public static final java.lang.String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
@@ -987,6 +988,7 @@
field public static final int notificationTimeout = 16843651; // 0x1010383
field public static final int numColumns = 16843032; // 0x1010118
field public static final int numStars = 16843076; // 0x1010144
+ field public static final int numberPickerStyle = 16844071; // 0x1010527
field public static final int numbersBackgroundColor = 16843938; // 0x10104a2
field public static final int numbersInnerTextColor = 16844001; // 0x10104e1
field public static final int numbersSelectorColor = 16843939; // 0x10104a3
@@ -2637,6 +2639,7 @@
field public static final int Widget_Material_Light_ListView = 16974513; // 0x10302b1
field public static final int Widget_Material_Light_ListView_DropDown = 16974514; // 0x10302b2
field public static final int Widget_Material_Light_MediaRouteButton = 16974515; // 0x10302b3
+ field public static final int Widget_Material_Light_NumberPicker = 16974557; // 0x10302dd
field public static final int Widget_Material_Light_PopupMenu = 16974516; // 0x10302b4
field public static final int Widget_Material_Light_PopupMenu_Overflow = 16974517; // 0x10302b5
field public static final int Widget_Material_Light_PopupWindow = 16974518; // 0x10302b6
@@ -2669,6 +2672,7 @@
field public static final int Widget_Material_ListView = 16974448; // 0x1030270
field public static final int Widget_Material_ListView_DropDown = 16974449; // 0x1030271
field public static final int Widget_Material_MediaRouteButton = 16974450; // 0x1030272
+ field public static final int Widget_Material_NumberPicker = 16974556; // 0x10302dc
field public static final int Widget_Material_PopupMenu = 16974451; // 0x1030273
field public static final int Widget_Material_PopupMenu_Overflow = 16974452; // 0x1030274
field public static final int Widget_Material_PopupWindow = 16974453; // 0x1030275
@@ -3696,6 +3700,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);
@@ -4612,6 +4617,7 @@
method public void startActivity(android.content.Intent, android.os.Bundle);
method public void startActivityForResult(android.content.Intent, int);
method public void startActivityForResult(android.content.Intent, int, android.os.Bundle);
+ method public void startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
method public void unregisterForContextMenu(android.view.View);
}
@@ -4703,6 +4709,7 @@
method public void onRequestPermissionsFromFragment(android.app.Fragment, java.lang.String[], int);
method public boolean onShouldSaveFragmentState(android.app.Fragment);
method public void onStartActivityFromFragment(android.app.Fragment, android.content.Intent, int, android.os.Bundle);
+ method public void onStartIntentSenderFromFragment(android.app.Fragment, android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
method public boolean onUseFragmentManagerInflaterFactory();
}
@@ -5164,13 +5171,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 boolean getHintLaunchesActivity();
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 setHintLaunchesActivity(boolean);
method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence);
}
@@ -6039,11 +6046,11 @@
method public java.lang.String getDeviceOwnerNameOnAnyUser();
method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
method public int getKeyguardDisabledFeatures(android.content.ComponentName);
- method public java.lang.String getLongSupportMessage(android.content.ComponentName);
+ method public java.lang.CharSequence getLongSupportMessage(android.content.ComponentName);
method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
method public long getMaximumTimeToLock(android.content.ComponentName);
method public int getOrganizationColor(android.content.ComponentName);
- method public java.lang.String getOrganizationName(android.content.ComponentName);
+ method public java.lang.CharSequence getOrganizationName(android.content.ComponentName);
method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
method public long getPasswordExpiration(android.content.ComponentName);
method public long getPasswordExpirationTimeout(android.content.ComponentName);
@@ -6066,7 +6073,7 @@
method public android.content.ComponentName getProfileOwner() throws java.lang.IllegalArgumentException;
method public java.lang.String getProfileOwnerNameAsUser(int) throws java.lang.IllegalArgumentException;
method public boolean getScreenCaptureDisabled(android.content.ComponentName);
- method public java.lang.String getShortSupportMessage(android.content.ComponentName);
+ method public java.lang.CharSequence getShortSupportMessage(android.content.ComponentName);
method public boolean getStorageEncryption(android.content.ComponentName);
method public int getStorageEncryptionStatus();
method public android.app.admin.SystemUpdatePolicy getSystemUpdatePolicy();
@@ -6120,12 +6127,12 @@
method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException;
- method public void setLongSupportMessage(android.content.ComponentName, java.lang.String);
+ method public void setLongSupportMessage(android.content.ComponentName, java.lang.CharSequence);
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
method public void setMaximumTimeToLock(android.content.ComponentName, long);
method public void setOrganizationColor(android.content.ComponentName, int);
- method public void setOrganizationName(android.content.ComponentName, java.lang.String);
+ method public void setOrganizationName(android.content.ComponentName, java.lang.CharSequence);
method public java.lang.String[] setPackagesSuspended(android.content.ComponentName, java.lang.String[], boolean);
method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
method public void setPasswordHistoryLength(android.content.ComponentName, int);
@@ -6148,7 +6155,7 @@
method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean);
- method public void setShortSupportMessage(android.content.ComponentName, java.lang.String);
+ method public void setShortSupportMessage(android.content.ComponentName, java.lang.CharSequence);
method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
method public int setStorageEncryption(android.content.ComponentName, boolean);
method public void setSystemUpdatePolicy(android.content.ComponentName, android.app.admin.SystemUpdatePolicy);
@@ -6580,6 +6587,8 @@
method public static final long getMinimumPeriod();
method public int getNetworkType();
method public android.content.ComponentName getService();
+ method public long getTriggerContentMaxDelay();
+ method public long getTriggerContentUpdateDelay();
method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
method public boolean isPeriodic();
method public boolean isPersisted();
@@ -6610,6 +6619,8 @@
method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean);
+ method public android.app.job.JobInfo.Builder setTriggerContentMaxDelay(long);
+ method public android.app.job.JobInfo.Builder setTriggerContentUpdateDelay(long);
}
public static final class JobInfo.TriggerContentUri implements android.os.Parcelable {
@@ -8933,6 +8944,7 @@
field public static final java.lang.String ACTION_SENDTO = "android.intent.action.SENDTO";
field public static final java.lang.String ACTION_SEND_MULTIPLE = "android.intent.action.SEND_MULTIPLE";
field public static final java.lang.String ACTION_SET_WALLPAPER = "android.intent.action.SET_WALLPAPER";
+ field public static final java.lang.String ACTION_SHOW_APP_INFO = "android.intent.action.SHOW_APP_INFO";
field public static final java.lang.String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";
field public static final java.lang.String ACTION_SYNC = "android.intent.action.SYNC";
field public static final java.lang.String ACTION_SYSTEM_TUTORIAL = "android.intent.action.SYSTEM_TUTORIAL";
@@ -9834,10 +9846,8 @@
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 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);
@@ -9849,6 +9859,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);
}
@@ -9870,6 +9881,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
@@ -10438,13 +10450,16 @@
public final class ShortcutInfo implements android.os.Parcelable {
method public int describeContents();
method public android.content.ComponentName getActivityComponent();
+ method public java.util.List<java.lang.String> getCategories();
method public android.os.PersistableBundle getExtras();
+ method public int getIconResourceId();
method public java.lang.String getId();
method public android.content.Intent getIntent();
method public long getLastChangedTimestamp();
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();
@@ -10461,12 +10476,14 @@
field public static final int FLAG_HAS_ICON_RES = 4; // 0x4
field public static final int FLAG_KEY_FIELDS_ONLY = 16; // 0x10
field public static final int FLAG_PINNED = 2; // 0x2
+ field public static final java.lang.String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation";
}
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivityComponent(android.content.ComponentName);
+ method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.List<java.lang.String>);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
method public android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
@@ -10477,15 +10494,15 @@
}
public class ShortcutManager {
- method public boolean addDynamicShortcut(android.content.pm.ShortcutInfo);
- method public void deleteAllDynamicShortcuts();
- method public void deleteDynamicShortcut(java.lang.String);
+ method public boolean addDynamicShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
method public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
method public int getIconMaxDimensions();
method public int getMaxDynamicShortcutCount();
method public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
method public long getRateLimitResetTime();
method public int getRemainingCallCount();
+ method public void removeAllDynamicShortcuts();
+ method public void removeDynamicShortcuts(java.util.List<java.lang.String>);
method public boolean setDynamicShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
method public boolean updateShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
}
@@ -14839,20 +14856,20 @@
public final class OutputConfiguration implements android.os.Parcelable {
ctor public OutputConfiguration(android.view.Surface);
+ ctor public OutputConfiguration(int, android.view.Surface);
ctor public OutputConfiguration(android.view.Surface, int);
- ctor public OutputConfiguration(android.hardware.camera2.params.OutputConfiguration);
+ ctor public OutputConfiguration(int, android.view.Surface, int);
method public int describeContents();
method public int getRotation();
method public android.view.Surface getSurface();
- method public int getSurfaceSetId();
- method public void setSurfaceSetId(int);
+ method public int getSurfaceGroupId();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.hardware.camera2.params.OutputConfiguration> CREATOR;
field public static final int ROTATION_0 = 0; // 0x0
field public static final int ROTATION_180 = 2; // 0x2
field public static final int ROTATION_270 = 3; // 0x3
field public static final int ROTATION_90 = 1; // 0x1
- field public static final int SURFACE_SET_ID_INVALID = -1; // 0xffffffff
+ field public static final int SURFACE_GROUP_ID_NONE = -1; // 0xffffffff
}
public final class RggbChannelVector {
@@ -15490,6 +15507,7 @@
public class NanoApp {
ctor public NanoApp();
+ ctor public NanoApp(int, byte[]);
method public int describeContents();
method public byte[] getAppBinary();
method public int getAppId();
@@ -21330,8 +21348,8 @@
public class AudioRecord implements android.media.AudioRouting {
ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioRecord(android.media.AudioAttributes, android.media.AudioFormat, int, int) throws java.lang.IllegalArgumentException;
+ method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener, android.os.Handler);
- method public void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public int getAudioFormat();
method public int getAudioSessionId();
method public int getAudioSource();
@@ -21356,8 +21374,8 @@
method public int read(java.nio.ByteBuffer, int);
method public int read(java.nio.ByteBuffer, int, int);
method public void release();
+ method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
method public deprecated void removeOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener);
- method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
method public int setNotificationMarkerPosition(int);
method public int setPositionNotificationPeriod(int);
method public boolean setPreferredDevice(android.media.AudioDeviceInfo);
@@ -21393,8 +21411,9 @@
method public abstract void onPeriodicNotification(android.media.AudioRecord);
}
- public static abstract interface AudioRecord.OnRoutingChangedListener {
+ public static abstract deprecated interface AudioRecord.OnRoutingChangedListener implements android.media.AudioRouting.OnRoutingChangedListener {
method public abstract void onRoutingChanged(android.media.AudioRecord);
+ method public default void onRoutingChanged(android.media.AudioRouting);
}
public final class AudioRecordingConfiguration implements android.os.Parcelable {
@@ -21409,10 +21428,10 @@
}
public abstract interface AudioRouting {
- method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
+ method public abstract void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public abstract android.media.AudioDeviceInfo getPreferredDevice();
method public abstract android.media.AudioDeviceInfo getRoutedDevice();
- method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
+ method public abstract void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo);
}
@@ -21432,8 +21451,8 @@
ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
+ method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
- method public void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public int attachAuxEffect(int);
method public void flush();
method public int getAudioFormat();
@@ -21465,8 +21484,8 @@
method public void play() throws java.lang.IllegalStateException;
method public void release();
method public int reloadStaticData();
+ method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
method public deprecated void removeOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener);
- method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
method public int setAuxEffectSendLevel(float);
method public int setBufferSizeInFrames(int);
method public int setLoopPoints(int, int, int);
@@ -21520,8 +21539,9 @@
method public abstract void onPeriodicNotification(android.media.AudioTrack);
}
- public static abstract deprecated interface AudioTrack.OnRoutingChangedListener {
- method public abstract deprecated void onRoutingChanged(android.media.AudioTrack);
+ public static abstract deprecated interface AudioTrack.OnRoutingChangedListener implements android.media.AudioRouting.OnRoutingChangedListener {
+ method public abstract void onRoutingChanged(android.media.AudioTrack);
+ method public default void onRoutingChanged(android.media.AudioRouting);
}
public class CamcorderProfile {
@@ -22197,10 +22217,12 @@
field public static final int VP9Level6 = 1024; // 0x400
field public static final int VP9Level61 = 2048; // 0x800
field public static final int VP9Level62 = 4096; // 0x1000
- field public static final int VP9Profile0 = 0; // 0x0
- field public static final int VP9Profile1 = 1; // 0x1
- field public static final int VP9Profile2 = 2; // 0x2
- field public static final int VP9Profile3 = 3; // 0x3
+ field public static final int VP9Profile0 = 1; // 0x1
+ field public static final int VP9Profile1 = 2; // 0x2
+ field public static final int VP9Profile2 = 4; // 0x4
+ field public static final int VP9Profile2HDR = 4096; // 0x1000
+ field public static final int VP9Profile3 = 8; // 0x8
+ field public static final int VP9Profile3HDR = 8192; // 0x2000
field public int level;
field public int profile;
}
@@ -24482,6 +24504,7 @@
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+ field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
@@ -24613,6 +24636,7 @@
method public static deprecated android.media.tv.TvInputInfo createTvInputInfo(android.content.Context, android.content.pm.ResolveInfo, android.media.tv.TvInputHardwareInfo, java.lang.String, android.net.Uri) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static deprecated android.media.tv.TvInputInfo createTvInputInfo(android.content.Context, android.content.pm.ResolveInfo, android.media.tv.TvInputHardwareInfo, int, android.graphics.drawable.Icon) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public int describeContents();
+ method public android.os.Bundle getExtras();
method public android.hardware.hdmi.HdmiDeviceInfo getHdmiDeviceInfo();
method public java.lang.String getId();
method public java.lang.String getParentId();
@@ -24646,6 +24670,7 @@
ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName);
method public android.media.tv.TvInputInfo build() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean);
+ method public android.media.tv.TvInputInfo.Builder setExtras(android.os.Bundle);
method public android.media.tv.TvInputInfo.Builder setHdmiDeviceInfo(android.hardware.hdmi.HdmiDeviceInfo);
method public android.media.tv.TvInputInfo.Builder setIcon(android.graphics.drawable.Icon);
method public android.media.tv.TvInputInfo.Builder setIcon(android.graphics.drawable.Icon, int);
@@ -31880,6 +31905,7 @@
public class StorageManager {
method public java.lang.String getMountedObbPath(java.lang.String);
method public android.os.storage.StorageVolume getPrimaryStorageVolume();
+ method public android.os.storage.StorageVolume getStorageVolume(java.io.File);
method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes();
method public boolean isEncrypted(java.io.File);
method public boolean isObbMounted(java.lang.String);
@@ -37509,6 +37535,7 @@
method public void onDestroy();
method public boolean[] onGetSupportedCommands(java.lang.String[]);
method public void onHandleAssist(android.os.Bundle, android.app.assist.AssistStructure, android.app.assist.AssistContent);
+ method public void onHandleAssistSecondary(android.os.Bundle, android.app.assist.AssistStructure, android.app.assist.AssistContent, int, int);
method public void onHandleScreenshot(android.graphics.Bitmap);
method public void onHide();
method public boolean onKeyDown(int, android.view.KeyEvent);
@@ -52164,6 +52191,7 @@
ctor public BufferedReader(java.io.Reader, int);
ctor public BufferedReader(java.io.Reader);
method public void close() throws java.io.IOException;
+ method public java.util.stream.Stream<java.lang.String> lines();
method public int read(char[], int, int) throws java.io.IOException;
method public java.lang.String readLine() throws java.io.IOException;
}
@@ -53034,6 +53062,11 @@
ctor public UTFDataFormatException(java.lang.String);
}
+ public class UncheckedIOException extends java.lang.RuntimeException {
+ ctor public UncheckedIOException(java.lang.String, java.io.IOException);
+ ctor public UncheckedIOException(java.io.IOException);
+ }
+
public class UnsupportedEncodingException extends java.io.IOException {
ctor public UnsupportedEncodingException();
ctor public UnsupportedEncodingException(java.lang.String);
@@ -60690,6 +60723,7 @@
method public void set(int, int);
method public void set(int, int, boolean);
method public int size();
+ method public java.util.stream.IntStream stream();
method public byte[] toByteArray();
method public long[] toLongArray();
method public static java.util.BitSet valueOf(long[]);
@@ -61145,6 +61179,7 @@
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
method public boolean replace(K, V, V);
+ method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
}
public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
@@ -61188,6 +61223,7 @@
method public synchronized boolean remove(java.lang.Object, java.lang.Object);
method public synchronized boolean replace(K, V, V);
method public synchronized V replace(K, V);
+ method public synchronized void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
method public synchronized int size();
method public java.util.Collection<V> values();
}
@@ -61728,6 +61764,18 @@
public class Random implements java.io.Serializable {
ctor public Random();
ctor public Random(long);
+ method public java.util.stream.DoubleStream doubles(long);
+ method public java.util.stream.DoubleStream doubles();
+ method public java.util.stream.DoubleStream doubles(long, double, double);
+ method public java.util.stream.DoubleStream doubles(double, double);
+ method public java.util.stream.IntStream ints(long);
+ method public java.util.stream.IntStream ints();
+ method public java.util.stream.IntStream ints(long, int, int);
+ method public java.util.stream.IntStream ints(int, int);
+ method public java.util.stream.LongStream longs(long);
+ method public java.util.stream.LongStream longs();
+ method public java.util.stream.LongStream longs(long, long, long);
+ method public java.util.stream.LongStream longs(long, long);
method protected int next(int);
method public boolean nextBoolean();
method public void nextBytes(byte[]);
@@ -62169,6 +62217,7 @@
method public java.util.NavigableSet<K> navigableKeySet();
method public java.util.Map.Entry<K, V> pollFirstEntry();
method public java.util.Map.Entry<K, V> pollLastEntry();
+ method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
method public java.util.NavigableMap<K, V> subMap(K, boolean, K, boolean);
method public java.util.SortedMap<K, V> subMap(K, K);
method public java.util.NavigableMap<K, V> tailMap(K, boolean);
@@ -62270,6 +62319,7 @@
ctor public WeakHashMap(java.util.Map<? extends K, ? extends V>);
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+ method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
}
}
@@ -63243,18 +63293,6 @@
public class ThreadLocalRandom extends java.util.Random {
method public static java.util.concurrent.ThreadLocalRandom current();
- method public java.util.stream.DoubleStream doubles(long);
- method public java.util.stream.DoubleStream doubles();
- method public java.util.stream.DoubleStream doubles(long, double, double);
- method public java.util.stream.DoubleStream doubles(double, double);
- method public java.util.stream.IntStream ints(long);
- method public java.util.stream.IntStream ints();
- method public java.util.stream.IntStream ints(long, int, int);
- method public java.util.stream.IntStream ints(int, int);
- method public java.util.stream.LongStream longs(long);
- method public java.util.stream.LongStream longs();
- method public java.util.stream.LongStream longs(long, long, long);
- method public java.util.stream.LongStream longs(long, long);
method public double nextDouble(double);
method public double nextDouble(double, double);
method public int nextInt(int, int);
@@ -64627,6 +64665,7 @@
}
public final class Pattern implements java.io.Serializable {
+ method public java.util.function.Predicate<java.lang.String> asPredicate();
method public static java.util.regex.Pattern compile(java.lang.String);
method public static java.util.regex.Pattern compile(java.lang.String, int) throws java.util.regex.PatternSyntaxException;
method public int flags();
@@ -64636,6 +64675,7 @@
method public static java.lang.String quote(java.lang.String);
method public java.lang.String[] split(java.lang.CharSequence, int);
method public java.lang.String[] split(java.lang.CharSequence);
+ method public java.util.stream.Stream<java.lang.String> splitAsStream(java.lang.CharSequence);
field public static final int CANON_EQ = 128; // 0x80
field public static final int CASE_INSENSITIVE = 2; // 0x2
field public static final int COMMENTS = 4; // 0x4
diff --git a/api/test-current.txt b/api/test-current.txt
index 4179948..0c86fd1 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -891,6 +891,7 @@
field public static final int notificationTimeout = 16843651; // 0x1010383
field public static final int numColumns = 16843032; // 0x1010118
field public static final int numStars = 16843076; // 0x1010144
+ field public static final int numberPickerStyle = 16844071; // 0x1010527
field public static final int numbersBackgroundColor = 16843938; // 0x10104a2
field public static final int numbersInnerTextColor = 16844001; // 0x10104e1
field public static final int numbersSelectorColor = 16843939; // 0x10104a3
@@ -2534,6 +2535,7 @@
field public static final int Widget_Material_Light_ListView = 16974513; // 0x10302b1
field public static final int Widget_Material_Light_ListView_DropDown = 16974514; // 0x10302b2
field public static final int Widget_Material_Light_MediaRouteButton = 16974515; // 0x10302b3
+ field public static final int Widget_Material_Light_NumberPicker = 16974557; // 0x10302dd
field public static final int Widget_Material_Light_PopupMenu = 16974516; // 0x10302b4
field public static final int Widget_Material_Light_PopupMenu_Overflow = 16974517; // 0x10302b5
field public static final int Widget_Material_Light_PopupWindow = 16974518; // 0x10302b6
@@ -2566,6 +2568,7 @@
field public static final int Widget_Material_ListView = 16974448; // 0x1030270
field public static final int Widget_Material_ListView_DropDown = 16974449; // 0x1030271
field public static final int Widget_Material_MediaRouteButton = 16974450; // 0x1030272
+ field public static final int Widget_Material_NumberPicker = 16974556; // 0x10302dc
field public static final int Widget_Material_PopupMenu = 16974451; // 0x1030273
field public static final int Widget_Material_PopupMenu_Overflow = 16974452; // 0x1030274
field public static final int Widget_Material_PopupWindow = 16974453; // 0x1030275
@@ -3578,6 +3581,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);
@@ -4479,6 +4483,7 @@
method public void startActivity(android.content.Intent, android.os.Bundle);
method public void startActivityForResult(android.content.Intent, int);
method public void startActivityForResult(android.content.Intent, int, android.os.Bundle);
+ method public void startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
method public void unregisterForContextMenu(android.view.View);
}
@@ -4570,6 +4575,7 @@
method public void onRequestPermissionsFromFragment(android.app.Fragment, java.lang.String[], int);
method public boolean onShouldSaveFragmentState(android.app.Fragment);
method public void onStartActivityFromFragment(android.app.Fragment, android.content.Intent, int, android.os.Bundle);
+ method public void onStartIntentSenderFromFragment(android.app.Fragment, android.content.IntentSender, int, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
method public boolean onUseFragmentManagerInflaterFactory();
}
@@ -5030,13 +5036,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 boolean getHintLaunchesActivity();
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 setHintLaunchesActivity(boolean);
method public android.app.Notification.Action.WearableExtender setInProgressLabel(java.lang.CharSequence);
}
@@ -5900,11 +5906,11 @@
method public java.lang.CharSequence getDeviceOwnerLockScreenInfo();
method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
method public int getKeyguardDisabledFeatures(android.content.ComponentName);
- method public java.lang.String getLongSupportMessage(android.content.ComponentName);
+ method public java.lang.CharSequence getLongSupportMessage(android.content.ComponentName);
method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
method public long getMaximumTimeToLock(android.content.ComponentName);
method public int getOrganizationColor(android.content.ComponentName);
- method public java.lang.String getOrganizationName(android.content.ComponentName);
+ method public java.lang.CharSequence getOrganizationName(android.content.ComponentName);
method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
method public long getPasswordExpiration(android.content.ComponentName);
method public long getPasswordExpirationTimeout(android.content.ComponentName);
@@ -5923,7 +5929,7 @@
method public java.util.List<java.lang.String> getPermittedAccessibilityServices(android.content.ComponentName);
method public java.util.List<java.lang.String> getPermittedInputMethods(android.content.ComponentName);
method public boolean getScreenCaptureDisabled(android.content.ComponentName);
- method public java.lang.String getShortSupportMessage(android.content.ComponentName);
+ method public java.lang.CharSequence getShortSupportMessage(android.content.ComponentName);
method public boolean getStorageEncryption(android.content.ComponentName);
method public int getStorageEncryptionStatus();
method public android.app.admin.SystemUpdatePolicy getSystemUpdatePolicy();
@@ -5974,12 +5980,12 @@
method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException;
- method public void setLongSupportMessage(android.content.ComponentName, java.lang.String);
+ method public void setLongSupportMessage(android.content.ComponentName, java.lang.CharSequence);
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
method public void setMaximumTimeToLock(android.content.ComponentName, long);
method public void setOrganizationColor(android.content.ComponentName, int);
- method public void setOrganizationName(android.content.ComponentName, java.lang.String);
+ method public void setOrganizationName(android.content.ComponentName, java.lang.CharSequence);
method public java.lang.String[] setPackagesSuspended(android.content.ComponentName, java.lang.String[], boolean);
method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
method public void setPasswordHistoryLength(android.content.ComponentName, int);
@@ -6002,7 +6008,7 @@
method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean);
- method public void setShortSupportMessage(android.content.ComponentName, java.lang.String);
+ method public void setShortSupportMessage(android.content.ComponentName, java.lang.CharSequence);
method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
method public int setStorageEncryption(android.content.ComponentName, boolean);
method public void setSystemUpdatePolicy(android.content.ComponentName, android.app.admin.SystemUpdatePolicy);
@@ -6316,6 +6322,8 @@
method public static final long getMinimumPeriod();
method public int getNetworkType();
method public android.content.ComponentName getService();
+ method public long getTriggerContentMaxDelay();
+ method public long getTriggerContentUpdateDelay();
method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
method public boolean isPeriodic();
method public boolean isPersisted();
@@ -6346,6 +6354,8 @@
method public android.app.job.JobInfo.Builder setRequiredNetworkType(int);
method public android.app.job.JobInfo.Builder setRequiresCharging(boolean);
method public android.app.job.JobInfo.Builder setRequiresDeviceIdle(boolean);
+ method public android.app.job.JobInfo.Builder setTriggerContentMaxDelay(long);
+ method public android.app.job.JobInfo.Builder setTriggerContentUpdateDelay(long);
}
public static final class JobInfo.TriggerContentUri implements android.os.Parcelable {
@@ -8621,6 +8631,7 @@
field public static final java.lang.String ACTION_SENDTO = "android.intent.action.SENDTO";
field public static final java.lang.String ACTION_SEND_MULTIPLE = "android.intent.action.SEND_MULTIPLE";
field public static final java.lang.String ACTION_SET_WALLPAPER = "android.intent.action.SET_WALLPAPER";
+ field public static final java.lang.String ACTION_SHOW_APP_INFO = "android.intent.action.SHOW_APP_INFO";
field public static final java.lang.String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";
field public static final java.lang.String ACTION_SYNC = "android.intent.action.SYNC";
field public static final java.lang.String ACTION_SYSTEM_TUTORIAL = "android.intent.action.SYSTEM_TUTORIAL";
@@ -8715,6 +8726,7 @@
field public static final java.lang.String EXTRA_MIME_TYPES = "android.intent.extra.MIME_TYPES";
field public static final java.lang.String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
field public static final java.lang.String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
+ field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";
field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
field public static final java.lang.String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT";
field public static final java.lang.String EXTRA_PROCESS_TEXT_READONLY = "android.intent.extra.PROCESS_TEXT_READONLY";
@@ -9504,11 +9516,10 @@
}
public class LauncherApps {
+ ctor public LauncherApps(android.content.Context);
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 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);
@@ -9520,6 +9531,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);
}
@@ -9541,6 +9553,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
@@ -10048,13 +10061,16 @@
public final class ShortcutInfo implements android.os.Parcelable {
method public int describeContents();
method public android.content.ComponentName getActivityComponent();
+ method public java.util.List<java.lang.String> getCategories();
method public android.os.PersistableBundle getExtras();
+ method public int getIconResourceId();
method public java.lang.String getId();
method public android.content.Intent getIntent();
method public long getLastChangedTimestamp();
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();
@@ -10071,12 +10087,14 @@
field public static final int FLAG_HAS_ICON_RES = 4; // 0x4
field public static final int FLAG_KEY_FIELDS_ONLY = 16; // 0x10
field public static final int FLAG_PINNED = 2; // 0x2
+ field public static final java.lang.String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation";
}
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivityComponent(android.content.ComponentName);
+ method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.List<java.lang.String>);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
method public android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
@@ -10087,15 +10105,16 @@
}
public class ShortcutManager {
- method public boolean addDynamicShortcut(android.content.pm.ShortcutInfo);
- method public void deleteAllDynamicShortcuts();
- method public void deleteDynamicShortcut(java.lang.String);
+ ctor public ShortcutManager(android.content.Context);
+ method public boolean addDynamicShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
method public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
method public int getIconMaxDimensions();
method public int getMaxDynamicShortcutCount();
method public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
method public long getRateLimitResetTime();
method public int getRemainingCallCount();
+ method public void removeAllDynamicShortcuts();
+ method public void removeDynamicShortcuts(java.util.List<java.lang.String>);
method public boolean setDynamicShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
method public boolean updateShortcuts(java.util.List<android.content.pm.ShortcutInfo>);
}
@@ -14441,13 +14460,13 @@
public final class OutputConfiguration implements android.os.Parcelable {
ctor public OutputConfiguration(android.view.Surface);
+ ctor public OutputConfiguration(int, android.view.Surface);
method public int describeContents();
method public android.view.Surface getSurface();
- method public int getSurfaceSetId();
- method public void setSurfaceSetId(int);
+ method public int getSurfaceGroupId();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.hardware.camera2.params.OutputConfiguration> CREATOR;
- field public static final int SURFACE_SET_ID_INVALID = -1; // 0xffffffff
+ field public static final int SURFACE_GROUP_ID_NONE = -1; // 0xffffffff
}
public final class RggbChannelVector {
@@ -19918,8 +19937,8 @@
public class AudioRecord implements android.media.AudioRouting {
ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException;
+ method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener, android.os.Handler);
- method public void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public int getAudioFormat();
method public int getAudioSessionId();
method public int getAudioSource();
@@ -19944,8 +19963,8 @@
method public int read(java.nio.ByteBuffer, int);
method public int read(java.nio.ByteBuffer, int, int);
method public void release();
+ method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
method public deprecated void removeOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener);
- method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
method public int setNotificationMarkerPosition(int);
method public int setPositionNotificationPeriod(int);
method public boolean setPreferredDevice(android.media.AudioDeviceInfo);
@@ -19979,8 +19998,9 @@
method public abstract void onPeriodicNotification(android.media.AudioRecord);
}
- public static abstract interface AudioRecord.OnRoutingChangedListener {
+ public static abstract deprecated interface AudioRecord.OnRoutingChangedListener implements android.media.AudioRouting.OnRoutingChangedListener {
method public abstract void onRoutingChanged(android.media.AudioRecord);
+ method public default void onRoutingChanged(android.media.AudioRouting);
}
public final class AudioRecordingConfiguration implements android.os.Parcelable {
@@ -19995,10 +20015,10 @@
}
public abstract interface AudioRouting {
- method public abstract void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
+ method public abstract void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public abstract android.media.AudioDeviceInfo getPreferredDevice();
method public abstract android.media.AudioDeviceInfo getRoutedDevice();
- method public abstract void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
+ method public abstract void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
method public abstract boolean setPreferredDevice(android.media.AudioDeviceInfo);
}
@@ -20018,8 +20038,8 @@
ctor public AudioTrack(int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioTrack(int, int, int, int, int, int, int) throws java.lang.IllegalArgumentException;
ctor public AudioTrack(android.media.AudioAttributes, android.media.AudioFormat, int, int, int) throws java.lang.IllegalArgumentException;
+ method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler);
- method public void addOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public int attachAuxEffect(int);
method public void flush();
method public int getAudioFormat();
@@ -20051,8 +20071,8 @@
method public void play() throws java.lang.IllegalStateException;
method public void release();
method public int reloadStaticData();
+ method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
method public deprecated void removeOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener);
- method public void removeOnRoutingListener(android.media.AudioRouting.OnRoutingChangedListener);
method public int setAuxEffectSendLevel(float);
method public int setBufferSizeInFrames(int);
method public int setLoopPoints(int, int, int);
@@ -20106,8 +20126,9 @@
method public abstract void onPeriodicNotification(android.media.AudioTrack);
}
- public static abstract deprecated interface AudioTrack.OnRoutingChangedListener {
- method public abstract deprecated void onRoutingChanged(android.media.AudioTrack);
+ public static abstract deprecated interface AudioTrack.OnRoutingChangedListener implements android.media.AudioRouting.OnRoutingChangedListener {
+ method public abstract void onRoutingChanged(android.media.AudioTrack);
+ method public default void onRoutingChanged(android.media.AudioRouting);
}
public class CamcorderProfile {
@@ -20783,10 +20804,12 @@
field public static final int VP9Level6 = 1024; // 0x400
field public static final int VP9Level61 = 2048; // 0x800
field public static final int VP9Level62 = 4096; // 0x1000
- field public static final int VP9Profile0 = 0; // 0x0
- field public static final int VP9Profile1 = 1; // 0x1
- field public static final int VP9Profile2 = 2; // 0x2
- field public static final int VP9Profile3 = 3; // 0x3
+ field public static final int VP9Profile0 = 1; // 0x1
+ field public static final int VP9Profile1 = 2; // 0x2
+ field public static final int VP9Profile2 = 4; // 0x4
+ field public static final int VP9Profile2HDR = 4096; // 0x1000
+ field public static final int VP9Profile3 = 8; // 0x8
+ field public static final int VP9Profile3HDR = 8192; // 0x2000
field public int level;
field public int profile;
}
@@ -22943,6 +22966,7 @@
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
+ field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
@@ -23023,6 +23047,7 @@
method public android.content.Intent createSettingsIntent();
method public android.content.Intent createSetupIntent();
method public int describeContents();
+ method public android.os.Bundle getExtras();
method public java.lang.String getId();
method public java.lang.String getParentId();
method public android.content.pm.ServiceInfo getServiceInfo();
@@ -23052,6 +23077,7 @@
ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName);
method public android.media.tv.TvInputInfo build() throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean);
+ method public android.media.tv.TvInputInfo.Builder setExtras(android.os.Bundle);
method public android.media.tv.TvInputInfo.Builder setTunerCount(int);
}
@@ -29642,6 +29668,7 @@
public class StorageManager {
method public java.lang.String getMountedObbPath(java.lang.String);
method public android.os.storage.StorageVolume getPrimaryStorageVolume();
+ method public android.os.storage.StorageVolume getStorageVolume(java.io.File);
method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes();
method public boolean isEncrypted(java.io.File);
method public boolean isObbMounted(java.lang.String);
@@ -35009,6 +35036,7 @@
method public void onDestroy();
method public boolean[] onGetSupportedCommands(java.lang.String[]);
method public void onHandleAssist(android.os.Bundle, android.app.assist.AssistStructure, android.app.assist.AssistContent);
+ method public void onHandleAssistSecondary(android.os.Bundle, android.app.assist.AssistStructure, android.app.assist.AssistContent, int, int);
method public void onHandleScreenshot(android.graphics.Bitmap);
method public void onHide();
method public boolean onKeyDown(int, android.view.KeyEvent);
@@ -49128,6 +49156,7 @@
ctor public BufferedReader(java.io.Reader, int);
ctor public BufferedReader(java.io.Reader);
method public void close() throws java.io.IOException;
+ method public java.util.stream.Stream<java.lang.String> lines();
method public int read(char[], int, int) throws java.io.IOException;
method public java.lang.String readLine() throws java.io.IOException;
}
@@ -49998,6 +50027,11 @@
ctor public UTFDataFormatException(java.lang.String);
}
+ public class UncheckedIOException extends java.lang.RuntimeException {
+ ctor public UncheckedIOException(java.lang.String, java.io.IOException);
+ ctor public UncheckedIOException(java.io.IOException);
+ }
+
public class UnsupportedEncodingException extends java.io.IOException {
ctor public UnsupportedEncodingException();
ctor public UnsupportedEncodingException(java.lang.String);
@@ -57654,6 +57688,7 @@
method public void set(int, int);
method public void set(int, int, boolean);
method public int size();
+ method public java.util.stream.IntStream stream();
method public byte[] toByteArray();
method public long[] toLongArray();
method public static java.util.BitSet valueOf(long[]);
@@ -58109,6 +58144,7 @@
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
method public boolean replace(K, V, V);
+ method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
}
public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
@@ -58152,6 +58188,7 @@
method public synchronized boolean remove(java.lang.Object, java.lang.Object);
method public synchronized boolean replace(K, V, V);
method public synchronized V replace(K, V);
+ method public synchronized void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
method public synchronized int size();
method public java.util.Collection<V> values();
}
@@ -58692,6 +58729,18 @@
public class Random implements java.io.Serializable {
ctor public Random();
ctor public Random(long);
+ method public java.util.stream.DoubleStream doubles(long);
+ method public java.util.stream.DoubleStream doubles();
+ method public java.util.stream.DoubleStream doubles(long, double, double);
+ method public java.util.stream.DoubleStream doubles(double, double);
+ method public java.util.stream.IntStream ints(long);
+ method public java.util.stream.IntStream ints();
+ method public java.util.stream.IntStream ints(long, int, int);
+ method public java.util.stream.IntStream ints(int, int);
+ method public java.util.stream.LongStream longs(long);
+ method public java.util.stream.LongStream longs();
+ method public java.util.stream.LongStream longs(long, long, long);
+ method public java.util.stream.LongStream longs(long, long);
method protected int next(int);
method public boolean nextBoolean();
method public void nextBytes(byte[]);
@@ -59133,6 +59182,7 @@
method public java.util.NavigableSet<K> navigableKeySet();
method public java.util.Map.Entry<K, V> pollFirstEntry();
method public java.util.Map.Entry<K, V> pollLastEntry();
+ method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
method public java.util.NavigableMap<K, V> subMap(K, boolean, K, boolean);
method public java.util.SortedMap<K, V> subMap(K, K);
method public java.util.NavigableMap<K, V> tailMap(K, boolean);
@@ -59234,6 +59284,7 @@
ctor public WeakHashMap(java.util.Map<? extends K, ? extends V>);
method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+ method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
}
}
@@ -60207,18 +60258,6 @@
public class ThreadLocalRandom extends java.util.Random {
method public static java.util.concurrent.ThreadLocalRandom current();
- method public java.util.stream.DoubleStream doubles(long);
- method public java.util.stream.DoubleStream doubles();
- method public java.util.stream.DoubleStream doubles(long, double, double);
- method public java.util.stream.DoubleStream doubles(double, double);
- method public java.util.stream.IntStream ints(long);
- method public java.util.stream.IntStream ints();
- method public java.util.stream.IntStream ints(long, int, int);
- method public java.util.stream.IntStream ints(int, int);
- method public java.util.stream.LongStream longs(long);
- method public java.util.stream.LongStream longs();
- method public java.util.stream.LongStream longs(long, long, long);
- method public java.util.stream.LongStream longs(long, long);
method public double nextDouble(double);
method public double nextDouble(double, double);
method public int nextInt(int, int);
@@ -61591,6 +61630,7 @@
}
public final class Pattern implements java.io.Serializable {
+ method public java.util.function.Predicate<java.lang.String> asPredicate();
method public static java.util.regex.Pattern compile(java.lang.String);
method public static java.util.regex.Pattern compile(java.lang.String, int) throws java.util.regex.PatternSyntaxException;
method public int flags();
@@ -61600,6 +61640,7 @@
method public static java.lang.String quote(java.lang.String);
method public java.lang.String[] split(java.lang.CharSequence, int);
method public java.lang.String[] split(java.lang.CharSequence);
+ method public java.util.stream.Stream<java.lang.String> splitAsStream(java.lang.CharSequence);
field public static final int CANON_EQ = 128; // 0x80
field public static final int CASE_INSENSITIVE = 2; // 0x2
field public static final int COMMENTS = 4; // 0x4
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 3385a17..e788d27 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -16,6 +16,9 @@
package android.animation;
+import android.app.ActivityThread;
+import android.app.Application;
+import android.os.Build;
import android.util.ArrayMap;
import android.util.Log;
@@ -133,10 +136,25 @@
// The total duration of finishing all the Animators in the set.
private long mTotalDuration = 0;
+ // In pre-N releases, calling end() before start() on an animator set is no-op. But that is not
+ // consistent with the behavior for other animator types. In order to keep the behavior
+ // consistent within Animation framework, when end() is called without start(), we will start
+ // the animator set and immediately end it for N and forward.
+ private final boolean mShouldIgnoreEndWithoutStart;
+
public AnimatorSet() {
super();
mNodeMap.put(mDelayAnim, mRootNode);
mNodes.add(mRootNode);
+ // Set the flag to ignore calling end() without start() for pre-N releases
+ Application app = ActivityThread.currentApplication();
+ if (app == null || app.getApplicationInfo() == null) {
+ mShouldIgnoreEndWithoutStart = true;
+ } else if (app.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
+ mShouldIgnoreEndWithoutStart = true;
+ } else {
+ mShouldIgnoreEndWithoutStart = false;
+ }
}
/**
@@ -365,6 +383,9 @@
*/
@Override
public void end() {
+ if (mShouldIgnoreEndWithoutStart && !isStarted()) {
+ return;
+ }
mTerminated = true;
if (isStarted()) {
endRemainingAnimations();
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index c6a5152..31035a7 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -1200,13 +1200,17 @@
boolean animateBasedOnTime(long currentTime) {
boolean done = false;
if (mRunning) {
- final float fraction = getScaledDuration() > 0 ?
- (float)(currentTime - mStartTime) / getScaledDuration() : 1f;
+ final long scaledDuration = getScaledDuration();
+ final float fraction = scaledDuration > 0 ?
+ (float)(currentTime - mStartTime) / scaledDuration : 1f;
final float lastFraction = mOverallFraction;
final boolean newIteration = (int) fraction > (int) lastFraction;
final boolean lastIterationFinished = (fraction >= mRepeatCount + 1) &&
(mRepeatCount != INFINITE);
- if (newIteration && !lastIterationFinished) {
+ if (scaledDuration == 0) {
+ // 0 duration animator, ignore the repeat count and skip to the end
+ done = true;
+ } else if (newIteration && !lastIterationFinished) {
// Time to repeat
if (mListeners != null) {
int numListeners = mListeners.size();
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 672a706..f7884a7 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1676,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) {
@@ -4394,8 +4405,8 @@
@Nullable Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
Bundle options) throws IntentSender.SendIntentException {
if (mParent == null) {
- startIntentSenderForResultInner(intent, requestCode, fillInIntent,
- flagsMask, flagsValues, this, options);
+ startIntentSenderForResultInner(intent, mEmbeddedID, requestCode, fillInIntent,
+ flagsMask, flagsValues, options);
} else if (options != null) {
mParent.startIntentSenderFromChild(this, intent, requestCode,
fillInIntent, flagsMask, flagsValues, extraFlags, options);
@@ -4407,8 +4418,8 @@
}
}
- private void startIntentSenderForResultInner(IntentSender intent, int requestCode,
- Intent fillInIntent, int flagsMask, int flagsValues, Activity activity,
+ private void startIntentSenderForResultInner(IntentSender intent, String who, int requestCode,
+ Intent fillInIntent, int flagsMask, int flagsValues,
Bundle options)
throws IntentSender.SendIntentException {
try {
@@ -4420,7 +4431,7 @@
}
int result = ActivityManagerNative.getDefault()
.startActivityIntentSender(mMainThread.getApplicationThread(), intent,
- fillInIntent, resolvedType, mToken, activity.mEmbeddedID,
+ fillInIntent, resolvedType, mToken, who,
requestCode, flagsMask, flagsValues, options);
if (result == ActivityManager.START_CANCELED) {
throw new IntentSender.SendIntentException();
@@ -4877,8 +4888,23 @@
int requestCode, Intent fillInIntent, int flagsMask, int flagsValues,
int extraFlags, @Nullable Bundle options)
throws IntentSender.SendIntentException {
- startIntentSenderForResultInner(intent, requestCode, fillInIntent,
- flagsMask, flagsValues, child, options);
+ startIntentSenderForResultInner(intent, child.mEmbeddedID, requestCode, fillInIntent,
+ flagsMask, flagsValues, options);
+ }
+
+ /**
+ * Like {@link #startIntentSenderFromChild}, but taking a Fragment; see
+ * {@link #startIntentSenderForResult(IntentSender, int, Intent, int, int, int)}
+ * for more information.
+ *
+ * @hide
+ */
+ public void startIntentSenderFromChildFragment(Fragment child, IntentSender intent,
+ int requestCode, Intent fillInIntent, int flagsMask, int flagsValues,
+ int extraFlags, @Nullable Bundle options)
+ throws IntentSender.SendIntentException {
+ startIntentSenderForResultInner(intent, child.mWho, requestCode, fillInIntent,
+ flagsMask, flagsValues, options);
}
/**
@@ -7024,6 +7050,19 @@
}
@Override
+ public void onStartIntentSenderFromFragment(Fragment fragment, IntentSender intent,
+ int requestCode, @Nullable Intent fillInIntent, int flagsMask, int flagsValues,
+ int extraFlags, Bundle options) throws IntentSender.SendIntentException {
+ if (mParent == null) {
+ startIntentSenderForResultInner(intent, fragment.mWho, requestCode, fillInIntent,
+ flagsMask, flagsValues, options);
+ } else if (options != null) {
+ mParent.startIntentSenderFromChildFragment(fragment, intent, requestCode,
+ fillInIntent, flagsMask, flagsValues, extraFlags, options);
+ }
+ }
+
+ @Override
public void onRequestPermissionsFromFragment(Fragment fragment, String[] permissions,
int requestCode) {
String who = REQUEST_PERMISSIONS_WHO_PREFIX + fragment.mWho;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index d1f5143..631a129 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -22,6 +22,7 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Matrix;
@@ -1305,6 +1306,12 @@
*/
public boolean isDockable;
+ /**
+ * The resize mode of the task. See {@link ActivityInfo#resizeMode}.
+ * @hide
+ */
+ public int resizeMode;
+
public RecentTaskInfo() {
}
@@ -1349,6 +1356,7 @@
dest.writeInt(0);
}
dest.writeInt(isDockable ? 1 : 0);
+ dest.writeInt(resizeMode);
}
public void readFromParcel(Parcel source) {
@@ -1372,6 +1380,7 @@
bounds = source.readInt() > 0 ?
Rect.CREATOR.createFromParcel(source) : null;
isDockable = source.readInt() == 1;
+ resizeMode = source.readInt();
}
public static final Creator<RecentTaskInfo> CREATOR
@@ -1560,6 +1569,12 @@
*/
public boolean isDockable;
+ /**
+ * The resize mode of the task. See {@link ActivityInfo#resizeMode}.
+ * @hide
+ */
+ public int resizeMode;
+
public RunningTaskInfo() {
}
@@ -1583,6 +1598,7 @@
dest.writeInt(numActivities);
dest.writeInt(numRunning);
dest.writeInt(isDockable ? 1 : 0);
+ dest.writeInt(resizeMode);
}
public void readFromParcel(Parcel source) {
@@ -1599,6 +1615,7 @@
numActivities = source.readInt();
numRunning = source.readInt();
isDockable = source.readInt() != 0;
+ resizeMode = source.readInt();
}
public static final Creator<RunningTaskInfo> CREATOR = new Creator<RunningTaskInfo>() {
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 5116634..374c4f6 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -23,6 +23,8 @@
import com.android.internal.app.IVoiceInteractor;
+import java.util.List;
+
/**
* Activity manager local system service interface.
*
@@ -125,4 +127,10 @@
* Callback for window manager to let activity manager know that the app transition is finished.
*/
public abstract void notifyAppTransitionFinished();
+
+ /**
+ * Returns the top activity from each of the currently visible stacks. The first entry will be
+ * the focused activity.
+ */
+ public abstract List<IBinder> getTopVisibleActivities();
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 65d48e6..7bf03de 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2411,8 +2411,11 @@
data.enforceInterface(IActivityManager.descriptor);
int requestType = data.readInt();
IResultReceiver receiver = IResultReceiver.Stub.asInterface(data.readStrongBinder());
+ Bundle receiverExtras = data.readBundle();
IBinder activityToken = data.readStrongBinder();
- boolean res = requestAssistContextExtras(requestType, receiver, activityToken);
+ boolean focused = data.readInt() == 1;
+ boolean res = requestAssistContextExtras(requestType, receiver, receiverExtras,
+ activityToken, focused);
reply.writeNoException();
reply.writeInt(res ? 1 : 0);
return true;
@@ -6080,13 +6083,16 @@
}
public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver,
- IBinder activityToken) throws RemoteException {
+ Bundle receiverExtras,
+ IBinder activityToken, boolean focused) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(requestType);
data.writeStrongBinder(receiver.asBinder());
+ data.writeBundle(receiverExtras);
data.writeStrongBinder(activityToken);
+ data.writeInt(focused ? 1 : 0);
mRemote.transact(REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION, data, reply, 0);
reply.readException();
boolean res = reply.readInt() != 0;
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index ed590e6..bf56f25 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1921,6 +1921,16 @@
}
@Override
+ public void deleteApplicationCacheFilesAsUser(String packageName, int userId,
+ IPackageDataObserver observer) {
+ try {
+ mPM.deleteApplicationCacheFilesAsUser(packageName, userId, observer);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
public void freeStorageAndNotify(String volumeUuid, long idealStorageSize,
IPackageDataObserver observer) {
try {
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 2a04c39..29f594f 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -23,6 +23,7 @@
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentSender;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -1116,6 +1117,20 @@
}
/**
+ * Call {@link Activity#startIntentSenderForResult(IntentSender, int, Intent, int, int, int,
+ * Bundle)} from the fragment's containing Activity.
+ */
+ public void startIntentSenderForResult(IntentSender intent, int requestCode,
+ @Nullable Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
+ Bundle options) throws IntentSender.SendIntentException {
+ if (mHost == null) {
+ throw new IllegalStateException("Fragment " + this + " not attached to Activity");
+ }
+ mHost.onStartIntentSenderFromFragment(this, intent, requestCode, fillInIntent, flagsMask,
+ flagsValues, extraFlags, options);
+ }
+
+ /**
* Receive the result from a previous call to
* {@link #startActivityForResult(Intent, int)}. This follows the
* related Activity API as described there in
diff --git a/core/java/android/app/FragmentHostCallback.java b/core/java/android/app/FragmentHostCallback.java
index 13517e6..cf6b114 100644
--- a/core/java/android/app/FragmentHostCallback.java
+++ b/core/java/android/app/FragmentHostCallback.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentSender;
import android.os.Bundle;
import android.os.Handler;
import android.util.ArrayMap;
@@ -131,6 +132,21 @@
}
/**
+ * Starts a new {@link IntentSender} from the given fragment.
+ * See {@link Activity#startIntentSender(IntentSender, Intent, int, int, int, Bundle)}.
+ */
+ public void onStartIntentSenderFromFragment(Fragment fragment, IntentSender intent,
+ int requestCode, @Nullable Intent fillInIntent, int flagsMask, int flagsValues,
+ int extraFlags, Bundle options) throws IntentSender.SendIntentException {
+ if (requestCode != -1) {
+ throw new IllegalStateException(
+ "Starting intent sender with a requestCode requires a FragmentActivity host");
+ }
+ mContext.startIntentSender(intent, fillInIntent, flagsMask, flagsValues, extraFlags,
+ options);
+ }
+
+ /**
* Requests permissions from the given fragment.
* See {@link Activity#requestPermissions(String[], int)}
*/
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 8ee6fd0..6975116 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -523,7 +523,8 @@
public Bundle getAssistContextExtras(int requestType) throws RemoteException;
public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver,
- IBinder activityToken) throws RemoteException;
+ Bundle receiverExtras,
+ IBinder activityToken, boolean focused) throws RemoteException;
public void reportAssistContextExtras(IBinder token, Bundle extras,
AssistStructure structure, AssistContent content, Uri referrer) throws RemoteException;
diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java
index f0e35c9..f203f46 100644
--- a/core/java/android/app/LoaderManager.java
+++ b/core/java/android/app/LoaderManager.java
@@ -318,7 +318,7 @@
if (mStarted) {
if (mReportNextStart) {
mReportNextStart = false;
- if (mHaveData) {
+ if (mHaveData && !mRetaining) {
callOnLoadFinished(mLoader, mData);
}
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 4bf1aa3..400a313 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -25,10 +25,13 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
@@ -43,6 +46,7 @@
import android.os.Parcelable;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.text.BidiFormatter;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
@@ -588,8 +592,8 @@
private static final int COLOR_INVALID = 1;
/**
- * Sphere of visibility of this notification, which affects how and when the SystemUI reveals
- * the notification's presence and contents in untrusted situations (namely, on the secure
+ * Sphere of visibility of this notification, which affects how and when the SystemUI reveals
+ * the notification's presence and contents in untrusted situations (namely, on the secure
* lockscreen).
*
* The default level, {@link #VISIBILITY_PRIVATE}, behaves exactly as notifications have always
@@ -777,6 +781,16 @@
/**
* {@link #extras} key: this is the remote input history, as supplied to
* {@link Builder#setRemoteInputHistory(CharSequence[])}.
+ *
+ * Apps can fill this through {@link Builder#setRemoteInputHistory(CharSequence[])}
+ * with the most recent inputs that have been sent through a {@link RemoteInput} of this
+ * Notification and are expected to clear it once the it is no longer relevant (e.g. for chat
+ * notifications once the other party has responded).
+ *
+ * The extra with this key is of type CharSequence[] and contains the most recent entry at
+ * the 0 index, the second most recent at the 1 index, etc.
+ *
+ * @see Builder#setRemoteInputHistory(CharSequence[])
*/
public static final String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory";
@@ -958,6 +972,12 @@
*/
public static final String EXTRA_CONTAINS_CUSTOM_VIEW = "android.contains.customView";
+ /**
+ * @SystemApi
+ * @hide
+ */
+ public static final String EXTRA_SUBSTITUTE_APP_NAME = "android.substName";
+
private Icon mSmallIcon;
private Icon mLargeIcon;
@@ -1419,7 +1439,7 @@
* an activity and transitions should be generated, false otherwise.
* @return this object for method chaining
*/
- public WearableExtender setHintContentIntentLaunchesActivity(
+ public WearableExtender setHintLaunchesActivity(
boolean hintLaunchesActivity) {
setFlag(FLAG_HINT_LAUNCHES_ACTIVITY, hintLaunchesActivity);
return this;
@@ -1432,7 +1452,7 @@
* should be generated, false otherwise. The default value is {@code false} if this was
* never set.
*/
- public boolean getHintContentIntentLaunchesActivity() {
+ public boolean getHintLaunchesActivity() {
return (mFlags & FLAG_HINT_LAUNCHES_ACTIVITY) != 0;
}
}
@@ -1955,9 +1975,16 @@
* @hide
*/
public static void addFieldsFromContext(Context context, Notification notification) {
- notification.extras.putParcelable(EXTRA_BUILDER_APPLICATION_INFO,
- context.getApplicationInfo());
- notification.extras.putInt(EXTRA_ORIGINATING_USERID, context.getUserId());
+ addFieldsFromContext(context.getApplicationInfo(), context.getUserId(), notification);
+ }
+
+ /**
+ * @hide
+ */
+ public static void addFieldsFromContext(ApplicationInfo ai, int userId,
+ Notification notification) {
+ notification.extras.putParcelable(EXTRA_BUILDER_APPLICATION_INFO, ai);
+ notification.extras.putInt(EXTRA_ORIGINATING_USERID, userId);
}
@Override
@@ -2220,7 +2247,8 @@
Log.d(TAG, "Unknown style class: " + templateClass);
} else {
try {
- final Constructor<? extends Style> ctor = styleClass.getConstructor();
+ final Constructor<? extends Style> ctor =
+ styleClass.getDeclaredConstructor();
ctor.setAccessible(true);
final Style style = ctor.newInstance();
style.restoreFromExtras(mN.extras);
@@ -3119,6 +3147,18 @@
* @param hasProgress whether the progress bar should be shown and set
*/
private RemoteViews applyStandardTemplate(int resId, boolean hasProgress) {
+ final Bundle ex = mN.extras;
+
+ CharSequence title = processLegacyText(ex.getCharSequence(EXTRA_TITLE));
+ CharSequence text = processLegacyText(ex.getCharSequence(EXTRA_TEXT));
+ return applyStandardTemplate(resId, hasProgress, title, text);
+ }
+
+ /**
+ * @param hasProgress whether the progress bar should be shown and set
+ */
+ private RemoteViews applyStandardTemplate(int resId, boolean hasProgress,
+ CharSequence title, CharSequence text) {
RemoteViews contentView = new BuilderRemoteViews(mContext.getApplicationInfo(), resId);
resetStandardTemplate(contentView);
@@ -3127,17 +3167,15 @@
bindNotificationHeader(contentView);
bindLargeIcon(contentView);
- if (ex.getCharSequence(EXTRA_TITLE) != null) {
+ if (title != null) {
contentView.setViewVisibility(R.id.title, View.VISIBLE);
- contentView.setTextViewText(R.id.title,
- processLegacyText(ex.getCharSequence(EXTRA_TITLE)));
+ contentView.setTextViewText(R.id.title, title);
}
boolean showProgress = handleProgressBar(hasProgress, contentView, ex);
- if (ex.getCharSequence(EXTRA_TEXT) != null) {
+ if (text != null) {
int textId = showProgress ? com.android.internal.R.id.text_line_1
: com.android.internal.R.id.text;
- contentView.setTextViewText(textId, processLegacyText(
- ex.getCharSequence(EXTRA_TEXT)));
+ contentView.setTextViewText(textId, text);
contentView.setViewVisibility(textId, View.VISIBLE);
}
@@ -3249,14 +3287,38 @@
}
}
- private void bindHeaderAppName(RemoteViews contentView) {
- CharSequence appName = mContext.getPackageManager()
- .getApplicationLabel(mContext.getApplicationInfo());
-
- if (TextUtils.isEmpty(appName)) {
- return;
+ private String loadHeaderAppName() {
+ CharSequence name = null;
+ final PackageManager pm = mContext.getPackageManager();
+ if (mN.extras.containsKey(EXTRA_SUBSTITUTE_APP_NAME)) {
+ // only system packages which lump together a bunch of unrelated stuff
+ // may substitute a different name to make the purpose of the
+ // notification more clear. the correct package label should always
+ // be accessible via SystemUI.
+ final String pkg = mContext.getPackageName();
+ final String subName = mN.extras.getString(EXTRA_SUBSTITUTE_APP_NAME);
+ if (PackageManager.PERMISSION_GRANTED == pm.checkPermission(
+ android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME, pkg)) {
+ name = subName;
+ } else {
+ Log.w(TAG, "warning: pkg "
+ + pkg + " attempting to substitute app name '" + subName
+ + "' without holding perm "
+ + android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME);
+ }
}
- contentView.setTextViewText(R.id.app_name_text, appName);
+ if (TextUtils.isEmpty(name)) {
+ name = pm.getApplicationLabel(mContext.getApplicationInfo());
+ }
+ if (TextUtils.isEmpty(name)) {
+ // still nothing?
+ return null;
+ }
+
+ return String.valueOf(name);
+ }
+ private void bindHeaderAppName(RemoteViews contentView) {
+ contentView.setTextViewText(R.id.app_name_text, loadHeaderAppName());
contentView.setTextColor(R.id.app_name_text, resolveContrastColor());
}
@@ -3288,7 +3350,16 @@
}
private RemoteViews applyStandardTemplateWithActions(int layoutId) {
- RemoteViews big = applyStandardTemplate(layoutId);
+ final Bundle ex = mN.extras;
+
+ CharSequence title = processLegacyText(ex.getCharSequence(EXTRA_TITLE));
+ CharSequence text = processLegacyText(ex.getCharSequence(EXTRA_TEXT));
+ return applyStandardTemplateWithActions(layoutId, true /* hasProgress */, title, text);
+ }
+
+ private RemoteViews applyStandardTemplateWithActions(int layoutId, boolean hasProgress,
+ CharSequence title, CharSequence text) {
+ RemoteViews big = applyStandardTemplate(layoutId, hasProgress, title, text);
resetStandardTemplateWithActions(big);
@@ -3742,6 +3813,10 @@
return R.layout.notification_template_material_inbox;
}
+ private int getMessagingLayoutResource() {
+ return R.layout.notification_template_material_messaging;
+ }
+
private int getActionLayoutResource() {
return R.layout.notification_material_action;
}
@@ -4368,13 +4443,100 @@
/**
* @hide
*/
- public RemoteViews makeBigContentView() {
- // TODO handset to write implementation
- RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource());
+ @Override
+ public RemoteViews makeContentView() {
+ Message m = findLatestIncomingMessage();
+ CharSequence title = mConversationTitle != null
+ ? mConversationTitle
+ : (m == null) ? null : m.mSender;
+ CharSequence text = (m == null)
+ ? null
+ : mConversationTitle != null ? makeMessageLine(m) : m.mText;
+ return mBuilder.applyStandardTemplate(mBuilder.getBaseLayoutResource(),
+ false /* hasProgress */,
+ title,
+ text);
+ }
+
+ private Message findLatestIncomingMessage() {
+ for (int i = mMessages.size() - 1; i >= 0; i--) {
+ Message m = mMessages.get(i);
+ // Incoming messages have a non-empty sender.
+ if (!TextUtils.isEmpty(m.mSender)) {
+ return m;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public RemoteViews makeBigContentView() {
+ CharSequence title = !TextUtils.isEmpty(super.mBigContentTitle)
+ ? super.mBigContentTitle
+ : mConversationTitle;
+ boolean hasTitle = !TextUtils.isEmpty(title);
+
+ RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
+ mBuilder.getMessagingLayoutResource(),
+ false /* hasProgress */,
+ title,
+ null /* text */);
+
+ int[] rowIds = {R.id.inbox_text0, R.id.inbox_text1, R.id.inbox_text2, R.id.inbox_text3,
+ R.id.inbox_text4, R.id.inbox_text5, R.id.inbox_text6};
+
+ // Make sure all rows are gone in case we reuse a view.
+ for (int rowId : rowIds) {
+ contentView.setViewVisibility(rowId, View.GONE);
+ }
+
+ int i=0;
+ int titlePadding = mBuilder.mContext.getResources().getDimensionPixelSize(
+ R.dimen.notification_messaging_spacing);
+ contentView.setViewLayoutMarginBottom(R.id.line1, hasTitle ? titlePadding : 0);
+ contentView.setInt(R.id.notification_messaging, "setNumIndentLines",
+ mBuilder.mN.mLargeIcon == null ? 0 : (hasTitle ? 1 : 2));
+
+ int firstMessage = Math.max(0, mMessages.size() - rowIds.length);
+ while (firstMessage + i < mMessages.size() && i < rowIds.length) {
+ Message m = mMessages.get(firstMessage + i);
+ int rowId = rowIds[i];
+
+ contentView.setViewVisibility(rowId, View.VISIBLE);
+ contentView.setTextViewText(rowId, makeMessageLine(m));
+
+ i++;
+ }
return contentView;
}
+ private CharSequence makeMessageLine(Message m) {
+ BidiFormatter bidi = BidiFormatter.getInstance();
+ SpannableStringBuilder sb = new SpannableStringBuilder();
+ if (TextUtils.isEmpty(m.mSender)) {
+ CharSequence replyName = mUserDisplayName == null ? "" : mUserDisplayName;
+ sb.append(bidi.unicodeWrap(replyName),
+ makeFontColorSpan(mBuilder.resolveContrastColor()),
+ 0 /* flags */);
+ } else {
+ sb.append(bidi.unicodeWrap(m.mSender),
+ makeFontColorSpan(Color.BLACK),
+ 0 /* flags */);
+ }
+ CharSequence text = m.mText == null ? "" : m.mText;
+ sb.append(" ").append(bidi.unicodeWrap(text));
+ return sb;
+ }
+
+ private static TextAppearanceSpan makeFontColorSpan(int color) {
+ return new TextAppearanceSpan(null, 0, 0,
+ ColorStateList.valueOf(color), null);
+ }
+
public static final class Message implements Parcelable {
private final CharSequence mText;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index bdc4404..cd6e572 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -532,7 +532,8 @@
public WifiScanner createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.WIFI_SCANNING_SERVICE);
IWifiScanner service = IWifiScanner.Stub.asInterface(b);
- return new WifiScanner(ctx.getOuterContext(), service);
+ return new WifiScanner(ctx.getOuterContext(), service,
+ ConnectivityThread.getInstanceLooper());
}});
registerService(Context.WIFI_RTT_SERVICE, RttManager.class,
@@ -589,9 +590,7 @@
new CachedServiceFetcher<LauncherApps>() {
@Override
public LauncherApps createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.LAUNCHER_APPS_SERVICE);
- ILauncherApps service = ILauncherApps.Stub.asInterface(b);
- return new LauncherApps(ctx, service);
+ return new LauncherApps(ctx);
}});
registerService(Context.RESTRICTIONS_SERVICE, RestrictionsManager.class,
@@ -758,8 +757,7 @@
new CachedServiceFetcher<ShortcutManager>() {
@Override
public ShortcutManager createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(Context.SHORTCUT_SERVICE);
- return new ShortcutManager(ctx, IShortcutService.Stub.asInterface(b));
+ return new ShortcutManager(ctx);
}});
registerService(Context.SYSTEM_HEALTH_SERVICE, SystemHealthManager.class,
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3f9629c..269089e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2216,7 +2216,9 @@
* that uses {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD}
*/
public boolean resetPassword(String password, int flags) {
- throwIfParentInstance("resetPassword");
+ if (mParentInstance) {
+ throw new SecurityException("Reset password does not work across profiles.");
+ }
if (mService != null) {
try {
return mService.resetPassword(password, flags);
@@ -2353,7 +2355,6 @@
* that uses {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA}
*/
public void wipeData(int flags) {
- throwIfParentInstance("wipeData");
if (mService != null) {
try {
mService.wipeData(flags);
@@ -2387,7 +2388,6 @@
*/
public ComponentName setGlobalProxy(@NonNull ComponentName admin, Proxy proxySpec,
List<String> exclusionList ) {
- throwIfParentInstance("setGlobalProxy");
if (proxySpec == null) {
throw new NullPointerException();
}
@@ -2453,7 +2453,6 @@
*/
public void setRecommendedGlobalProxy(@NonNull ComponentName admin, @Nullable ProxyInfo
proxyInfo) {
- throwIfParentInstance("setRecommendedGlobalProxy");
if (mService != null) {
try {
mService.setRecommendedGlobalProxy(admin, proxyInfo);
@@ -2604,7 +2603,6 @@
* {@link DeviceAdminInfo#USES_ENCRYPTED_STORAGE}
*/
public int setStorageEncryption(@NonNull ComponentName admin, boolean encrypt) {
- throwIfParentInstance("setStorageEncryption");
if (mService != null) {
try {
return mService.setStorageEncryption(admin, encrypt);
@@ -2625,7 +2623,6 @@
* @return true if the admin(s) are requesting encryption, false if not.
*/
public boolean getStorageEncryption(@Nullable ComponentName admin) {
- throwIfParentInstance("getStorageEncryption");
if (mService != null) {
try {
return mService.getStorageEncryption(admin, myUserId());
@@ -2721,7 +2718,6 @@
* owner.
*/
public boolean installCaCert(@Nullable ComponentName admin, byte[] certBuffer) {
- throwIfParentInstance("installCaCert");
if (mService != null) {
try {
return mService.installCaCert(admin, certBuffer);
@@ -2742,7 +2738,6 @@
* owner.
*/
public void uninstallCaCert(@Nullable ComponentName admin, byte[] certBuffer) {
- throwIfParentInstance("uninstallCaCert");
if (mService != null) {
try {
final String alias = getCaCertAlias(certBuffer);
@@ -2768,7 +2763,6 @@
*/
public List<byte[]> getInstalledCaCerts(@Nullable ComponentName admin) {
List<byte[]> certs = new ArrayList<byte[]>();
- throwIfParentInstance("getInstalledCaCerts");
if (mService != null) {
try {
mService.enforceCanManageCaCerts(admin);
@@ -2797,7 +2791,6 @@
* owner.
*/
public void uninstallAllUserCaCerts(@Nullable ComponentName admin) {
- throwIfParentInstance("uninstallAllUserCaCerts");
if (mService != null) {
try {
mService.uninstallCaCerts(admin, new TrustedCertificateStore().userAliases()
@@ -2818,7 +2811,6 @@
* owner.
*/
public boolean hasCaCertInstalled(@Nullable ComponentName admin, byte[] certBuffer) {
- throwIfParentInstance("hasCaCertInstalled");
if (mService != null) {
try {
mService.enforceCanManageCaCerts(admin);
@@ -2887,7 +2879,6 @@
*/
public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey,
@NonNull Certificate[] certs, @NonNull String alias, boolean requestAccess) {
- throwIfParentInstance("installKeyPair");
try {
final byte[] pemCert = Credentials.convertToPem(certs[0]);
byte[] pemChain = null;
@@ -2920,7 +2911,6 @@
* owner.
*/
public boolean removeKeyPair(@Nullable ComponentName admin, @NonNull String alias) {
- throwIfParentInstance("removeKeyPair");
try {
return mService.removeKeyPair(admin, alias);
} catch (RemoteException e) {
@@ -2961,7 +2951,6 @@
*/
public void setCertInstallerPackage(@NonNull ComponentName admin, @Nullable String
installerPackage) throws SecurityException {
- throwIfParentInstance("setCertInstallerPackage");
if (mService != null) {
try {
mService.setCertInstallerPackage(admin, installerPackage);
@@ -2981,7 +2970,6 @@
* @throws SecurityException if {@code admin} is not a device or a profile owner.
*/
public String getCertInstallerPackage(@NonNull ComponentName admin) throws SecurityException {
- throwIfParentInstance("getCertInstallerPackage");
if (mService != null) {
try {
return mService.getCertInstallerPackage(admin);
@@ -3012,7 +3000,6 @@
*/
public void setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage)
throws NameNotFoundException, UnsupportedOperationException {
- throwIfParentInstance("setAlwaysOnVpnPackage");
if (mService != null) {
try {
if (!mService.setAlwaysOnVpnPackage(admin, vpnPackage)) {
@@ -3034,7 +3021,6 @@
* @throws SecurityException if {@code admin} is not a device or a profile owner.
*/
public String getAlwaysOnVpnPackage(@NonNull ComponentName admin) {
- throwIfParentInstance("getAlwaysOnVpnPackage");
if (mService != null) {
try {
return mService.getAlwaysOnVpnPackage(admin);
@@ -3062,7 +3048,6 @@
* {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA}.
*/
public void setCameraDisabled(@NonNull ComponentName admin, boolean disabled) {
- throwIfParentInstance("setCameraDisabled");
if (mService != null) {
try {
mService.setCameraDisabled(admin, disabled);
@@ -3079,7 +3064,6 @@
* have disabled the camera
*/
public boolean getCameraDisabled(@Nullable ComponentName admin) {
- throwIfParentInstance("getCameraDisabled");
return getCameraDisabled(admin, myUserId());
}
@@ -3109,7 +3093,6 @@
* than the one managed by the device owner.
*/
public boolean requestBugreport(@NonNull ComponentName admin) {
- throwIfParentInstance("requestBugreport");
if (mService != null) {
try {
return mService.requestBugreport(admin);
@@ -3148,7 +3131,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public void setScreenCaptureDisabled(@NonNull ComponentName admin, boolean disabled) {
- throwIfParentInstance("setScreenCaptureDisabled");
if (mService != null) {
try {
mService.setScreenCaptureDisabled(admin, disabled);
@@ -3165,7 +3147,6 @@
* have disabled screen capture.
*/
public boolean getScreenCaptureDisabled(@Nullable ComponentName admin) {
- throwIfParentInstance("getScreenCaptureDisabled");
return getScreenCaptureDisabled(admin, myUserId());
}
@@ -3195,7 +3176,6 @@
* @throws SecurityException if {@code admin} is not a device owner.
*/
public void setAutoTimeRequired(@NonNull ComponentName admin, boolean required) {
- throwIfParentInstance("setAutoTimeRequired");
if (mService != null) {
try {
mService.setAutoTimeRequired(admin, required);
@@ -3209,7 +3189,6 @@
* @return true if auto time is required.
*/
public boolean getAutoTimeRequired() {
- throwIfParentInstance("getAutoTimeRequired");
if (mService != null) {
try {
return mService.getAutoTimeRequired();
@@ -3236,7 +3215,6 @@
*/
public void setForceEphemeralUsers(
@NonNull ComponentName admin, boolean forceEphemeralUsers) {
- throwIfParentInstance("setForceEphemeralUsers");
if (mService != null) {
try {
mService.setForceEphemeralUsers(admin, forceEphemeralUsers);
@@ -3252,7 +3230,6 @@
* @hide
*/
public boolean getForceEphemeralUsers(@NonNull ComponentName admin) {
- throwIfParentInstance("getForceEphemeralUsers");
if (mService != null) {
try {
return mService.getForceEphemeralUsers(admin);
@@ -3540,7 +3517,6 @@
* @return whether or not the package is registered as the device owner app.
*/
public boolean isDeviceOwnerApp(String packageName) {
- throwIfParentInstance("isDeviceOwnerApp");
return isDeviceOwnerAppOnCallingUser(packageName);
}
@@ -3638,7 +3614,6 @@
* does not own the current device owner component.
*/
public void clearDeviceOwnerApp(String packageName) {
- throwIfParentInstance("clearDeviceOwnerApp");
if (mService != null) {
try {
mService.clearDeviceOwner(packageName);
@@ -3756,7 +3731,6 @@
* @throws SecurityException if {@code admin} is not an active profile owner.
*/
public void clearProfileOwner(@NonNull ComponentName admin) {
- throwIfParentInstance("clearProfileOwner");
if (mService != null) {
try {
mService.clearProfileOwner(admin);
@@ -3830,7 +3804,6 @@
* @throws SecurityException if {@code admin} is not a device owner.
*/
public void setDeviceOwnerLockScreenInfo(@NonNull ComponentName admin, CharSequence info) {
- throwIfParentInstance("setDeviceOwnerLockScreenInfo");
if (mService != null) {
try {
mService.setDeviceOwnerLockScreenInfo(admin, info);
@@ -3844,7 +3817,6 @@
* @return The device owner information. If it is not set returns {@code null}.
*/
public CharSequence getDeviceOwnerLockScreenInfo() {
- throwIfParentInstance("getDeviceOwnerLockScreenInfo");
if (mService != null) {
try {
return mService.getDeviceOwnerLockScreenInfo();
@@ -3876,7 +3848,6 @@
*/
public String[] setPackagesSuspended(@NonNull ComponentName admin, String[] packageNames,
boolean suspended) {
- throwIfParentInstance("setPackagesSuspended");
if (mService != null) {
try {
return mService.setPackagesSuspended(admin, packageNames, suspended);
@@ -3899,7 +3870,6 @@
*/
public boolean isPackageSuspended(@NonNull ComponentName admin, String packageName)
throws NameNotFoundException {
- throwIfParentInstance("isPackageSuspended");
if (mService != null) {
try {
return mService.isPackageSuspended(admin, packageName);
@@ -3921,7 +3891,6 @@
* @throws SecurityException if {@code admin} is not a profile owner.
*/
public void setProfileEnabled(@NonNull ComponentName admin) {
- throwIfParentInstance("setProfileEnabled");
if (mService != null) {
try {
mService.setProfileEnabled(admin);
@@ -3943,7 +3912,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public void setProfileName(@NonNull ComponentName admin, String profileName) {
- throwIfParentInstance("setProfileName");
if (mService != null) {
try {
mService.setProfileName(admin, profileName);
@@ -3962,7 +3930,6 @@
* @return Whether or not the package is registered as the profile owner.
*/
public boolean isProfileOwnerApp(String packageName) {
- throwIfParentInstance("isProfileOwnerApp");
if (mService != null) {
try {
ComponentName profileOwner = mService.getProfileOwner(myUserId());
@@ -4057,7 +4024,6 @@
*/
public void addPersistentPreferredActivity(@NonNull ComponentName admin, IntentFilter filter,
@NonNull ComponentName activity) {
- throwIfParentInstance("addPersistentPreferredActivity");
if (mService != null) {
try {
mService.addPersistentPreferredActivity(admin, filter, activity);
@@ -4080,7 +4046,6 @@
*/
public void clearPackagePersistentPreferredActivities(@NonNull ComponentName admin,
String packageName) {
- throwIfParentInstance("clearPackagePersistentPreferredActivities");
if (mService != null) {
try {
mService.clearPackagePersistentPreferredActivities(admin, packageName);
@@ -4109,7 +4074,6 @@
*/
public void setApplicationRestrictionsManagingPackage(@NonNull ComponentName admin,
@Nullable String packageName) throws NameNotFoundException {
- throwIfParentInstance("setApplicationRestrictionsManagingPackage");
if (mService != null) {
try {
if (!mService.setApplicationRestrictionsManagingPackage(admin, packageName)) {
@@ -4131,7 +4095,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public String getApplicationRestrictionsManagingPackage(@NonNull ComponentName admin) {
- throwIfParentInstance("getApplicationRestrictionsManagingPackage");
if (mService != null) {
try {
return mService.getApplicationRestrictionsManagingPackage(admin);
@@ -4151,7 +4114,6 @@
* that method.
*/
public boolean isCallerApplicationRestrictionsManagingPackage() {
- throwIfParentInstance("isCallerApplicationRestrictionsManagingPackage");
if (mService != null) {
try {
return mService.isCallerApplicationRestrictionsManagingPackage();
@@ -4197,7 +4159,6 @@
*/
public void setApplicationRestrictions(@Nullable ComponentName admin, String packageName,
Bundle settings) {
- throwIfParentInstance("setApplicationRestrictions");
if (mService != null) {
try {
mService.setApplicationRestrictions(admin, packageName, settings);
@@ -4296,7 +4257,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public void setCrossProfileCallerIdDisabled(@NonNull ComponentName admin, boolean disabled) {
- throwIfParentInstance("setCrossProfileCallerIdDisabled");
if (mService != null) {
try {
mService.setCrossProfileCallerIdDisabled(admin, disabled);
@@ -4317,7 +4277,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public boolean getCrossProfileCallerIdDisabled(@NonNull ComponentName admin) {
- throwIfParentInstance("getCrossProfileCallerIdDisabled");
if (mService != null) {
try {
return mService.getCrossProfileCallerIdDisabled(admin);
@@ -4358,7 +4317,6 @@
*/
public void setCrossProfileContactsSearchDisabled(@NonNull ComponentName admin,
boolean disabled) {
- throwIfParentInstance("setCrossProfileContactsSearchDisabled");
if (mService != null) {
try {
mService.setCrossProfileContactsSearchDisabled(admin, disabled);
@@ -4379,7 +4337,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public boolean getCrossProfileContactsSearchDisabled(@NonNull ComponentName admin) {
- throwIfParentInstance("getCrossProfileContactsSearchDisabled");
if (mService != null) {
try {
return mService.getCrossProfileContactsSearchDisabled(admin);
@@ -4450,7 +4407,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public void setBluetoothContactSharingDisabled(@NonNull ComponentName admin, boolean disabled) {
- throwIfParentInstance("setBluetoothContactSharingDisabled");
if (mService != null) {
try {
mService.setBluetoothContactSharingDisabled(admin, disabled);
@@ -4473,7 +4429,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public boolean getBluetoothContactSharingDisabled(@NonNull ComponentName admin) {
- throwIfParentInstance("getBluetoothContactSharingDisabled");
if (mService != null) {
try {
return mService.getBluetoothContactSharingDisabled(admin);
@@ -4517,7 +4472,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public void addCrossProfileIntentFilter(@NonNull ComponentName admin, IntentFilter filter, int flags) {
- throwIfParentInstance("addCrossProfileIntentFilter");
if (mService != null) {
try {
mService.addCrossProfileIntentFilter(admin, filter, flags);
@@ -4536,7 +4490,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public void clearCrossProfileIntentFilters(@NonNull ComponentName admin) {
- throwIfParentInstance("clearCrossProfileIntentFilters");
if (mService != null) {
try {
mService.clearCrossProfileIntentFilters(admin);
@@ -4566,7 +4519,6 @@
*/
public boolean setPermittedAccessibilityServices(@NonNull ComponentName admin,
List<String> packageNames) {
- throwIfParentInstance("setPermittedAccessibilityServices");
if (mService != null) {
try {
return mService.setPermittedAccessibilityServices(admin, packageNames);
@@ -4588,7 +4540,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public List<String> getPermittedAccessibilityServices(@NonNull ComponentName admin) {
- throwIfParentInstance("getPermittedAccessibilityServices");
if (mService != null) {
try {
return mService.getPermittedAccessibilityServices(admin);
@@ -4666,7 +4617,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public boolean setPermittedInputMethods(@NonNull ComponentName admin, List<String> packageNames) {
- throwIfParentInstance("setPermittedInputMethods");
if (mService != null) {
try {
return mService.setPermittedInputMethods(admin, packageNames);
@@ -4689,7 +4639,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public List<String> getPermittedInputMethods(@NonNull ComponentName admin) {
- throwIfParentInstance("getPermittedInputMethods");
if (mService != null) {
try {
return mService.getPermittedInputMethods(admin);
@@ -4885,7 +4834,6 @@
public UserHandle createAndManageUser(@NonNull ComponentName admin, @NonNull String name,
@NonNull ComponentName profileOwner, @Nullable PersistableBundle adminExtras,
int flags) {
- throwIfParentInstance("createAndManageUser");
try {
return mService.createAndManageUser(admin, name, profileOwner, adminExtras, flags);
} catch (RemoteException re) {
@@ -4903,7 +4851,6 @@
* @throws SecurityException if {@code admin} is not a device owner.
*/
public boolean removeUser(@NonNull ComponentName admin, UserHandle userHandle) {
- throwIfParentInstance("removeUser");
try {
return mService.removeUser(admin, userHandle);
} catch (RemoteException re) {
@@ -4921,7 +4868,6 @@
* @see Intent#ACTION_USER_FOREGROUND
*/
public boolean switchUser(@NonNull ComponentName admin, @Nullable UserHandle userHandle) {
- throwIfParentInstance("switchUser");
try {
return mService.switchUser(admin, userHandle);
} catch (RemoteException re) {
@@ -4947,7 +4893,6 @@
* @see {@link #setApplicationRestrictionsManagingPackage}
*/
public Bundle getApplicationRestrictions(@Nullable ComponentName admin, String packageName) {
- throwIfParentInstance("getApplicationRestrictions");
if (mService != null) {
try {
return mService.getApplicationRestrictions(admin, packageName);
@@ -4970,7 +4915,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public void addUserRestriction(@NonNull ComponentName admin, String key) {
- throwIfParentInstance("addUserRestriction");
if (mService != null) {
try {
mService.setUserRestriction(admin, key, true);
@@ -4992,7 +4936,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public void clearUserRestriction(@NonNull ComponentName admin, String key) {
- throwIfParentInstance("clearUserRestriction");
if (mService != null) {
try {
mService.setUserRestriction(admin, key, false);
@@ -5014,7 +4957,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public Bundle getUserRestrictions(@NonNull ComponentName admin) {
- throwIfParentInstance("getUserRestrictions");
Bundle ret = null;
if (mService != null) {
try {
@@ -5059,7 +5001,6 @@
*/
public boolean setApplicationHidden(@NonNull ComponentName admin, String packageName,
boolean hidden) {
- throwIfParentInstance("setApplicationHidden");
if (mService != null) {
try {
return mService.setApplicationHidden(admin, packageName, hidden);
@@ -5079,7 +5020,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public boolean isApplicationHidden(@NonNull ComponentName admin, String packageName) {
- throwIfParentInstance("isApplicationHidden");
if (mService != null) {
try {
return mService.isApplicationHidden(admin, packageName);
@@ -5099,7 +5039,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public void enableSystemApp(@NonNull ComponentName admin, String packageName) {
- throwIfParentInstance("enableSystemApp");
if (mService != null) {
try {
mService.enableSystemApp(admin, packageName);
@@ -5120,7 +5059,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public int enableSystemApp(@NonNull ComponentName admin, Intent intent) {
- throwIfParentInstance("enableSystemApp");
if (mService != null) {
try {
return mService.enableSystemAppWithIntent(admin, intent);
@@ -5153,7 +5091,6 @@
*/
public void setAccountManagementDisabled(@NonNull ComponentName admin, String accountType,
boolean disabled) {
- throwIfParentInstance("setAccountManagementDisabled");
if (mService != null) {
try {
mService.setAccountManagementDisabled(admin, accountType, disabled);
@@ -5174,7 +5111,6 @@
* @see #setAccountManagementDisabled
*/
public String[] getAccountTypesWithManagementDisabled() {
- throwIfParentInstance("getAccountTypesWithManagementDisabled");
return getAccountTypesWithManagementDisabledAsUser(myUserId());
}
@@ -5212,7 +5148,6 @@
*/
public void setLockTaskPackages(@NonNull ComponentName admin, String[] packages)
throws SecurityException {
- throwIfParentInstance("setLockTaskPackages");
if (mService != null) {
try {
mService.setLockTaskPackages(admin, packages);
@@ -5229,7 +5164,6 @@
* @hide
*/
public String[] getLockTaskPackages(@NonNull ComponentName admin) {
- throwIfParentInstance("getLockTaskPackages");
if (mService != null) {
try {
return mService.getLockTaskPackages(admin);
@@ -5246,7 +5180,6 @@
* @param pkg The package to check
*/
public boolean isLockTaskPermitted(String pkg) {
- throwIfParentInstance("isLockTaskPermitted");
if (mService != null) {
try {
return mService.isLockTaskPermitted(pkg);
@@ -5295,7 +5228,6 @@
* @throws SecurityException if {@code admin} is not a device owner.
*/
public void setGlobalSetting(@NonNull ComponentName admin, String setting, String value) {
- throwIfParentInstance("setGlobalSetting");
if (mService != null) {
try {
mService.setGlobalSetting(admin, setting, value);
@@ -5328,7 +5260,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public void setSecureSetting(@NonNull ComponentName admin, String setting, String value) {
- throwIfParentInstance("setSecureSetting");
if (mService != null) {
try {
mService.setSecureSetting(admin, setting, value);
@@ -5352,7 +5283,6 @@
*/
public void setRestrictionsProvider(@NonNull ComponentName admin,
@Nullable ComponentName provider) {
- throwIfParentInstance("setRestrictionsProvider");
if (mService != null) {
try {
mService.setRestrictionsProvider(admin, provider);
@@ -5370,7 +5300,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public void setMasterVolumeMuted(@NonNull ComponentName admin, boolean on) {
- throwIfParentInstance("setMasterVolumeMuted");
if (mService != null) {
try {
mService.setMasterVolumeMuted(admin, on);
@@ -5388,7 +5317,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public boolean isMasterVolumeMuted(@NonNull ComponentName admin) {
- throwIfParentInstance("isMasterVolumeMuted");
if (mService != null) {
try {
return mService.isMasterVolumeMuted(admin);
@@ -5409,7 +5337,6 @@
*/
public void setUninstallBlocked(@NonNull ComponentName admin, String packageName,
boolean uninstallBlocked) {
- throwIfParentInstance("setUninstallBlocked");
if (mService != null) {
try {
mService.setUninstallBlocked(admin, packageName, uninstallBlocked);
@@ -5435,7 +5362,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public boolean isUninstallBlocked(@Nullable ComponentName admin, String packageName) {
- throwIfParentInstance("isUninstallBlocked");
if (mService != null) {
try {
return mService.isUninstallBlocked(admin, packageName);
@@ -5463,7 +5389,6 @@
* @see #getCrossProfileWidgetProviders(android.content.ComponentName)
*/
public boolean addCrossProfileWidgetProvider(@NonNull ComponentName admin, String packageName) {
- throwIfParentInstance("addCrossProfileWidgetProvider");
if (mService != null) {
try {
return mService.addCrossProfileWidgetProvider(admin, packageName);
@@ -5491,7 +5416,6 @@
*/
public boolean removeCrossProfileWidgetProvider(
@NonNull ComponentName admin, String packageName) {
- throwIfParentInstance("removeCrossProfileWidgetProvider");
if (mService != null) {
try {
return mService.removeCrossProfileWidgetProvider(admin, packageName);
@@ -5513,7 +5437,6 @@
* @throws SecurityException if {@code admin} is not a profile owner.
*/
public List<String> getCrossProfileWidgetProviders(@NonNull ComponentName admin) {
- throwIfParentInstance("getCrossProfileWidgetProviders");
if (mService != null) {
try {
List<String> providers = mService.getCrossProfileWidgetProviders(admin);
@@ -5535,7 +5458,6 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public void setUserIcon(@NonNull ComponentName admin, Bitmap icon) {
- throwIfParentInstance("setUserIcon");
try {
mService.setUserIcon(admin, icon);
} catch (RemoteException re) {
@@ -5555,7 +5477,6 @@
* @see SystemUpdatePolicy
*/
public void setSystemUpdatePolicy(@NonNull ComponentName admin, SystemUpdatePolicy policy) {
- throwIfParentInstance("setSystemUpdatePolicy");
if (mService != null) {
try {
mService.setSystemUpdatePolicy(admin, policy);
@@ -5571,7 +5492,6 @@
* @return The current policy object, or {@code null} if no policy is set.
*/
public SystemUpdatePolicy getSystemUpdatePolicy() {
- throwIfParentInstance("getSystemUpdatePolicy");
if (mService != null) {
try {
return mService.getSystemUpdatePolicy();
@@ -5597,7 +5517,6 @@
* @throws SecurityException if {@code admin} is not a device owner.
*/
public boolean setKeyguardDisabled(@NonNull ComponentName admin, boolean disabled) {
- throwIfParentInstance("setKeyguardDisabled");
try {
return mService.setKeyguardDisabled(admin, disabled);
} catch (RemoteException re) {
@@ -5616,7 +5535,6 @@
* @throws SecurityException if {@code admin} is not a device owner.
*/
public boolean setStatusBarDisabled(@NonNull ComponentName admin, boolean disabled) {
- throwIfParentInstance("setStatusBarDisabled");
try {
return mService.setStatusBarDisabled(admin, disabled);
} catch (RemoteException re) {
@@ -5662,7 +5580,6 @@
* @see #setPermissionGrantState
*/
public void setPermissionPolicy(@NonNull ComponentName admin, int policy) {
- throwIfParentInstance("setPermissionPolicy");
try {
mService.setPermissionPolicy(admin, policy);
} catch (RemoteException re) {
@@ -5677,7 +5594,6 @@
* @return the current policy for future permission requests.
*/
public int getPermissionPolicy(ComponentName admin) {
- throwIfParentInstance("getPermissionPolicy");
try {
return mService.getPermissionPolicy(admin);
} catch (RemoteException re) {
@@ -5714,7 +5630,6 @@
*/
public boolean setPermissionGrantState(@NonNull ComponentName admin, String packageName,
String permission, int grantState) {
- throwIfParentInstance("setPermissionGrantState");
try {
return mService.setPermissionGrantState(admin, packageName, permission, grantState);
} catch (RemoteException re) {
@@ -5743,7 +5658,6 @@
*/
public int getPermissionGrantState(@NonNull ComponentName admin, String packageName,
String permission) {
- throwIfParentInstance("getPermissionGrantState");
try {
return mService.getPermissionGrantState(admin, packageName, permission);
} catch (RemoteException re) {
@@ -5759,7 +5673,6 @@
* @throws IllegalArgumentException if the supplied action is not valid.
*/
public boolean isProvisioningAllowed(String action) {
- throwIfParentInstance("isProvisioningAllowed");
try {
return mService.isProvisioningAllowed(action);
} catch (RemoteException re) {
@@ -5775,7 +5688,6 @@
* @return if this user is a managed profile of another user.
*/
public boolean isManagedProfile(@NonNull ComponentName admin) {
- throwIfParentInstance("isManagedProfile");
try {
return mService.isManagedProfile(admin);
} catch (RemoteException re) {
@@ -5809,7 +5721,6 @@
* @throws SecurityException if {@code admin} is not a device owner.
*/
public String getWifiMacAddress(@NonNull ComponentName admin) {
- throwIfParentInstance("getWifiMacAddress");
try {
return mService.getWifiMacAddress(admin);
} catch (RemoteException re) {
@@ -5826,7 +5737,6 @@
* @see TelephonyManager#CALL_STATE_IDLE
*/
public void reboot(@NonNull ComponentName admin) {
- throwIfParentInstance("reboot");
try {
mService.reboot(admin);
} catch (RemoteException re) {
@@ -5852,8 +5762,7 @@
* @throws SecurityException if {@code admin} is not an active administrator.
*/
public void setShortSupportMessage(@NonNull ComponentName admin,
- @Nullable String message) {
- throwIfParentInstance("setShortSupportMessage");
+ @Nullable CharSequence message) {
if (mService != null) {
try {
mService.setShortSupportMessage(admin, message);
@@ -5867,12 +5776,11 @@
* Called by a device admin to get the short support message.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @return The message set by {@link #setShortSupportMessage(ComponentName, String)} or null if
- * no message has been set.
+ * @return The message set by {@link #setShortSupportMessage(ComponentName, CharSequence)} or
+ * null if no message has been set.
* @throws SecurityException if {@code admin} is not an active administrator.
*/
- public String getShortSupportMessage(@NonNull ComponentName admin) {
- throwIfParentInstance("getShortSupportMessage");
+ public CharSequence getShortSupportMessage(@NonNull ComponentName admin) {
if (mService != null) {
try {
return mService.getShortSupportMessage(admin);
@@ -5898,8 +5806,7 @@
* @throws SecurityException if {@code admin} is not an active administrator.
*/
public void setLongSupportMessage(@NonNull ComponentName admin,
- @Nullable String message) {
- throwIfParentInstance("setLongSupportMessage");
+ @Nullable CharSequence message) {
if (mService != null) {
try {
mService.setLongSupportMessage(admin, message);
@@ -5913,12 +5820,11 @@
* Called by a device admin to get the long support message.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @return The message set by {@link #setLongSupportMessage(ComponentName, String)} or null if
- * no message has been set.
+ * @return The message set by {@link #setLongSupportMessage(ComponentName, CharSequence)} or
+ * null if no message has been set.
* @throws SecurityException if {@code admin} is not an active administrator.
*/
- public String getLongSupportMessage(@NonNull ComponentName admin) {
- throwIfParentInstance("getLongSupportMessage");
+ public CharSequence getLongSupportMessage(@NonNull ComponentName admin) {
if (mService != null) {
try {
return mService.getLongSupportMessage(admin);
@@ -5934,11 +5840,12 @@
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param userHandle user id the admin is running as.
- * @return The message set by {@link #setShortSupportMessage(ComponentName, String)}
+ * @return The message set by {@link #setShortSupportMessage(ComponentName, CharSequence)}
*
* @hide
*/
- public String getShortSupportMessageForUser(@NonNull ComponentName admin, int userHandle) {
+ public CharSequence getShortSupportMessageForUser(@NonNull ComponentName admin,
+ int userHandle) {
if (mService != null) {
try {
return mService.getShortSupportMessageForUser(admin, userHandle);
@@ -5955,11 +5862,11 @@
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param userHandle user id the admin is running as.
- * @return The message set by {@link #setLongSupportMessage(ComponentName, String)}
+ * @return The message set by {@link #setLongSupportMessage(ComponentName, CharSequence)}
*
* @hide
*/
- public String getLongSupportMessageForUser(@NonNull ComponentName admin, int userHandle) {
+ public CharSequence getLongSupportMessageForUser(@NonNull ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getLongSupportMessageForUser(admin, userHandle);
@@ -6015,7 +5922,6 @@
* @throws SecurityException if {@code admin} is not a profile owner.
*/
public DevicePolicyManager getParentProfileInstance(@NonNull ComponentName admin) {
- throwIfParentInstance("getParentProfileInstance");
try {
if (!mService.isManagedProfile(admin)) {
throw new SecurityException("The current user does not have a parent profile.");
@@ -6042,7 +5948,6 @@
* @see #retrieveSecurityLogs
*/
public void setSecurityLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
- throwIfParentInstance("setSecurityLoggingEnabled");
try {
mService.setSecurityLoggingEnabled(admin, enabled);
} catch (RemoteException re) {
@@ -6061,7 +5966,6 @@
* @throws SecurityException if {@code admin} is not a device owner.
*/
public boolean isSecurityLoggingEnabled(@NonNull ComponentName admin) {
- throwIfParentInstance("isSecurityLoggingEnabled");
try {
return mService.isSecurityLoggingEnabled(admin);
} catch (RemoteException re) {
@@ -6085,7 +5989,6 @@
* @throws SecurityException if {@code admin} is not a device owner.
*/
public List<SecurityEvent> retrieveSecurityLogs(@NonNull ComponentName admin) {
- throwIfParentInstance("retrieveSecurityLogs");
try {
ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(admin);
if (list != null) {
@@ -6131,7 +6034,6 @@
* @throws SecurityException if {@code admin} is not a device owner.
*/
public List<SecurityEvent> retrievePreRebootSecurityLogs(@NonNull ComponentName admin) {
- throwIfParentInstance("retrievePreRebootSecurityLogs");
try {
ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(admin);
return list.getList();
@@ -6149,12 +6051,13 @@
* {@link android.app.KeyguardManager#createConfirmDeviceCredentialIntent}.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param color The 32bit representation of the color to be used.
+ * @param color The 24bit (0xRRGGBB) representation of the color to be used.
* @throws SecurityException if {@code admin} is not a profile owner.
*/
public void setOrganizationColor(@NonNull ComponentName admin, int color) {
- throwIfParentInstance("setOrganizationColor");
try {
+ // always enforce alpha channel to have 100% opacity
+ color |= 0xFF000000;
mService.setOrganizationColor(admin, color);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
@@ -6166,7 +6069,7 @@
*
* Sets the color used for customization.
*
- * @param color The 32bit representation of the color to be used.
+ * @param color The 24bit (0xRRGGBB) representation of the color to be used.
* @param userId which user to set the color to.
* @RequiresPermission(allOf = {
* Manifest.permission.MANAGE_USERS,
@@ -6174,6 +6077,8 @@
*/
public void setOrganizationColorForUser(@ColorInt int color, @UserIdInt int userId) {
try {
+ // always enforce alpha channel to have 100% opacity
+ color |= 0xFF000000;
mService.setOrganizationColorForUser(color, userId);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
@@ -6185,11 +6090,10 @@
* This color is used as background color of the confirm credentials screen for that user.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @return The 32bit representation of the color to be used.
+ * @return The 24bit (0xRRGGBB) representation of the color to be used.
* @throws SecurityException if {@code admin} is not a profile owner.
*/
- public int getOrganizationColor(@NonNull ComponentName admin) {
- throwIfParentInstance("getOrganizationColor");
+ public @ColorInt int getOrganizationColor(@NonNull ComponentName admin) {
try {
return mService.getOrganizationColor(admin);
} catch (RemoteException re) {
@@ -6202,9 +6106,9 @@
* Retrieve the customization color for a given user.
*
* @param userHandle The user id of the user we're interested in.
- * @return The 32bit representation of the color to be used.
+ * @return The 24bit (0xRRGGBB) representation of the color to be used.
*/
- public int getOrganizationColorForUser(int userHandle) {
+ public @ColorInt int getOrganizationColorForUser(int userHandle) {
try {
return mService.getOrganizationColorForUser(userHandle);
} catch (RemoteException re) {
@@ -6224,8 +6128,7 @@
* @param title The organization name or {@code null} to clear a previously set name.
* @throws SecurityException if {@code admin} is not a profile owner.
*/
- public void setOrganizationName(@NonNull ComponentName admin, @Nullable String title) {
- throwIfParentInstance("setOrganizationName");
+ public void setOrganizationName(@NonNull ComponentName admin, @Nullable CharSequence title) {
try {
mService.setOrganizationName(admin, title);
} catch (RemoteException re) {
@@ -6241,8 +6144,7 @@
* @return The organization name or {@code null} if none is set.
* @throws SecurityException if {@code admin} is not a profile owner.
*/
- public String getOrganizationName(@NonNull ComponentName admin) {
- throwIfParentInstance("getOrganizationName");
+ public CharSequence getOrganizationName(@NonNull ComponentName admin) {
try {
return mService.getOrganizationName(admin);
} catch (RemoteException re) {
@@ -6258,7 +6160,7 @@
*
* @hide
*/
- public String getOrganizationNameForUser(int userHandle) {
+ public CharSequence getOrganizationNameForUser(int userHandle) {
try {
return mService.getOrganizationNameForUser(userHandle);
} catch (RemoteException re) {
@@ -6368,10 +6270,4 @@
throw re.rethrowFromSystemServer();
}
}
-
- private void throwIfParentInstance(String functionName) {
- if (mParentInstance) {
- throw new SecurityException(functionName + " cannot be called on the parent instance");
- }
- }
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 6df1038..cba64c2 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -269,13 +269,13 @@
String getWifiMacAddress(in ComponentName admin);
void reboot(in ComponentName admin);
- void setShortSupportMessage(in ComponentName admin, in String message);
- String getShortSupportMessage(in ComponentName admin);
- void setLongSupportMessage(in ComponentName admin, in String message);
- String getLongSupportMessage(in ComponentName admin);
+ void setShortSupportMessage(in ComponentName admin, in CharSequence message);
+ CharSequence getShortSupportMessage(in ComponentName admin);
+ void setLongSupportMessage(in ComponentName admin, in CharSequence message);
+ CharSequence getLongSupportMessage(in ComponentName admin);
- String getShortSupportMessageForUser(in ComponentName admin, int userHandle);
- String getLongSupportMessageForUser(in ComponentName admin, int userHandle);
+ CharSequence getShortSupportMessageForUser(in ComponentName admin, int userHandle);
+ CharSequence getLongSupportMessageForUser(in ComponentName admin, int userHandle);
boolean isSeparateProfileChallengeAllowed(int userHandle);
@@ -284,9 +284,9 @@
int getOrganizationColor(in ComponentName admin);
int getOrganizationColorForUser(int userHandle);
- void setOrganizationName(in ComponentName admin, in String title);
- String getOrganizationName(in ComponentName admin);
- String getOrganizationNameForUser(int userHandle);
+ void setOrganizationName(in ComponentName admin, in CharSequence title);
+ CharSequence getOrganizationName(in ComponentName admin);
+ CharSequence getOrganizationNameForUser(int userHandle);
int getUserProvisioningState();
void setUserProvisioningState(int state, int userHandle);
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 828ac38..c84a0dc 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -138,12 +138,28 @@
*/
public static final int PRIORITY_TOP_APP = 40;
+ /**
+ * Adjustment of {@link #getPriority} if the app has often (50% or more of the time)
+ * been running jobs.
+ * @hide
+ */
+ public static final int PRIORITY_ADJ_OFTEN_RUNNING = -40;
+
+ /**
+ * Adjustment of {@link #getPriority} if the app has always (90% or more of the time)
+ * been running jobs.
+ * @hide
+ */
+ public static final int PRIORITY_ADJ_ALWAYS_RUNNING = -80;
+
private final int jobId;
private final PersistableBundle extras;
private final ComponentName service;
private final boolean requireCharging;
private final boolean requireDeviceIdle;
private final TriggerContentUri[] triggerContentUris;
+ private final long triggerContentUpdateDelay;
+ private final long triggerContentMaxDelay;
private final boolean hasEarlyConstraint;
private final boolean hasLateConstraint;
private final int networkType;
@@ -207,6 +223,22 @@
}
/**
+ * When triggering on content URI changes, this is the delay from when a change
+ * is detected until the job is scheduled.
+ */
+ public long getTriggerContentUpdateDelay() {
+ return triggerContentUpdateDelay;
+ }
+
+ /**
+ * When triggering on content URI changes, this is the maximum delay we will
+ * use before scheduling the job.
+ */
+ public long getTriggerContentMaxDelay() {
+ return triggerContentMaxDelay;
+ }
+
+ /**
* One of {@link android.app.job.JobInfo#NETWORK_TYPE_ANY},
* {@link android.app.job.JobInfo#NETWORK_TYPE_NONE}, or
* {@link android.app.job.JobInfo#NETWORK_TYPE_UNMETERED}.
@@ -254,7 +286,8 @@
}
/**
- * Flex time for this job. Only valid if this is a periodic job.
+ * Flex time for this job. Only valid if this is a periodic job. The job can
+ * execute at any time in a window of flex length at the end of the period.
*/
public long getFlexMillis() {
long interval = getIntervalMillis();
@@ -306,6 +339,8 @@
requireCharging = in.readInt() == 1;
requireDeviceIdle = in.readInt() == 1;
triggerContentUris = in.createTypedArray(TriggerContentUri.CREATOR);
+ triggerContentUpdateDelay = in.readLong();
+ triggerContentMaxDelay = in.readLong();
networkType = in.readInt();
minLatencyMillis = in.readLong();
maxExecutionDelayMillis = in.readLong();
@@ -329,6 +364,8 @@
triggerContentUris = b.mTriggerContentUris != null
? b.mTriggerContentUris.toArray(new TriggerContentUri[b.mTriggerContentUris.size()])
: null;
+ triggerContentUpdateDelay = b.mTriggerContentUpdateDelay;
+ triggerContentMaxDelay = b.mTriggerContentMaxDelay;
networkType = b.mNetworkType;
minLatencyMillis = b.mMinLatencyMillis;
maxExecutionDelayMillis = b.mMaxExecutionDelayMillis;
@@ -356,6 +393,8 @@
out.writeInt(requireCharging ? 1 : 0);
out.writeInt(requireDeviceIdle ? 1 : 0);
out.writeTypedArray(triggerContentUris, flags);
+ out.writeLong(triggerContentUpdateDelay);
+ out.writeLong(triggerContentMaxDelay);
out.writeInt(networkType);
out.writeLong(minLatencyMillis);
out.writeLong(maxExecutionDelayMillis);
@@ -467,6 +506,8 @@
private boolean mRequiresDeviceIdle;
private int mNetworkType;
private ArrayList<TriggerContentUri> mTriggerContentUris;
+ private long mTriggerContentUpdateDelay = -1;
+ private long mTriggerContentMaxDelay = -1;
private boolean mIsPersisted;
// One-off parameters.
private long mMinLatencyMillis;
@@ -573,6 +614,27 @@
}
/**
+ * Set the delay (in milliseconds) from when a content change is detected until
+ * the job is scheduled. If there are more changes during that time, the delay
+ * will be reset to start at the time of the most recent change.
+ * @param durationMs Delay after most recent content change, in milliseconds.
+ */
+ public Builder setTriggerContentUpdateDelay(long durationMs) {
+ mTriggerContentUpdateDelay = durationMs;
+ return this;
+ }
+
+ /**
+ * Set the maximum total delay (in milliseconds) that is allowed from the first
+ * time a content change is detected until the job is scheduled.
+ * @param durationMs Delay after initial content change, in milliseconds.
+ */
+ public Builder setTriggerContentMaxDelay(long durationMs) {
+ mTriggerContentMaxDelay = durationMs;
+ return this;
+ }
+
+ /**
* Specify that this job should recur with the provided interval, not more than once per
* period. You have no control over when within this interval this job will be executed,
* only the guarantee that it will be executed at most once within this interval.
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 207b70a..831de4a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -765,6 +765,19 @@
= "android.intent.action.APPLICATION_PREFERENCES";
/**
+ * Activity Action: Launch an activity showing the app information.
+ * For applications which install other applications (such as app stores), it is recommended
+ * to handle this action for providing the app information to the user.
+ *
+ * <p>Input: {@link #EXTRA_PACKAGE_NAME} specifies the package whose information needs
+ * to be displayed.
+ * <p>Output: Nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_SHOW_APP_INFO
+ = "android.intent.action.SHOW_APP_INFO";
+
+ /**
* Represents a shortcut/live folder icon resource.
*
* @see Intent#ACTION_CREATE_SHORTCUT
@@ -1404,6 +1417,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.
@@ -1673,9 +1696,7 @@
* Type: String
* </p>
*
- * @hide
*/
- @SystemApi
public static final String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";
/**
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 104feb5..585d2a3 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -366,6 +366,9 @@
*
* <p>NOTE: {@code WebView} does not honor this flag.
*
+ * <p>This flag is ignored on Android N and above if an Android Network Security Config is
+ * present.
+ *
* <p>This flag comes from
* {@link android.R.styleable#AndroidManifestApplication_usesCleartextTraffic
* android:usesCleartextTraffic} of the <application> tag.
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 6b3d4f1..430c7e7 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -18,6 +18,7 @@
import android.content.ComponentName;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IOnAppsChangedListener;
import android.content.pm.ParceledListSlice;
@@ -37,7 +38,7 @@
void addOnAppsChangedListener(String callingPackage, in IOnAppsChangedListener listener);
void removeOnAppsChangedListener(in IOnAppsChangedListener listener);
ParceledListSlice getLauncherActivities(String packageName, in UserHandle user);
- ResolveInfo resolveActivity(in Intent intent, in UserHandle user);
+ ActivityInfo resolveActivity(in ComponentName component, in UserHandle user);
void startActivityAsUser(in ComponentName component, in Rect sourceBounds,
in Bundle opts, in UserHandle user);
void showAppDetailsAsUser(in ComponentName component, in Rect sourceBounds,
@@ -47,17 +48,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/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 6fce36b..0526815 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -388,6 +388,15 @@
void deleteApplicationCacheFiles(in String packageName, IPackageDataObserver observer);
/**
+ * Delete all the cache files in an applications cache directory
+ * @param packageName The package name of the application whose cache
+ * files need to be deleted
+ * @param userId the user to delete application cache for
+ * @param observer a callback used to notify when the deletion is finished.
+ */
+ void deleteApplicationCacheFilesAsUser(in String packageName, int userId, IPackageDataObserver observer);
+
+ /**
* Clear the user data directory of an application.
* @param packageName The package name of the application whose cache
* files need to be deleted
diff --git a/core/java/android/content/pm/IShortcutService.aidl b/core/java/android/content/pm/IShortcutService.aidl
index 31d377b..9c90346 100644
--- a/core/java/android/content/pm/IShortcutService.aidl
+++ b/core/java/android/content/pm/IShortcutService.aidl
@@ -28,11 +28,12 @@
ParceledListSlice getDynamicShortcuts(String packageName, int userId);
- boolean addDynamicShortcut(String packageName, in ShortcutInfo shortcutInfo, int userId);
+ boolean addDynamicShortcuts(String packageName, in ParceledListSlice shortcutInfoList,
+ int userId);
- void deleteDynamicShortcut(String packageName, in String shortcutId, int userId);
+ void removeDynamicShortcuts(String packageName, in List shortcutIds, int userId);
- void deleteAllDynamicShortcuts(String packageName, int userId);
+ void removeAllDynamicShortcuts(String packageName, int userId);
ParceledListSlice getPinnedShortcuts(String packageName, int userId);
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
index 40e1a9f..2beca7b 100644
--- a/core/java/android/content/pm/LauncherActivityInfo.java
+++ b/core/java/android/content/pm/LauncherActivityInfo.java
@@ -39,7 +39,6 @@
private ActivityInfo mActivityInfo;
private ComponentName mComponentName;
- private ResolveInfo mResolveInfo;
private UserHandle mUser;
/**
@@ -49,11 +48,10 @@
* @param info ResolveInfo from which to create the LauncherActivityInfo.
* @param user The UserHandle of the profile to which this activity belongs.
*/
- LauncherActivityInfo(Context context, ResolveInfo info, UserHandle user) {
+ LauncherActivityInfo(Context context, ActivityInfo info, UserHandle user) {
this(context);
- mResolveInfo = info;
- mActivityInfo = info.activityInfo;
- mComponentName = LauncherApps.getComponentName(info);
+ mActivityInfo = info;
+ mComponentName = new ComponentName(info.packageName, info.name);
mUser = user;
}
@@ -91,7 +89,7 @@
* @return The label for the activity.
*/
public CharSequence getLabel() {
- return mResolveInfo.loadLabel(mPm);
+ return mActivityInfo.loadLabel(mPm);
}
/**
@@ -103,7 +101,7 @@
* @return The drawable associated with the activity.
*/
public Drawable getIcon(int density) {
- final int iconRes = mResolveInfo.getIconResourceInternal();
+ final int iconRes = mActivityInfo.getIconResource();
Drawable icon = null;
// Get the preferred density icon from the app's resources
if (density != 0 && iconRes != 0) {
@@ -116,7 +114,7 @@
}
// Get the default density icon
if (icon == null) {
- icon = mResolveInfo.loadIcon(mPm);
+ icon = mActivityInfo.loadIcon(mPm);
}
return icon;
}
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index d865f34..824722d 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -30,6 +31,7 @@
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
@@ -37,6 +39,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -205,6 +208,9 @@
String mPackage;
@Nullable
+ List<String> mShortcutIds;
+
+ @Nullable
ComponentName mActivity;
@QueryFlags
@@ -229,6 +235,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) {
@@ -250,6 +264,13 @@
mPm = context.getPackageManager();
}
+ /** @hide */
+ @TestApi
+ public LauncherApps(Context context) {
+ this(context, ILauncherApps.Stub.asInterface(
+ ServiceManager.getService(Context.LAUNCHER_APPS_SERVICE)));
+ }
+
/**
* Retrieves a list of launchable activities that match {@link Intent#ACTION_MAIN} and
* {@link Intent#CATEGORY_LAUNCHER}, for a specified user.
@@ -271,7 +292,7 @@
}
ArrayList<LauncherActivityInfo> lais = new ArrayList<LauncherActivityInfo>();
for (ResolveInfo ri : activities.getList()) {
- LauncherActivityInfo lai = new LauncherActivityInfo(mContext, ri, user);
+ LauncherActivityInfo lai = new LauncherActivityInfo(mContext, ri.activityInfo, user);
if (DEBUG) {
Log.v(TAG, "Returning activity for profile " + user + " : "
+ lai.getComponentName());
@@ -281,10 +302,6 @@
return lais;
}
- static ComponentName getComponentName(ResolveInfo ri) {
- return new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
- }
-
/**
* Returns the activity info for a given intent and user handle, if it resolves. Otherwise it
* returns null.
@@ -295,9 +312,9 @@
*/
public LauncherActivityInfo resolveActivity(Intent intent, UserHandle user) {
try {
- ResolveInfo ri = mService.resolveActivity(intent, user);
- if (ri != null) {
- LauncherActivityInfo info = new LauncherActivityInfo(mContext, ri, user);
+ ActivityInfo ai = mService.resolveActivity(intent.getComponent(), user);
+ if (ai != null) {
+ LauncherActivityInfo info = new LauncherActivityInfo(mContext, ai, user);
return info;
}
} catch (RemoteException re) {
@@ -369,6 +386,7 @@
*
* @return An {@link ApplicationInfo} containing information about the package or
* null of the package isn't found.
+ * @hide
*/
public ApplicationInfo getApplicationInfo(String packageName, @ApplicationInfoFlags int flags,
UserHandle user) {
@@ -429,7 +447,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 +456,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.
*
@@ -483,21 +491,24 @@
}
/**
- * 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 shortcut The target shortcut.
- * @param user The UserHandle of the profile.
+ * @hide kept for testing.
*/
- public int getShortcutIconResId(@NonNull ShortcutInfo shortcut, @NonNull UserHandle user) {
- try {
- return mService.getShortcutIconResId(mContext.getPackageName(), shortcut, user);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ public int getShortcutIconResId(@NonNull ShortcutInfo shortcut) {
+ return shortcut.getIconResourceId();
+ }
+
+ /**
+ * @hide kept for testing.
+ */
+ public int getShortcutIconResId(@NonNull String packageName, @NonNull String shortcutId,
+ @NonNull UserHandle user) {
+ final ShortcutQuery q = new ShortcutQuery();
+ q.setPackage(packageName);
+ q.setShortcutIds(Arrays.asList(shortcutId));
+ q.setQueryFlags(ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
+ final List<ShortcutInfo> shortcuts = getShortcuts(q, user);
+
+ return shortcuts.size() > 0 ? shortcuts.get(0).getIconResourceId() : 0;
}
/**
@@ -508,12 +519,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 +569,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/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 39bc783..ade2248 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -4972,6 +4972,27 @@
IPackageDataObserver observer);
/**
+ * Attempts to delete the cache files associated with an application for a given user. Since
+ * this may take a little while, the result will be posted back to the given observer. A
+ * deletion will fail if the calling context lacks the
+ * {@link android.Manifest.permission#DELETE_CACHE_FILES} permission, if the named package
+ * cannot be found, or if the named package is a "system package". If {@code userId} does not
+ * belong to the calling user, the caller must have
+ * {@link android.Manifest.permission#INTERACT_ACROSS_USERS} permission.
+ *
+ * @param packageName The name of the package to delete
+ * @param userId the user for which the cache files needs to be deleted
+ * @param observer An observer callback to get notified when the cache file deletion is
+ * complete.
+ * {@link android.content.pm.IPackageDataObserver#onRemoveCompleted(String, boolean)}
+ * will be called when that happens. observer may be null to indicate that no
+ * callback is desired.
+ * @hide
+ */
+ public abstract void deleteApplicationCacheFilesAsUser(String packageName, int userId,
+ IPackageDataObserver observer);
+
+ /**
* Free storage by deleting LRU sorted list of cache files across
* all applications. If the currently available free storage
* on the device is greater than or equal to the requested
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index e85311d..995d2cc 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);
}
/**
@@ -87,6 +87,11 @@
/**
* Test if the given component is considered installed, enabled and a match
* for the given flags.
+ *
+ * <p>
+ * Expects at least one of {@link PackageManager#MATCH_DIRECT_BOOT_AWARE} and
+ * {@link PackageManager#MATCH_DIRECT_BOOT_UNAWARE} are specified in {@code flags}.
+ * </p>
*/
public boolean isMatch(ComponentInfo componentInfo, int flags) {
if (!isInstalled(flags)) return false;
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 1812575a..a900015 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;
@@ -33,6 +34,8 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
// TODO Enhance javadoc
/**
@@ -106,6 +109,11 @@
@Retention(RetentionPolicy.SOURCE)
public @interface CloneFlags {}
+ /**
+ * Shortcut category for
+ */
+ public static final String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation";
+
private final String mId;
@NonNull
@@ -123,6 +131,9 @@
@Nullable
private String mText;
+ @NonNull
+ private List<String> mCategories;
+
/**
* Intent *with extras removed*.
*/
@@ -153,7 +164,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
@@ -163,6 +178,7 @@
mIcon = b.mIcon;
mTitle = b.mTitle;
mText = b.mText;
+ mCategories = clone(b.mCategories);
mIntent = b.mIntent;
if (mIntent != null) {
final Bundle intentExtras = mIntent.getExtras();
@@ -176,6 +192,10 @@
updateTimestamp();
}
+ private <T> ArrayList<T> clone(List<T> source) {
+ return (source == null) ? null : new ArrayList<>(source);
+ }
+
/**
* Throws if any of the mandatory fields is not set.
*
@@ -191,22 +211,26 @@
* Copy constructor.
*/
private ShortcutInfo(ShortcutInfo source, @CloneFlags int cloneFlags) {
+ mUserId = source.mUserId;
mId = source.mId;
mPackageName = source.mPackageName;
mFlags = source.mFlags;
mLastChangedTimestamp = source.mLastChangedTimestamp;
+ // Just always keep it since it's cheep.
+ mIconResourceId = source.mIconResourceId;
+
if ((cloneFlags & CLONE_REMOVE_NON_KEY_INFO) == 0) {
mActivityComponent = source.mActivityComponent;
if ((cloneFlags & CLONE_REMOVE_ICON) == 0) {
mIcon = source.mIcon;
mBitmapPath = source.mBitmapPath;
- mIconResourceId = source.mIconResourceId;
}
mTitle = source.mTitle;
mText = source.mText;
+ mCategories = clone(source.mCategories);
if ((cloneFlags & CLONE_REMOVE_INTENT) == 0) {
mIntent = source.mIntent;
mIntentPersistableExtras = source.mIntentPersistableExtras;
@@ -238,6 +262,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");
@@ -255,6 +280,9 @@
if (source.mText != null) {
mText = source.mText;
}
+ if (source.mCategories != null) {
+ mCategories = clone(source.mCategories);
+ }
if (source.mIntent != null) {
mIntent = source.mIntent;
mIntentPersistableExtras = source.mIntentPersistableExtras;
@@ -318,6 +346,8 @@
private String mText;
+ private List<String> mCategories;
+
private Intent mIntent;
private int mWeight;
@@ -362,8 +392,9 @@
*
* <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)}.
+ * can use {@link ShortcutInfo#getIconResourceId()} if {@link #hasIconResource()} is true.
+ * Otherwise, if {@link #hasIconFile()} is true, use
+ * {@link LauncherApps#getShortcutIconFd} to load the image.
*/
@NonNull
public Builder setIcon(Icon icon) {
@@ -396,6 +427,18 @@
}
/**
+ * Sets categories for a shortcut. Launcher applications may use this information to
+ * categorise shortcuts.
+ *
+ * @see #SHORTCUT_CATEGORY_CONVERSATION
+ */
+ @NonNull
+ public Builder setCategories(List<String> categories) {
+ mCategories = categories;
+ return this;
+ }
+
+ /**
* Sets the intent of a shortcut. This is a mandatory field. The extras must only contain
* persistable information. (See {@link PersistableBundle}).
*/
@@ -493,6 +536,14 @@
}
/**
+ * Return the categories.
+ */
+ @Nullable
+ public List<String> getCategories() {
+ return mCategories;
+ }
+
+ /**
* Return the intent.
*
* <p>All shortcuts must have an intent, but this method will return null when
@@ -544,6 +595,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 +653,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 +662,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);
@@ -643,7 +706,9 @@
mIconResourceId = iconResourceId;
}
- /** @hide */
+ /**
+ * Get the resource ID for the icon, valid only when {@link #hasIconResource()} } is true.
+ */
public int getIconResourceId() {
return mIconResourceId;
}
@@ -661,12 +726,15 @@
private ShortcutInfo(Parcel source) {
final ClassLoader cl = getClass().getClassLoader();
+ mUserId = source.readInt();
mId = source.readString();
mPackageName = source.readString();
mActivityComponent = source.readParcelable(cl);
mIcon = source.readParcelable(cl);
mTitle = source.readString();
mText = source.readString();
+ mCategories = new ArrayList<>();
+ source.readStringList(mCategories);
mIntent = source.readParcelable(cl);
mIntentPersistableExtras = source.readParcelable(cl);
mWeight = source.readInt();
@@ -679,12 +747,14 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mUserId);
dest.writeString(mId);
dest.writeString(mPackageName);
dest.writeParcelable(mActivityComponent, flags);
dest.writeParcelable(mIcon, flags);
dest.writeString(mTitle);
dest.writeString(mText);
+ dest.writeStringList(mCategories);
dest.writeParcelable(mIntent, flags);
dest.writeParcelable(mIntentPersistableExtras, flags);
dest.writeInt(mWeight);
@@ -749,6 +819,9 @@
sb.append(", text=");
sb.append(secure ? "***" : mText);
+ sb.append(", categories=");
+ sb.append(mCategories);
+
sb.append(", icon=");
sb.append(mIcon);
@@ -784,17 +857,20 @@
}
/** @hide */
- public ShortcutInfo(String id, String packageName, ComponentName activityComponent,
- Icon icon, String title, String text, Intent intent,
+ public ShortcutInfo(
+ @UserIdInt int userId, String id, String packageName, ComponentName activityComponent,
+ Icon icon, String title, String text, List<String> categories, Intent intent,
PersistableBundle intentPersistableExtras,
int weight, PersistableBundle extras, long lastChangedTimestamp,
int flags, int iconResId, String bitmapPath) {
+ mUserId = userId;
mId = id;
mPackageName = packageName;
mActivityComponent = activityComponent;
mIcon = icon;
mTitle = title;
mText = text;
+ mCategories = clone(categories);
mIntent = intent;
mIntentPersistableExtras = intentPersistableExtras;
mWeight = weight;
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index e4a98b5..75803d3 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -16,8 +16,11 @@
package android.content.pm;
import android.annotation.NonNull;
+import android.annotation.TestApi;
import android.content.Context;
+import android.os.IBinder;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import com.android.internal.annotations.VisibleForTesting;
@@ -31,11 +34,11 @@
* <h3>Dynamic shortcuts and pinned shortcuts</h3>
*
* An application can publish shortcuts with {@link #setDynamicShortcuts(List)} and
- * {@link #addDynamicShortcut(ShortcutInfo)}. There can be at most
+ * {@link #addDynamicShortcuts(List)}. There can be at most
* {@link #getMaxDynamicShortcutCount()} number of dynamic shortcuts at a time from the same
* application.
- * A dynamic shortcut can be deleted with {@link #deleteDynamicShortcut(String)}, and apps
- * can also use {@link #deleteAllDynamicShortcuts()} to delete all dynamic shortcuts.
+ * A dynamic shortcut can be deleted with {@link #removeDynamicShortcuts(List)}, and apps
+ * can also use {@link #removeAllDynamicShortcuts()} to delete all dynamic shortcuts.
*
* <p>The shortcuts that are currently published by the above APIs are called "dynamic", because
* they can be removed by the creator application at any time. The user may "pin" dynamic shortcuts
@@ -58,11 +61,11 @@
*
* <h3>Rate limiting</h3>
*
- * Calls to {@link #setDynamicShortcuts(List)}, {@link #addDynamicShortcut(ShortcutInfo)},
+ * Calls to {@link #setDynamicShortcuts(List)}, {@link #addDynamicShortcuts(List)},
* and {@link #updateShortcuts(List)} will be
* rate-limited. An application can call these methods at most
* {@link #getRemainingCallCount()} times until the rate-limiting counter is reset,
- * which happens at a certain time every day.
+ * which happens every hour.
*
* <p>An application can use {@link #getRateLimitResetTime()} to get the next reset time.
*
@@ -97,6 +100,15 @@
}
/**
+ * @hide
+ */
+ @TestApi
+ public ShortcutManager(Context context) {
+ this(context, IShortcutService.Stub.asInterface(
+ ServiceManager.getService(Context.SHORTCUT_SERVICE)));
+ }
+
+ /**
* Publish a list of shortcuts. All existing dynamic shortcuts from the caller application
* will be replaced.
*
@@ -141,10 +153,10 @@
* @throws IllegalArgumentException if the caller application has already published the
* max number of dynamic shortcuts.
*/
- public boolean addDynamicShortcut(@NonNull ShortcutInfo shortcutInfo) {
+ public boolean addDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
try {
- return mService.addDynamicShortcut(
- mContext.getPackageName(), shortcutInfo, injectMyUserId());
+ return mService.addDynamicShortcuts(mContext.getPackageName(),
+ new ParceledListSlice(shortcutInfoList), injectMyUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -153,9 +165,10 @@
/**
* Delete a single dynamic shortcut by ID.
*/
- public void deleteDynamicShortcut(@NonNull String shortcutId) {
+ public void removeDynamicShortcuts(@NonNull List<String> shortcutIds) {
try {
- mService.deleteDynamicShortcut(mContext.getPackageName(), shortcutId, injectMyUserId());
+ mService.removeDynamicShortcuts(mContext.getPackageName(), shortcutIds,
+ injectMyUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -164,9 +177,9 @@
/**
* Delete all dynamic shortcuts from the caller application.
*/
- public void deleteAllDynamicShortcuts() {
+ public void removeAllDynamicShortcuts() {
try {
- mService.deleteAllDynamicShortcuts(mContext.getPackageName(), injectMyUserId());
+ mService.removeAllDynamicShortcuts(mContext.getPackageName(), injectMyUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
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/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 79eff4f..98a8904 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1590,16 +1590,16 @@
new Key<Integer>("android.control.videoStabilizationMode", int.class);
/**
- * <p>The amount of additional sesnsitivity boost applied to output images
+ * <p>The amount of additional sensitivity boost applied to output images
* after RAW sensor data is captured.</p>
* <p>Some camera devices support additional digital sensitivity boosting in the
* camera processing pipeline after sensor RAW image is captured.
* Such a boost will be applied to YUV/JPEG format output images but will not
* have effect on RAW output formats like RAW_SENSOR, RAW10, RAW12 or RAW_OPAQUE.</p>
- * <p>This key is optional. Applications can assume there is no boost applied
- * after RAW is captured if this key is not available.
- * When this key is available, the sensitivity boost value must be within
- * {@link CameraCharacteristics#CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE android.control.postRawSensitivityBoostRange}.</p>
+ * <p>This key will be <code>null</code> for devices that do not support any RAW format
+ * outputs. For devices that do support RAW format outputs, this key will always
+ * present, and if a device does not support post RAW sensitivity boost, it will
+ * list <code>100</code> in this key.</p>
* <p>If the camera device cannot apply the exact boost requested, it will reduce the
* boost to the nearest supported value.
* The final boost value used will be available in the output capture result.</p>
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 4f41e1c..8c73e6a 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2097,16 +2097,16 @@
new Key<Integer>("android.control.videoStabilizationMode", int.class);
/**
- * <p>The amount of additional sesnsitivity boost applied to output images
+ * <p>The amount of additional sensitivity boost applied to output images
* after RAW sensor data is captured.</p>
* <p>Some camera devices support additional digital sensitivity boosting in the
* camera processing pipeline after sensor RAW image is captured.
* Such a boost will be applied to YUV/JPEG format output images but will not
* have effect on RAW output formats like RAW_SENSOR, RAW10, RAW12 or RAW_OPAQUE.</p>
- * <p>This key is optional. Applications can assume there is no boost applied
- * after RAW is captured if this key is not available.
- * When this key is available, the sensitivity boost value must be within
- * {@link CameraCharacteristics#CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE android.control.postRawSensitivityBoostRange}.</p>
+ * <p>This key will be <code>null</code> for devices that do not support any RAW format
+ * outputs. For devices that do support RAW format outputs, this key will always
+ * present, and if a device does not support post RAW sensitivity boost, it will
+ * list <code>100</code> in this key.</p>
* <p>If the camera device cannot apply the exact boost requested, it will reduce the
* boost to the nearest supported value.
* The final boost value used will be available in the output capture result.</p>
@@ -3599,10 +3599,20 @@
/**
* <p>The shading map is a low-resolution floating-point map
- * that lists the coefficients used to correct for vignetting, for each
- * Bayer color channel of RAW image data.</p>
- * <p>The least shaded section of the image should have a gain factor
- * of 1; all other sections should have gains above 1.</p>
+ * that lists the coefficients used to correct for vignetting and color shading,
+ * for each Bayer color channel of RAW image data.</p>
+ * <p>The lens shading correction is defined as a full shading correction that
+ * corrects both color shading for the output non-RAW images. After the
+ * shading map is applied, the output non-RAW images will be flat-field images
+ * for flat scenes under uniform illumination.</p>
+ * <p>When there is no lens shading correction applied to RAW output images
+ * ({@link CameraCharacteristics#SENSOR_INFO_LENS_SHADING_APPLIED android.sensor.info.lensShadingApplied} <code>==</code> false), this map is a full lens
+ * shading correction map; when there is some lens shading correction applied
+ * to the RAW output image ({@link CameraCharacteristics#SENSOR_INFO_LENS_SHADING_APPLIED android.sensor.info.lensShadingApplied} <code>==</code> true),
+ * this map reports the remaining lens shading correction map that needs to be
+ * applied to get fully shading corrected images.</p>
+ * <p>For a full shading correction map, the least shaded section of the image
+ * should have a gain factor of 1; all other sections should have gains above 1.</p>
* <p>When {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} = TRANSFORM_MATRIX, the map
* must take into account the colorCorrection settings.</p>
* <p>The shading map is for the entire active pixel array, and is not
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 18a155d..b542339 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -501,11 +501,8 @@
Log.d(TAG, "createCaptureSessionByOutputConfiguration");
}
- // OutputConfiguration objects aren't immutable, make a copy before using.
- List<OutputConfiguration> currentOutputs = new ArrayList<OutputConfiguration>();
- for (OutputConfiguration output : outputConfigurations) {
- currentOutputs.add(new OutputConfiguration(output));
- }
+ // OutputConfiguration objects are immutable, but need to have our own array
+ List<OutputConfiguration> currentOutputs = new ArrayList<>(outputConfigurations);
createCaptureSessionInternal(null, currentOutputs, callback, handler,
/*isConstrainedHighSpeed*/false);
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index cd0c474..61b534b 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -17,6 +17,8 @@
package android.hardware.camera2.params;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.utils.HashCodeHelpers;
@@ -71,12 +73,12 @@
public static final int ROTATION_270 = 3;
/**
- * Invalid surface set ID.
+ * Invalid surface group ID.
*
*<p>An {@link OutputConfiguration} with this value indicates that the included surface
- *doesn't belong to any surface set.</p>
+ *doesn't belong to any surface group.</p>
*/
- public static final int SURFACE_SET_ID_INVALID = -1;
+ public static final int SURFACE_GROUP_ID_NONE = -1;
/**
* Create a new {@link OutputConfiguration} instance with a {@link Surface}.
@@ -84,11 +86,47 @@
* @param surface
* A Surface for camera to output to.
*
- * <p>This constructor creates a default configuration.</p>
+ * <p>This constructor creates a default configuration, with a surface group ID of
+ * {@value #SURFACE_GROUP_ID_NONE}.</p>
*
*/
- public OutputConfiguration(Surface surface) {
- this(surface, ROTATION_0);
+ public OutputConfiguration(@NonNull Surface surface) {
+ this(SURFACE_GROUP_ID_NONE, surface, ROTATION_0);
+ }
+
+ /**
+ * Create a new {@link OutputConfiguration} instance with a {@link Surface},
+ * with a surface group ID.
+ *
+ * <p>
+ * A surface group ID is used to identify which surface group this output surface belongs to. A
+ * surface group is a group of output surfaces that are not intended to receive camera output
+ * buffer streams simultaneously. The {@link CameraDevice} may be able to share the buffers used
+ * by all the surfaces from the same surface group, therefore may reduce the overall memory
+ * footprint. The application should only set the same set ID for the streams that are not
+ * simultaneously streaming. A negative ID indicates that this surface doesn't belong to any
+ * surface group. The default value is {@value #SURFACE_GROUP_ID_NONE}.</p>
+ *
+ * <p>For example, a video chat application that has an adaptive output resolution feature would
+ * need two (or more) output resolutions, to switch resolutions without any output glitches.
+ * However, at any given time, only one output is active to minimize outgoing network bandwidth
+ * and encoding overhead. To save memory, the application should set the video outputs to have
+ * the same non-negative group ID, so that the camera device can share the same memory region
+ * for the alternating outputs.</p>
+ *
+ * <p>It is not an error to include output streams with the same group ID in the same capture
+ * request, but the resulting memory consumption may be higher than if the two streams were
+ * not in the same surface group to begin with, especially if the outputs have substantially
+ * different dimensions.</p>
+ *
+ * @param surfaceGroupId
+ * A group ID for this output, used for sharing memory between multiple outputs.
+ * @param surface
+ * A Surface for camera to output to.
+ *
+ */
+ public OutputConfiguration(int surfaceGroupId, @NonNull Surface surface) {
+ this(surfaceGroupId, surface, ROTATION_0);
}
/**
@@ -100,9 +138,9 @@
* A Surface for camera to output to.
* @param rotation
* The desired rotation to be applied on camera output. Value must be one of
- * ROTATION_[0, 90, 180, 270]. Note that when the rotation is 90 or 270 degree,
+ * ROTATION_[0, 90, 180, 270]. Note that when the rotation is 90 or 270 degrees,
* application should make sure corresponding surface size has width and height
- * transposed corresponding to the width and height without rotation. For example,
+ * transposed relative to the width and height without rotation. For example,
* if application needs camera to capture 1280x720 picture and rotate it by 90 degree,
* application should set rotation to {@code ROTATION_90} and make sure the
* corresponding Surface size is 720x1280. Note that {@link CameraDevice} might
@@ -110,15 +148,43 @@
* @hide
*/
@SystemApi
- public OutputConfiguration(Surface surface, int rotation) {
+ public OutputConfiguration(@NonNull Surface surface, int rotation) {
+ this(SURFACE_GROUP_ID_NONE, surface, rotation);
+ }
+
+
+ /**
+ * Create a new {@link OutputConfiguration} instance, with rotation and a group ID.
+ *
+ * <p>This constructor takes an argument for desired camera rotation and for the surface group
+ * ID. See {@link #OutputConfiguration(int, Surface)} for details of the group ID.</p>
+ *
+ * @param surfaceGroupId
+ * A group ID for this output, used for sharing memory between multiple outputs.
+ * @param surface
+ * A Surface for camera to output to.
+ * @param rotation
+ * The desired rotation to be applied on camera output. Value must be one of
+ * ROTATION_[0, 90, 180, 270]. Note that when the rotation is 90 or 270 degrees,
+ * application should make sure corresponding surface size has width and height
+ * transposed relative to the width and height without rotation. For example,
+ * if application needs camera to capture 1280x720 picture and rotate it by 90 degree,
+ * application should set rotation to {@code ROTATION_90} and make sure the
+ * corresponding Surface size is 720x1280. Note that {@link CameraDevice} might
+ * throw {@code IllegalArgumentException} if device cannot perform such rotation.
+ * @hide
+ */
+ @SystemApi
+ public OutputConfiguration(int surfaceGroupId, @NonNull Surface surface, int rotation) {
checkNotNull(surface, "Surface must not be null");
checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
- mSurfaceSetId = SURFACE_SET_ID_INVALID;
+ mSurfaceGroupId = surfaceGroupId;
mSurface = surface;
mRotation = rotation;
mConfiguredSize = SurfaceUtils.getSurfaceSize(surface);
mConfiguredFormat = SurfaceUtils.getSurfaceFormat(surface);
mConfiguredDataspace = SurfaceUtils.getSurfaceDataspace(surface);
+ mConfiguredGenerationId = surface.getGenerationId();
}
/**
@@ -129,35 +195,36 @@
*
* @hide
*/
- @SystemApi
- public OutputConfiguration(OutputConfiguration other) {
+ public OutputConfiguration(@NonNull OutputConfiguration other) {
if (other == null) {
throw new IllegalArgumentException("OutputConfiguration shouldn't be null");
}
this.mSurface = other.mSurface;
this.mRotation = other.mRotation;
- this.mSurfaceSetId = other.mSurfaceSetId;
+ this.mSurfaceGroupId = other.mSurfaceGroupId;
this.mConfiguredDataspace = other.mConfiguredDataspace;
this.mConfiguredFormat = other.mConfiguredFormat;
this.mConfiguredSize = other.mConfiguredSize;
+ this.mConfiguredGenerationId = other.mConfiguredGenerationId;
}
/**
* Create an OutputConfiguration from Parcel.
*/
- private OutputConfiguration(Parcel source) {
+ private OutputConfiguration(@NonNull Parcel source) {
int rotation = source.readInt();
int surfaceSetId = source.readInt();
Surface surface = Surface.CREATOR.createFromParcel(source);
checkNotNull(surface, "Surface must not be null");
checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
- mSurfaceSetId = surfaceSetId;
+ mSurfaceGroupId = surfaceSetId;
mSurface = surface;
mRotation = rotation;
mConfiguredSize = SurfaceUtils.getSurfaceSize(mSurface);
mConfiguredFormat = SurfaceUtils.getSurfaceFormat(mSurface);
mConfiguredDataspace = SurfaceUtils.getSurfaceDataspace(mSurface);
+ mConfiguredGenerationId = mSurface.getGenerationId();
}
/**
@@ -165,6 +232,7 @@
*
* @return the {@link Surface} associated with this {@link OutputConfiguration}.
*/
+ @NonNull
public Surface getSurface() {
return mSurface;
}
@@ -183,35 +251,13 @@
}
/**
- * Set the surface set ID to this {@link OutputConfiguration}.
+ * Get the surface group ID associated with this {@link OutputConfiguration}.
*
- * <p>
- * A surface set ID is used to identify which surface set this output surface belongs to. A
- * surface set is a group of output surfaces that are not intended to receive camera output
- * buffer streams simultaneously. The {@link CameraDevice} may be able to share the buffers used
- * by all the surfaces from the same surface set, therefore may save the overall memory
- * footprint. The application should only set the same set ID for the streams that are not
- * simultaneously streaming. A negative ID indicates that this surface doesn't belong to any
- * surface set. The default value will be {@value #SURFACE_SET_ID_INVALID}.
- * </p>
- *
- * @param setId
+ * @return the surface group ID associated with this {@link OutputConfiguration}.
+ * The default value is {@value #SURFACE_GROUP_ID_NONE}.
*/
- public void setSurfaceSetId(int setId) {
- if (setId < 0) {
- setId = SURFACE_SET_ID_INVALID;
- }
- mSurfaceSetId = setId;
- }
-
- /**
- * Get the surface set Id associated with this {@link OutputConfiguration}.
- *
- * @return the surface set Id associated with this {@link OutputConfiguration}.
- * Value will be one of ROTATION_[0, 90, 180, 270]
- */
- public int getSurfaceSetId() {
- return mSurfaceSetId;
+ public int getSurfaceGroupId() {
+ return mSurfaceGroupId;
}
public static final Parcelable.Creator<OutputConfiguration> CREATOR =
@@ -244,7 +290,7 @@
throw new IllegalArgumentException("dest must not be null");
}
dest.writeInt(mRotation);
- dest.writeInt(mSurfaceSetId);
+ dest.writeInt(mSurfaceGroupId);
mSurface.writeToParcel(dest, flags);
}
@@ -265,12 +311,13 @@
return true;
} else if (obj instanceof OutputConfiguration) {
final OutputConfiguration other = (OutputConfiguration) obj;
- return mSurface == other.mSurface &&
- mRotation == other.mRotation &&
+ return mRotation == other.mRotation &&
+ mSurface == other.mSurface &&
+ mConfiguredGenerationId == other.mConfiguredGenerationId &&
mConfiguredSize.equals(other.mConfiguredSize) &&
mConfiguredFormat == other.mConfiguredFormat &&
mConfiguredDataspace == other.mConfiguredDataspace &&
- mSurfaceSetId == other.mSurfaceSetId;
+ mSurfaceGroupId == other.mSurfaceGroupId;
}
return false;
}
@@ -280,16 +327,20 @@
*/
@Override
public int hashCode() {
- return HashCodeHelpers.hashCode(mSurface.hashCode(), mRotation);
+ return HashCodeHelpers.hashCode(
+ mRotation, mSurface.hashCode(), mConfiguredGenerationId,
+ mConfiguredSize.hashCode(), mConfiguredFormat, mConfiguredDataspace, mSurfaceGroupId);
}
private static final String TAG = "OutputConfiguration";
private final Surface mSurface;
private final int mRotation;
- private int mSurfaceSetId;
+ private int mSurfaceGroupId;
// The size, format, and dataspace of the surface when OutputConfiguration is created.
private final Size mConfiguredSize;
private final int mConfiguredFormat;
private final int mConfiguredDataspace;
+ // Surface generation ID to distinguish changes to Surface native internals
+ private final int mConfiguredGenerationId;
}
diff --git a/core/java/android/hardware/location/NanoApp.java b/core/java/android/hardware/location/NanoApp.java
index c8f3439..03ac4a2 100644
--- a/core/java/android/hardware/location/NanoApp.java
+++ b/core/java/android/hardware/location/NanoApp.java
@@ -18,6 +18,7 @@
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.Log;
/** A class describing nano apps.
* A nano app is a piece of executable code that can be
@@ -31,10 +32,15 @@
*/
@SystemApi
public class NanoApp {
+ private final String TAG = "NanoApp";
+
+ private final String UNKNOWN = "Unknown";
+
private String mPublisher;
private String mName;
private int mAppId;
+ private boolean mAppIdSet;
private int mAppVersion;
private int mNeededReadMemBytes;
@@ -45,7 +51,48 @@
private int[] mOutputEvents;
private byte[] mAppBinary;
+ /**
+ * If this version of the constructor is used, the methods
+ * {@link #setAppBinary(byte[])} and {@link #setAppId(int)} must be called
+ * prior to passing this object to any managers.
+ *
+ * @see #NanoApp(int, byte[])
+ */
public NanoApp() {
+ this(0, null);
+ mAppIdSet = false;
+ }
+
+ /**
+ * Initialize a NanoApp with the given id and binary.
+ *
+ * While this sets defaults for other fields, users will want to provide
+ * other values for those fields in most cases.
+ *
+ * @see #setPublisher(String)
+ * @see #setName(String)
+ * @see #setAppVersion(int)
+ * @see #setNeededReadMemBytes(int)
+ * @see #setNeededWriteMemBytes(int)
+ * @see #setNeededExecMemBytes(int)
+ * @see #setNeededSensors(int[])
+ * @see #setOutputEvents(int[])
+ */
+ public NanoApp(int appId, byte[] appBinary) {
+ mPublisher = UNKNOWN;
+ mName = UNKNOWN;
+
+ mAppId = appId;
+ mAppIdSet = true;
+ mAppVersion = 0;
+
+ mNeededReadMemBytes = 0;
+ mNeededWriteMemBytes = 0;
+ mNeededExecMemBytes = 0;
+
+ mNeededSensors = new int[0];
+ mOutputEvents = new int[0];
+ mAppBinary = appBinary;
}
/**
@@ -73,6 +120,7 @@
*/
public void setAppId(int appId) {
mAppId = appId;
+ mAppIdSet = true;
}
/**
@@ -144,7 +192,7 @@
* @return publisher name
*/
public String getPublisher() {
- return mPublisher;
+ return mPublisher;
}
/**
@@ -153,7 +201,7 @@
* @return app name
*/
public String getName() {
- return mName;
+ return mName;
}
/**
@@ -162,7 +210,7 @@
* @return identifier for this app
*/
public int getAppId() {
- return mAppId;
+ return mAppId;
}
/**
@@ -171,7 +219,7 @@
* @return app version
*/
public int getAppVersion() {
- return mAppVersion;
+ return mAppVersion;
}
/**
@@ -180,7 +228,7 @@
* @return readable memory needed in bytes
*/
public int getNeededReadMemBytes() {
- return mNeededReadMemBytes;
+ return mNeededReadMemBytes;
}
/**
@@ -189,7 +237,7 @@
* @return writable memory needed in bytes
*/
public int getNeededWriteMemBytes() {
- return mNeededWriteMemBytes;
+ return mNeededWriteMemBytes;
}
/**
@@ -198,7 +246,7 @@
* @return executable memory needed in bytes
*/
public int getNeededExecMemBytes() {
- return mNeededExecMemBytes;
+ return mNeededExecMemBytes;
}
/**
@@ -207,7 +255,7 @@
* @return sensors needed
*/
public int[] getNeededSensors() {
- return mNeededSensors;
+ return mNeededSensors;
}
/**
@@ -216,7 +264,7 @@
* @return generated events
*/
public int[] getOutputEvents() {
- return mOutputEvents;
+ return mOutputEvents;
}
/**
@@ -225,7 +273,7 @@
* @return app binary
*/
public byte[] getAppBinary() {
- return mAppBinary;
+ return mAppBinary;
}
private NanoApp(Parcel in) {
@@ -256,6 +304,13 @@
}
public void writeToParcel(Parcel out, int flags) {
+ if (mAppBinary == null) {
+ throw new IllegalStateException("Must set non-null AppBinary for nanoapp " + mName);
+ }
+ if (!mAppIdSet) {
+ throw new IllegalStateException("Must set AppId for nanoapp " + mName);
+ }
+
out.writeString(mPublisher);
out.writeString(mName);
out.writeInt(mAppId);
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/inputmethodservice/CompactExtractEditLayout.java b/core/java/android/inputmethodservice/CompactExtractEditLayout.java
index f994c65..35c54b2 100644
--- a/core/java/android/inputmethodservice/CompactExtractEditLayout.java
+++ b/core/java/android/inputmethodservice/CompactExtractEditLayout.java
@@ -1,3 +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.inputmethodservice;
import android.content.Context;
@@ -100,4 +116,3 @@
}
}
}
-
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index a025337..5d008e3 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2734,7 +2734,7 @@
private void incCallbackHandlerRefCount() {
synchronized(sCallbackRefCount) {
if (sCallbackRefCount.incrementAndGet() == 1) {
- // TODO - switch this over to a ManagerThread or expire it when done
+ // TODO: switch this to ConnectivityThread
HandlerThread callbackThread = new HandlerThread("ConnectivityManager");
callbackThread.start();
sCallbackHandler = new CallbackHandler(callbackThread.getLooper(),
@@ -3093,6 +3093,10 @@
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
+
+ synchronized (sNetworkCallback) {
+ sNetworkCallback.remove(networkCallback.networkRequest);
+ }
}
/**
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 20c2168..2dacf8f 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -120,12 +120,17 @@
* either a bad network configuration (no internet link) or captive portal.
*
* arg1 = either {@code VALID_NETWORK} or {@code INVALID_NETWORK}
+ * obj = Bundle containing map from {@code REDIRECT_URL_KEY} to {@code String}
+ * representing URL that Internet probe was redirect to, if it was redirected,
+ * or mapping to {@code null} otherwise.
*/
public static final int CMD_REPORT_NETWORK_STATUS = BASE + 7;
public static final int VALID_NETWORK = 1;
public static final int INVALID_NETWORK = 2;
+ public static String REDIRECT_URL_KEY = "redirect URL";
+
/**
* Sent by the NetworkAgent to ConnectivityService to indicate this network was
* explicitly selected. This should be sent before the NetworkInfo is marked
@@ -283,11 +288,12 @@
break;
}
case CMD_REPORT_NETWORK_STATUS: {
+ String redirectUrl = ((Bundle)msg.obj).getString(REDIRECT_URL_KEY);
if (VDBG) {
log("CMD_REPORT_NETWORK_STATUS(" +
- (msg.arg1 == VALID_NETWORK ? "VALID)" : "INVALID)"));
+ (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ") + redirectUrl);
}
- networkStatus(msg.arg1);
+ networkStatus(msg.arg1, redirectUrl);
break;
}
case CMD_SAVE_ACCEPT_UNVALIDATED: {
@@ -443,8 +449,12 @@
*
* This may be called multiple times as the network status changes and may
* generate false negatives if we lose ip connectivity before the link is torn down.
+ *
+ * @param status one of {@code VALID_NETWORK} or {@code INVALID_NETWORK}.
+ * @param redirectUrl If the Internet probe was redirected, this is the destination it was
+ * redirected to, otherwise {@code null}.
*/
- protected void networkStatus(int status) {
+ protected void networkStatus(int status, String redirectUrl) {
}
/**
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index cfd0468..1ac9fca 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -228,7 +228,6 @@
* statistics parameters.
*
* @see #setThreadStatsTag(int)
- * @see #setThreadStatsUid(int)
*/
public static void tagSocket(Socket socket) throws SocketException {
SocketTagger.get().tag(socket);
@@ -249,7 +248,6 @@
* parameters.
*
* @see #setThreadStatsTag(int)
- * @see #setThreadStatsUid(int)
*/
public static void tagDatagramSocket(DatagramSocket socket) throws SocketException {
SocketTagger.get().tag(socket);
diff --git a/core/java/android/net/http/X509TrustManagerExtensions.java b/core/java/android/net/http/X509TrustManagerExtensions.java
index 6729347..e0fa63a 100644
--- a/core/java/android/net/http/X509TrustManagerExtensions.java
+++ b/core/java/android/net/http/X509TrustManagerExtensions.java
@@ -17,6 +17,7 @@
package android.net.http;
import android.annotation.SystemApi;
+import android.security.net.config.UserCertificateSource;
import com.android.org.conscrypt.TrustManagerImpl;
@@ -43,7 +44,7 @@
// Methods to use when mDelegate is not a TrustManagerImpl and duck typing is being used.
private final X509TrustManager mTrustManager;
private final Method mCheckServerTrusted;
- private final Method mIsUserAddedCertificate;
+ private final Method mIsSameTrustConfiguration;
/**
* Constructs a new X509TrustManagerExtensions wrapper.
@@ -56,7 +57,7 @@
mDelegate = (TrustManagerImpl) tm;
mTrustManager = null;
mCheckServerTrusted = null;
- mIsUserAddedCertificate = null;
+ mIsSameTrustConfiguration = null;
return;
}
// Use duck typing if possible.
@@ -72,14 +73,15 @@
throw new IllegalArgumentException("Required method"
+ " checkServerTrusted(X509Certificate[], String, String, String) missing");
}
- // Check that isUserAddedCertificate is present.
+ // Get the option isSameTrustConfiguration method.
+ Method isSameTrustConfiguration = null;
try {
- mIsUserAddedCertificate = tm.getClass().getMethod("isUserAddedCertificate",
- X509Certificate.class);
- } catch (NoSuchMethodException e) {
- throw new IllegalArgumentException(
- "Required method isUserAddedCertificate(X509Certificate) missing");
+ isSameTrustConfiguration = tm.getClass().getMethod("isSameTrustConfiguration",
+ String.class,
+ String.class);
+ } catch (ReflectiveOperationException ignored) {
}
+ mIsSameTrustConfiguration = isSameTrustConfiguration;
}
/**
@@ -117,29 +119,15 @@
/**
* Checks whether a CA certificate is added by an user.
*
- * <p>Since {@link X509TrustManager#checkServerTrusted} allows its parameter {@code chain} to
+ * <p>Since {@link X509TrustManager#checkServerTrusted} may allow its parameter {@code chain} to
* chain up to user-added CA certificates, this method can be used to perform additional
* policies for user-added CA certificates.
*
- * @return {@code true} to indicate that the certificate was added by the user, {@code false}
- * otherwise.
+ * @return {@code true} to indicate that the certificate authority exists in the user added
+ * certificate store, {@code false} otherwise.
*/
public boolean isUserAddedCertificate(X509Certificate cert) {
- if (mDelegate != null) {
- return mDelegate.isUserAddedCertificate(cert);
- } else {
- try {
- return (Boolean) mIsUserAddedCertificate.invoke(mTrustManager, cert);
- } catch (IllegalAccessException e) {
- throw new RuntimeException("Failed to call isUserAddedCertificate", e);
- } catch (InvocationTargetException e) {
- if (e.getCause() instanceof RuntimeException) {
- throw (RuntimeException) e.getCause();
- } else {
- throw new RuntimeException("isUserAddedCertificate failed", e.getCause());
- }
- }
- }
+ return UserCertificateSource.getInstance().findBySubjectAndPublicKey(cert) != null;
}
/**
@@ -150,6 +138,19 @@
*/
@SystemApi
public boolean isSameTrustConfiguration(String hostname1, String hostname2) {
- return true;
+ if (mIsSameTrustConfiguration == null) {
+ return true;
+ }
+ try {
+ return (Boolean) mIsSameTrustConfiguration.invoke(mTrustManager, hostname1, hostname2);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Failed to call isSameTrustConfiguration", e);
+ } catch (InvocationTargetException e) {
+ if (e.getCause() instanceof RuntimeException) {
+ throw (RuntimeException) e.getCause();
+ } else {
+ throw new RuntimeException("isSameTrustConfiguration failed", e.getCause());
+ }
+ }
}
}
diff --git a/core/java/android/net/metrics/ConnectivityServiceChangeEvent.java b/core/java/android/net/metrics/ConnectivityServiceChangeEvent.java
index c6fcb2d..a491ffc 100644
--- a/core/java/android/net/metrics/ConnectivityServiceChangeEvent.java
+++ b/core/java/android/net/metrics/ConnectivityServiceChangeEvent.java
@@ -25,18 +25,40 @@
public class ConnectivityServiceChangeEvent extends IpConnectivityEvent implements Parcelable {
public static final String TAG = "ConnectivityServiceChangeEvent";
- private int mNetId;
+ // The ID of the network that has become the new default or NETID_UNSET if none.
+ private final int mNetId;
+ // The list of transport types of the new default network, for example TRANSPORT_WIFI, as
+ // defined in NetworkCapabilities.java.
+ private final int[] mTransportTypes;
+ // The ID of the network that was the default before or NETID_UNSET if none.
+ private final int mPrevNetId;
+ // Whether the previous network had IPv4/IPv6 connectivity.
+ private final boolean mPrevIPv4;
+ private final boolean mPrevIPv6;
- public ConnectivityServiceChangeEvent(int netId) {
+ public ConnectivityServiceChangeEvent(int netId, int[] transportTypes,
+ int prevNetId, boolean prevIPv4, boolean prevIPv6) {
mNetId = netId;
+ mTransportTypes = transportTypes;
+ mPrevNetId = prevNetId;
+ mPrevIPv4 = prevIPv4;
+ mPrevIPv6 = prevIPv6;
}
public ConnectivityServiceChangeEvent(Parcel in) {
mNetId = in.readInt();
+ mTransportTypes = in.createIntArray();
+ mPrevNetId = in.readInt();
+ mPrevIPv4 = (in.readByte() > 0);
+ mPrevIPv6 = (in.readByte() > 0);
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mNetId);
+ out.writeIntArray(mTransportTypes);
+ out.writeInt(mPrevNetId);
+ out.writeByte(mPrevIPv4 ? (byte) 1 : (byte) 0);
+ out.writeByte(mPrevIPv6 ? (byte) 1 : (byte) 0);
}
public static final Parcelable.Creator<ConnectivityServiceChangeEvent> CREATOR
@@ -50,8 +72,10 @@
}
};
- public static void logEvent(int netId) {
+ public static void logEvent(int netId, int[] transportTypes,
+ int prevNetId, boolean prevIPv4, boolean prevIPv6) {
IpConnectivityEvent.logEvent(IpConnectivityEvent.IPCE_CONSRV_DEFAULT_NET_CHANGE,
- new ConnectivityServiceChangeEvent(netId));
+ new ConnectivityServiceChangeEvent(
+ netId, transportTypes, prevNetId, prevIPv4, prevIPv6));
}
};
diff --git a/core/java/android/net/metrics/DhcpErrorEvent.java b/core/java/android/net/metrics/DhcpErrorEvent.java
new file mode 100644
index 0000000..3869823
--- /dev/null
+++ b/core/java/android/net/metrics/DhcpErrorEvent.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * {@hide} Event class used to record error events when parsing DHCP response packets.
+ */
+public class DhcpErrorEvent extends IpConnectivityEvent implements Parcelable {
+ public static final String TAG = "DhcpErrorEvent";
+
+ public static final int L2_ERROR = 1;
+ public static final int L3_ERROR = 2;
+ public static final int L4_ERROR = 3;
+ public static final int DHCP_ERROR = 4;
+ public static final int MISC_ERROR = 5;
+
+ public static final int L2_TOO_SHORT = makeErrorCode(L2_ERROR, 1);
+ public static final int L2_WRONG_ETH_TYPE = makeErrorCode(L2_ERROR, 2);
+
+ public static final int L3_TOO_SHORT = makeErrorCode(L3_ERROR, 1);
+ public static final int L3_NOT_IPV4 = makeErrorCode(L3_ERROR, 2);
+ public static final int L3_INVALID_IP = makeErrorCode(L3_ERROR, 3);
+
+ public static final int L4_NOT_UDP = makeErrorCode(L4_ERROR, 1);
+ public static final int L4_WRONG_PORT = makeErrorCode(L4_ERROR, 2);
+
+ public static final int BOOTP_TOO_SHORT = makeErrorCode(DHCP_ERROR, 1);
+ public static final int DHCP_BAD_MAGIC_COOKIE = makeErrorCode(DHCP_ERROR, 2);
+ public static final int DHCP_INVALID_OPTION_LENGTH = makeErrorCode(DHCP_ERROR, 3);
+ public static final int DHCP_NO_MSG_TYPE = makeErrorCode(DHCP_ERROR, 4);
+ public static final int DHCP_UNKNOWN_MSG_TYPE = makeErrorCode(DHCP_ERROR, 5);
+
+ public static final int BUFFER_UNDERFLOW = makeErrorCode(MISC_ERROR, 1);
+
+ // error code byte format (MSB to LSB):
+ // byte 0: error type
+ // byte 1: error subtype
+ // byte 2: unused
+ // byte 3: optional code
+ public final int errorCode;
+
+ private DhcpErrorEvent(int errorCode) {
+ this.errorCode = errorCode;
+ }
+
+ private DhcpErrorEvent(Parcel in) {
+ this.errorCode = in.readInt();
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(errorCode);
+ }
+
+ public static final Parcelable.Creator<DhcpErrorEvent> CREATOR
+ = new Parcelable.Creator<DhcpErrorEvent>() {
+ public DhcpErrorEvent createFromParcel(Parcel in) {
+ return new DhcpErrorEvent(in);
+ }
+
+ public DhcpErrorEvent[] newArray(int size) {
+ return new DhcpErrorEvent[size];
+ }
+ };
+
+ public static void logEvent(int errorCode) {
+ IpConnectivityEvent.logEvent(IPCE_DHCP_PARSE_ERROR, new DhcpErrorEvent(errorCode));
+ }
+
+ public static void logEvent(int errorCode, int option) {
+ logEvent((0xFFFF0000 & errorCode) | (0xFF & option));
+ }
+
+ private static int makeErrorCode(int type, int subtype) {
+ return (type << 24) | ((0xFF & subtype) << 16);
+ }
+}
diff --git a/core/java/android/net/metrics/IpConnectivityEvent.java b/core/java/android/net/metrics/IpConnectivityEvent.java
index ec42890..59c1cfe 100644
--- a/core/java/android/net/metrics/IpConnectivityEvent.java
+++ b/core/java/android/net/metrics/IpConnectivityEvent.java
@@ -28,14 +28,17 @@
// DHCP = DhcpClient
// NETMON = NetworkMonitorEvent
// CONSRV = ConnectivityServiceEvent
+ // IPMGR = IpManager
public static final String TAG = "IpConnectivityEvent";
public static final int IPCE_IPRM_BASE = 0*1024;
public static final int IPCE_DHCP_BASE = 1*1024;
public static final int IPCE_NETMON_BASE = 2*1024;
public static final int IPCE_CONSRV_BASE = 3*1024;
+ public static final int IPCE_IPMGR_BASE = 4*1024;
public static final int IPCE_IPRM_PROBE_RESULT = IPCE_IPRM_BASE + 0;
public static final int IPCE_IPRM_MESSAGE_RECEIVED = IPCE_IPRM_BASE + 1;
+ public static final int IPCE_IPRM_REACHABILITY_LOST = IPCE_IPRM_BASE + 2;
public static final int IPCE_DHCP_RECV_ERROR = IPCE_DHCP_BASE + 0;
public static final int IPCE_DHCP_PARSE_ERROR = IPCE_DHCP_BASE + 1;
public static final int IPCE_DHCP_TIMEOUT = IPCE_DHCP_BASE + 2;
@@ -43,6 +46,9 @@
public static final int IPCE_NETMON_STATE_CHANGE = IPCE_NETMON_BASE + 0;
public static final int IPCE_NETMON_CHECK_RESULT = IPCE_NETMON_BASE + 1;
public static final int IPCE_CONSRV_DEFAULT_NET_CHANGE = IPCE_CONSRV_BASE + 0;
+ public static final int IPCE_IPMGR_PROVISIONING_OK = IPCE_IPMGR_BASE + 0;
+ public static final int IPCE_IPMGR_PROVISIONING_FAIL = IPCE_IPMGR_BASE + 1;
+ public static final int IPCE_IPMGR_COMPLETE_LIFECYCLE = IPCE_IPMGR_BASE + 2;
private static ConnectivityMetricsLogger mMetricsLogger = new ConnectivityMetricsLogger();
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
new file mode 100644
index 0000000..6328ccb
--- /dev/null
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * {@hide}
+ */
+public class IpManagerEvent extends IpConnectivityEvent implements Parcelable {
+ private String mIfName;
+ private long mDurationMs;
+
+ public IpManagerEvent(String ifName, long duration) {
+ mIfName = ifName;
+ mDurationMs = duration;
+ }
+
+ public IpManagerEvent(Parcel in) {
+ mIfName = in.readString();
+ mDurationMs = in.readLong();
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mIfName);
+ out.writeLong(mDurationMs);
+ }
+
+ public static final Parcelable.Creator<IpManagerEvent> CREATOR
+ = new Parcelable.Creator<IpManagerEvent>() {
+ public IpManagerEvent createFromParcel(Parcel in) {
+ return new IpManagerEvent(in);
+ }
+
+ public IpManagerEvent[] newArray(int size) {
+ return new IpManagerEvent[size];
+ }
+ };
+
+ public static void logEvent(int eventType, String ifName, long durationMs) {
+ IpConnectivityEvent.logEvent(eventType, new IpManagerEvent(ifName, durationMs));
+ }
+};
diff --git a/core/java/android/net/metrics/IpReachabilityMonitorLostEvent.java b/core/java/android/net/metrics/IpReachabilityMonitorLostEvent.java
new file mode 100644
index 0000000..0f14210
--- /dev/null
+++ b/core/java/android/net/metrics/IpReachabilityMonitorLostEvent.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * {@hide}
+ */
+public class IpReachabilityMonitorLostEvent extends IpConnectivityEvent
+ implements Parcelable {
+ private String mIfName;
+
+ public IpReachabilityMonitorLostEvent(String ifName) {
+ mIfName = ifName;
+ }
+
+ public IpReachabilityMonitorLostEvent(Parcel in) {
+ mIfName = in.readString();
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mIfName);
+ }
+
+ public static final Parcelable.Creator<IpReachabilityMonitorLostEvent> CREATOR
+ = new Parcelable.Creator<IpReachabilityMonitorLostEvent>() {
+ public IpReachabilityMonitorLostEvent createFromParcel(Parcel in) {
+ return new IpReachabilityMonitorLostEvent(in);
+ }
+
+ public IpReachabilityMonitorLostEvent[] newArray(int size) {
+ return new IpReachabilityMonitorLostEvent[size];
+ }
+ };
+
+ public static void logEvent(String ifName) {
+ IpConnectivityEvent.logEvent(IpConnectivityEvent.IPCE_IPRM_REACHABILITY_LOST,
+ new IpReachabilityMonitorLostEvent(ifName));
+ }
+};
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index c452837..773e7dd 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -3094,14 +3094,8 @@
dumpControllerActivityLine(pw, uid, category, WIFI_CONTROLLER_DATA,
u.getWifiControllerActivity(), which);
- // Dump Bluetooth scan data, per UID.
- final long bleScanTimeUs = u.getBluetoothScanTimer().getTotalTimeLocked(
+ dumpTimer(pw, uid, category, BLUETOOTH_MISC_DATA, u.getBluetoothScanTimer(),
rawRealtime, which);
- final int bleScanCount = u.getBluetoothScanTimer().getCountLocked(which);
- if (bleScanTimeUs != 0 || bleScanCount != 0) {
- dumpLine(pw, uid, category, BLUETOOTH_MISC_DATA,
- bleScanTimeUs / 1000, bleScanCount);
- }
dumpControllerActivityLine(pw, uid, category, BLUETOOTH_CONTROLLER_DATA,
u.getBluetoothControllerActivity(), which);
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/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 ece1228..0a8fdd9 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -824,7 +824,9 @@
}
}
- /** {@hide} */
+ /**
+ * Return the {@link StorageVolume} that contains the given file, or {@code null} if none.
+ */
public @Nullable StorageVolume getStorageVolume(File file) {
return getStorageVolume(getVolumeList(), file);
}
@@ -836,9 +838,13 @@
/** {@hide} */
private static @Nullable StorageVolume getStorageVolume(StorageVolume[] volumes, File file) {
+ if (file == null) {
+ return null;
+ }
try {
file = file.getCanonicalFile();
} catch (IOException ignored) {
+ Slog.d(TAG, "Could not get canonical path for " + file);
return null;
}
for (StorageVolume volume : volumes) {
@@ -1056,8 +1062,8 @@
}
/**
- * Return if data stored at the given path will be encrypted while at rest.
- * This can help apps avoid the overhead of double-encrypting data.
+ * Return if data stored at or under the given path will be encrypted while
+ * at rest. This can help apps avoid the overhead of double-encrypting data.
*/
public boolean isEncrypted(File file) {
if (FileUtils.contains(Environment.getDataDirectory(), file)) {
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 89ac27c9a..de19f81 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -283,7 +283,7 @@
*
* <p>Note: if you app targets {@link android.os.Build.VERSION_CODES#M M} and above
* and declares as using the {@link android.Manifest.permission#CAMERA} permission which
- * is not granted, then atempting to use this action will result in a {@link
+ * is not granted, then attempting to use this action will result in a {@link
* java.lang.SecurityException}.
*
* @see #EXTRA_OUTPUT
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2a3c3fe..788a20c 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -296,7 +296,8 @@
* monitoring of encrypted network traffic.
* <p>
* In some cases, a matching Activity may not exist, so ensure you
- * safeguard against this.
+ * safeguard against this. Add {@link #EXTRA_NUMBER_OF_CERTIFICATES} extra to indicate the
+ * number of certificates.
* <p>
* Input: Nothing.
* <p>
@@ -1369,6 +1370,16 @@
public static final String EXTRA_DO_NOT_DISTURB_MODE_MINUTES =
"android.settings.extra.do_not_disturb_mode_minutes";
+ /**
+ * Activity Extra: Number of certificates
+ * <p>
+ * This can be passed as an extra field to the {@link #ACTION_MONITORING_CERT_INFO}
+ * intent to indicate the number of certificates
+ * @hide
+ */
+ public static final String EXTRA_NUMBER_OF_CERTIFICATES =
+ "android.settings.extra.number_of_certificates";
+
private static final String JID_RESOURCE_PREFIX = "android";
public static final String AUTHORITY = "settings";
@@ -1581,6 +1592,8 @@
public static final class System extends NameValueTable {
public static final String SYS_PROP_SETTING_VERSION = "sys.settings_system_version";
+ private static final float DEFAULT_FONT_SCALE = 1.0f;
+
/** @hide */
public static interface Validator {
public boolean validate(String value);
@@ -2089,9 +2102,9 @@
public static void getConfigurationForUser(ContentResolver cr, Configuration outConfig,
int userHandle) {
outConfig.fontScale = Settings.System.getFloatForUser(
- cr, FONT_SCALE, outConfig.fontScale, userHandle);
+ cr, FONT_SCALE, DEFAULT_FONT_SCALE, userHandle);
if (outConfig.fontScale < 0) {
- outConfig.fontScale = 1;
+ outConfig.fontScale = DEFAULT_FONT_SCALE;
}
outConfig.setLocales(LocaleList.forLanguageTags(
Settings.System.getStringForUser(cr, SYSTEM_LOCALES, userHandle)));
@@ -6666,6 +6679,17 @@
public static final String DEVICE_PROVISIONED = "device_provisioned";
/**
+ * Whether mobile data should be allowed while the device is being provisioned.
+ * This allows the provisioning process to turn off mobile data before the user
+ * has an opportunity to set things up, preventing other processes from burning
+ * precious bytes before wifi is setup.
+ * (0 = false, 1 = true)
+ * @hide
+ */
+ public static final String DEVICE_PROVISIONING_MOBILE_DATA_ENABLED =
+ "device_provisioning_mobile_data";
+
+ /**
* The saved value for WindowManagerService.setForcedDisplaySize().
* Two integers separated by a comma. If unset, then use the real display size.
* @hide
@@ -7782,13 +7806,13 @@
* ShortcutManager specific settings.
* This is encoded as a key=value list, separated by commas. Ex:
*
- * "reset_interval_sec=86400,max_daily_updates=5"
+ * "reset_interval_sec=86400,max_updates_per_interval=1"
*
* The following keys are supported:
*
* <pre>
* reset_interval_sec (long)
- * max_daily_updates (int)
+ * max_updates_per_interval (int)
* max_icon_dimension_dp (int, DP)
* max_icon_dimension_dp_lowram (int, DP)
* max_shortcuts (int)
diff --git a/core/java/android/security/net/config/NetworkSecurityTrustManager.java b/core/java/android/security/net/config/NetworkSecurityTrustManager.java
index 3c292ca..d9cc82a 100644
--- a/core/java/android/security/net/config/NetworkSecurityTrustManager.java
+++ b/core/java/android/security/net/config/NetworkSecurityTrustManager.java
@@ -115,15 +115,6 @@
return trustedChain;
}
- /**
- * Check if the provided certificate is a user added certificate authority.
- * This is required by android.net.http.X509TrustManagerExtensions.
- */
- public boolean isUserAddedCertificate(X509Certificate cert) {
- // TODO: Figure out the right way to handle this, and if it is still even used.
- return false;
- }
-
private void checkPins(List<X509Certificate> chain) throws CertificateException {
PinSet pinSet = mNetworkSecurityConfig.getPins();
if (pinSet.pins.isEmpty()
diff --git a/core/java/android/security/net/config/RootTrustManager.java b/core/java/android/security/net/config/RootTrustManager.java
index 19f6887..2a30f11 100644
--- a/core/java/android/security/net/config/RootTrustManager.java
+++ b/core/java/android/security/net/config/RootTrustManager.java
@@ -131,15 +131,6 @@
return config.getTrustManager().checkServerTrusted(certs, authType, hostname);
}
- /**
- * Check if the provided certificate is a user added certificate authority.
- * This is required by android.net.http.X509TrustManagerExtensions.
- */
- public boolean isUserAddedCertificate(X509Certificate cert) {
- // TODO: Figure out the right way to handle this, and if it is still even used.
- return false;
- }
-
@Override
public X509Certificate[] getAcceptedIssuers() {
// getAcceptedIssuers is meant to be used to determine which trust anchors the server will
@@ -148,4 +139,15 @@
NetworkSecurityConfig config = mConfig.getConfigForHostname("");
return config.getTrustManager().getAcceptedIssuers();
}
+
+ /**
+ * Returns {@code true} if this trust manager uses the same trust configuration for the provided
+ * hostnames.
+ *
+ * <p>This is required by android.net.http.X509TrustManagerExtensions.
+ */
+ public boolean isSameTrustConfiguration(String hostname1, String hostname2) {
+ return mConfig.getConfigForHostname(hostname1)
+ .equals(mConfig.getConfigForHostname(hostname2));
+ }
}
diff --git a/core/java/android/service/carrier/CarrierIdentifier.java b/core/java/android/service/carrier/CarrierIdentifier.java
index 495fea6..a70c24d 100644
--- a/core/java/android/service/carrier/CarrierIdentifier.java
+++ b/core/java/android/service/carrier/CarrierIdentifier.java
@@ -105,6 +105,18 @@
out.writeString(mGid2);
}
+ @Override
+ public String toString() {
+ return "CarrierIdentifier{"
+ + "mcc=" + mMcc
+ + ",mnc=" + mMnc
+ + ",spn=" + mSpn
+ + ",imsi=" + mImsi
+ + ",gid1=" + mGid1
+ + ",gid2=" + mGid2
+ + "}";
+ }
+
/** @hide */
public void readFromParcel(Parcel in) {
mMcc = in.readString();
diff --git a/core/java/android/service/voice/IVoiceInteractionSession.aidl b/core/java/android/service/voice/IVoiceInteractionSession.aidl
index dbc28f7..78e6bc3 100644
--- a/core/java/android/service/voice/IVoiceInteractionSession.aidl
+++ b/core/java/android/service/voice/IVoiceInteractionSession.aidl
@@ -30,7 +30,8 @@
oneway interface IVoiceInteractionSession {
void show(in Bundle sessionArgs, int flags, IVoiceInteractionSessionShowCallback showCallback);
void hide();
- void handleAssist(in Bundle assistData, in AssistStructure structure, in AssistContent content);
+ void handleAssist(in Bundle assistData, in AssistStructure structure, in AssistContent content,
+ int index, int count);
void handleScreenshot(in Bitmap screenshot);
void taskStarted(in Intent intent, int taskId);
void taskFinished(in Intent intent, int taskId);
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 6ff9fe7..e354ab3 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -77,7 +77,7 @@
*/
public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCallbacks2 {
static final String TAG = "VoiceInteractionSession";
- static final boolean DEBUG = true;
+ static final boolean DEBUG = false;
/**
* Flag received in {@link #onShow}: originator requested that the session be started with
@@ -110,6 +110,16 @@
*/
public static final int SHOW_SOURCE_ACTIVITY = 1<<4;
+ // Keys for Bundle values
+ /** @hide */
+ public static final String KEY_DATA = "data";
+ /** @hide */
+ public static final String KEY_STRUCTURE = "structure";
+ /** @hide */
+ public static final String KEY_CONTENT = "content";
+ /** @hide */
+ public static final String KEY_RECEIVER_EXTRAS = "receiverExtras";
+
final Context mContext;
final HandlerCaller mHandlerCaller;
@@ -229,7 +239,7 @@
@Override
public void handleAssist(final Bundle data, final AssistStructure structure,
- final AssistContent content) {
+ final AssistContent content, final int index, final int count) {
// We want to pre-warm the AssistStructure before handing it off to the main
// thread. We also want to do this on a separate thread, so that if the app
// is for some reason slow (due to slow filling in of async children in the
@@ -247,8 +257,9 @@
failure = e;
}
}
- mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOOOO(MSG_HANDLE_ASSIST,
- data, failure == null ? structure : null, failure, content));
+ mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOOOOII(MSG_HANDLE_ASSIST,
+ data, failure == null ? structure : null, failure, content,
+ index, count));
}
};
retriever.start();
@@ -831,9 +842,16 @@
case MSG_HANDLE_ASSIST:
args = (SomeArgs)msg.obj;
if (DEBUG) Log.d(TAG, "onHandleAssist: data=" + args.arg1
- + " structure=" + args.arg2 + " content=" + args.arg3);
- doOnHandleAssist((Bundle) args.arg1, (AssistStructure) args.arg2,
- (Throwable) args.arg3, (AssistContent) args.arg4);
+ + " structure=" + args.arg2 + " content=" + args.arg3
+ + " activityIndex=" + args.argi5 + " activityCount=" + args.argi6);
+ if (args.argi5 == 0) {
+ doOnHandleAssist((Bundle) args.arg1, (AssistStructure) args.arg2,
+ (Throwable) args.arg3, (AssistContent) args.arg4);
+ } else {
+ doOnHandleAssistSecondary((Bundle) args.arg1, (AssistStructure) args.arg2,
+ (Throwable) args.arg3, (AssistContent) args.arg4,
+ args.argi5, args.argi6);
+ }
break;
case MSG_HANDLE_SCREENSHOT:
if (DEBUG) Log.d(TAG, "onHandleScreenshot: " + msg.obj);
@@ -1320,6 +1338,14 @@
onHandleAssist(data, structure, content);
}
+ void doOnHandleAssistSecondary(Bundle data, AssistStructure structure, Throwable failure,
+ AssistContent content, int index, int count) {
+ if (failure != null) {
+ onAssistStructureFailure(failure);
+ }
+ onHandleAssistSecondary(data, structure, content, index, count);
+ }
+
/**
* Called when there has been a failure transferring the {@link AssistStructure} to
* the assistant. This may happen, for example, if the data is too large and results
@@ -1356,6 +1382,45 @@
}
/**
+ * Called to receive data from other applications that the user was or is interacting with,
+ * that are currently on the screen in a multi-window display environment, not including the
+ * currently focused activity. This could be
+ * a free-form window, a picture-in-picture window, or another window in a split-screen display.
+ * <p>
+ * This method is very similar to
+ * {@link #onHandleAssist} except that it is called
+ * for additional non-focused activities along with an index and count that indicates
+ * which additional activity the data is for. {@code index} will be between 1 and
+ * {@code count}-1 and this method is called once for each additional window, in no particular
+ * order. The {@code count} indicates how many windows to expect assist data for, including the
+ * top focused activity, which continues to be returned via {@link #onHandleAssist}.
+ * <p>
+ * To be responsive to assist requests, process assist data as soon as it is received,
+ * without waiting for all queued activities to return assist data.
+ *
+ * @param data Arbitrary data supplied by the app through
+ * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
+ * May be null if assist data has been disabled by the user or device policy.
+ * @param structure If available, the structure definition of all windows currently
+ * displayed by the app. May be null if assist data has been disabled by the user
+ * or device policy; will be an empty stub if the application has disabled assist
+ * by marking its window as secure.
+ * @param content Additional content data supplied by the app through
+ * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}.
+ * May be null if assist data has been disabled by the user or device policy; will
+ * not be automatically filled in with data from the app if the app has marked its
+ * window as secure.
+ * @param index the index of the additional activity that this data
+ * is for.
+ * @param count the total number of additional activities for which the assist data is being
+ * returned, including the focused activity that is returned via
+ * {@link #onHandleAssist}.
+ */
+ public void onHandleAssistSecondary(@Nullable Bundle data, @Nullable AssistStructure structure,
+ @Nullable AssistContent content, int index, int count) {
+ }
+
+ /**
* Called to receive a screenshot of what the user was currently viewing when an assist
* session is started. May be null if screenshots are disabled by the user, policy,
* or application. If the original show request did not specify
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 1eaa7cf..9b238ce 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -457,8 +457,17 @@
private class SynthHandler extends Handler {
private SpeechItem mCurrentSpeechItem = null;
- private ArrayList<Object> mFlushedObjects = new ArrayList<Object>();
- private boolean mFlushAll;
+ // When a message with QUEUE_FLUSH arrives we add the caller identity to the List and when a
+ // message with QUEUE_DESTROY arrives we increment mFlushAll. Then a message is added to the
+ // handler queue that removes the caller identify from the list and decrements the mFlushAll
+ // counter. This is so that when a message is processed and the caller identity is in the
+ // list or mFlushAll is not zero, we know that the message should be flushed.
+ // It's important that mFlushedObjects is a List and not a Set, and that mFlushAll is an
+ // int and not a bool. This is because when multiple messages arrive with QUEUE_FLUSH or
+ // QUEUE_DESTROY, we want to keep flushing messages until we arrive at the last QUEUE_FLUSH
+ // or QUEUE_DESTROY message.
+ private List<Object> mFlushedObjects = new ArrayList<>();
+ private int mFlushAll = 0;
public SynthHandler(Looper looper) {
super(looper);
@@ -467,7 +476,7 @@
private void startFlushingSpeechItems(Object callerIdentity) {
synchronized (mFlushedObjects) {
if (callerIdentity == null) {
- mFlushAll = true;
+ mFlushAll += 1;
} else {
mFlushedObjects.add(callerIdentity);
}
@@ -476,7 +485,7 @@
private void endFlushingSpeechItems(Object callerIdentity) {
synchronized (mFlushedObjects) {
if (callerIdentity == null) {
- mFlushAll = false;
+ mFlushAll -= 1;
} else {
mFlushedObjects.remove(callerIdentity);
}
@@ -484,7 +493,7 @@
}
private boolean isFlushed(SpeechItem speechItem) {
synchronized (mFlushedObjects) {
- return mFlushAll || mFlushedObjects.contains(speechItem.getCallerIdentity());
+ return mFlushAll > 0 || mFlushedObjects.contains(speechItem.getCallerIdentity());
}
}
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 94ce57a..239f2d0 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -683,7 +683,7 @@
// interface.
int leftLen = mLeftIndents == null ? 0 : mLeftIndents.length;
int rightLen = mRightIndents == null ? 0 : mRightIndents.length;
- int indentsLen = Math.max(1, Math.min(leftLen, rightLen) - mLineCount);
+ int indentsLen = Math.max(1, Math.max(leftLen, rightLen) - mLineCount);
int[] indents = new int[indentsLen];
for (int i = 0; i < indentsLen; i++) {
int leftMargin = mLeftIndents == null ? 0 :
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index 3564e11..e93e58d 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -48,6 +48,9 @@
implements KeyListener {
/* package */ static final Object OLD_SEL_START = new NoCopySpan.Concrete();
+ private static final int LINE_FEED = 0x0A;
+ private static final int CARRIAGE_RETURN = 0x0D;
+
private final Object mLock = new Object();
@GuardedBy("mLock")
@@ -110,34 +113,37 @@
// Initial state
final int STATE_START = 0;
+ // The offset is immediately before line feed.
+ final int STATE_LF = 1;
+
// The offset is immediately before a KEYCAP.
- final int STATE_BEFORE_KEYCAP = 1;
+ final int STATE_BEFORE_KEYCAP = 2;
// The offset is immediately before a variation selector and a KEYCAP.
- final int STATE_BEFORE_VS_AND_KEYCAP = 2;
+ final int STATE_BEFORE_VS_AND_KEYCAP = 3;
// The offset is immediately before an emoji modifier.
- final int STATE_BEFORE_EMOJI_MODIFIER = 3;
+ final int STATE_BEFORE_EMOJI_MODIFIER = 4;
// The offset is immediately before a variation selector and an emoji modifier.
- final int STATE_BEFORE_VS_AND_EMOJI_MODIFIER = 4;
+ final int STATE_BEFORE_VS_AND_EMOJI_MODIFIER = 5;
// The offset is immediately before a variation selector.
- final int STATE_BEFORE_VS = 5;
+ final int STATE_BEFORE_VS = 6;
// The offset is immediately before a ZWJ emoji.
- final int STATE_BEFORE_ZWJ_EMOJI = 6;
+ final int STATE_BEFORE_ZWJ_EMOJI = 7;
// The offset is immediately before a ZWJ that were seen before a ZWJ emoji.
- final int STATE_BEFORE_ZWJ = 7;
+ final int STATE_BEFORE_ZWJ = 8;
// The offset is immediately before a variation selector and a ZWJ that were seen before a
// ZWJ emoji.
- final int STATE_BEFORE_VS_AND_ZWJ = 8;
+ final int STATE_BEFORE_VS_AND_ZWJ = 9;
// The number of following RIS code points is odd.
- final int STATE_ODD_NUMBERED_RIS = 9;
+ final int STATE_ODD_NUMBERED_RIS = 10;
// The number of following RIS code points is even.
- final int STATE_EVEN_NUMBERED_RIS = 10;
+ final int STATE_EVEN_NUMBERED_RIS = 11;
// The state machine has been stopped.
- final int STATE_FINISHED = 11;
+ final int STATE_FINISHED = 12;
int deleteCharCount = 0; // Char count to be deleted by backspace.
int lastSeenVSCharCount = 0; // Char count of previous variation selector.
@@ -152,7 +158,9 @@
switch (state) {
case STATE_START:
deleteCharCount = Character.charCount(codePoint);
- if (isVariationSelector(codePoint)) {
+ if (codePoint == LINE_FEED) {
+ state = STATE_LF;
+ } else if (isVariationSelector(codePoint)) {
state = STATE_BEFORE_VS;
} else if (Emoji.isZwjEmoji(codePoint)) {
state = STATE_BEFORE_ZWJ_EMOJI;
@@ -166,6 +174,11 @@
state = STATE_FINISHED;
}
break;
+ case STATE_LF:
+ if (codePoint == CARRIAGE_RETURN) {
+ ++deleteCharCount;
+ }
+ state = STATE_FINISHED;
case STATE_ODD_NUMBERED_RIS:
if (Emoji.isRegionalIndicatorSymbol(codePoint)) {
deleteCharCount += 2; /* Char count of RIS */
diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java
index 9ed4850..0a452db 100644
--- a/core/java/android/util/Patterns.java
+++ b/core/java/android/util/Patterns.java
@@ -251,9 +251,9 @@
+ "|[1-9][0-9]|[0-9]))");
/**
- * Valid UCS characters defined in RFC 3987.
+ * Valid UCS characters defined in RFC 3987. Excludes space characters.
*/
- private static final String UCS_CHAR =
+ private static final String UCS_CHAR = "[" +
"\u00A0-\uD7FF" +
"\uF900-\uFDCF" +
"\uFDF0-\uFFEF" +
@@ -270,7 +270,8 @@
"\uDA80\uDC00-\uDABF\uDFFD" +
"\uDAC0\uDC00-\uDAFF\uDFFD" +
"\uDB00\uDC00-\uDB3F\uDFFD" +
- "\uDB44\uDC00-\uDB7F\uDFFD";
+ "\uDB44\uDC00-\uDB7F\uDFFD" +
+ "&&[^\u00A0[\u2000-\u200A]\u2028\u2029\u202F\u3000]]";
/**
* Valid characters for IRI label defined in RFC 3987.
diff --git a/core/java/android/view/IDockedStackListener.aidl b/core/java/android/view/IDockedStackListener.aidl
index cbc8dbd..88ac271 100644
--- a/core/java/android/view/IDockedStackListener.aidl
+++ b/core/java/android/view/IDockedStackListener.aidl
@@ -42,4 +42,9 @@
* @param animDuration The duration of the animation for changing the minimized state.
*/
void onDockedStackMinimizedChanged(boolean minimized, long animDuration);
+
+ /**
+ * Called when window manager repositioned the docked stack after a screen rotation change.
+ */
+ void onDockSideChanged(int newDockSide);
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index f44d4c1a..206ba16 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -903,6 +903,10 @@
nSerializeDisplayListTree(mNativeProxy);
}
+ public static boolean copySurfaceInto(Surface surface, Bitmap bitmap) {
+ return nCopySurfaceInto(surface, bitmap);
+ }
+
@Override
protected void finalize() throws Throwable {
try {
@@ -1040,4 +1044,6 @@
private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer);
private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
+
+ private static native boolean nCopySurfaceInto(Surface surface, Bitmap bitmap);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7e51096..8a6b5da 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10278,7 +10278,8 @@
*/
@Visibility boolean dispatchVisibilityAggregated(boolean isVisible) {
final boolean thisVisible = getVisibility() == VISIBLE;
- if (thisVisible) {
+ // If we're not visible but something is telling us we are, ignore it.
+ if (thisVisible || !isVisible) {
onVisibilityAggregated(isVisible);
}
return thisVisible && isVisible;
@@ -15741,8 +15742,10 @@
return;
}
- // Destroy any previous software drawing cache if needed
- if (mLayerType == LAYER_TYPE_SOFTWARE) {
+ if (layerType != LAYER_TYPE_SOFTWARE) {
+ // Destroy any previous software drawing cache if present
+ // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
+ // drawing cache created in View#draw when drawing to a SW canvas.
destroyDrawingCache();
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 94c4cef..e9ca623 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -549,8 +549,7 @@
// Compute surface insets required to draw at specified Z value.
// TODO: Use real shadow insets for a constant max Z.
if (!attrs.hasManualSurfaceInsets) {
- final int surfaceInset = (int) Math.ceil(view.getZ() * 2);
- attrs.surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset);
+ attrs.setSurfaceInsets(view, false /*manual*/, true /*preservePrevious*/);
}
CompatibilityInfo compatibilityInfo = mDisplayAdjustments.getCompatibilityInfo();
@@ -883,10 +882,12 @@
}
mWindowAttributes.privateFlags |= compatibleWindowFlag;
- // Restore old surface insets.
- mWindowAttributes.surfaceInsets.set(
- oldInsetLeft, oldInsetTop, oldInsetRight, oldInsetBottom);
- mWindowAttributes.hasManualSurfaceInsets = oldHasManualSurfaceInsets;
+ if (mWindowAttributes.preservePreviousSurfaceInsets) {
+ // Restore old surface insets.
+ mWindowAttributes.surfaceInsets.set(
+ oldInsetLeft, oldInsetTop, oldInsetRight, oldInsetBottom);
+ mWindowAttributes.hasManualSurfaceInsets = oldHasManualSurfaceInsets;
+ }
applyKeepScreenOnFlag(mWindowAttributes);
@@ -2558,6 +2559,7 @@
if (mAttachInfo.mHardwareRenderer != null) {
mAttachInfo.mHardwareRenderer.fence();
+ mAttachInfo.mHardwareRenderer.setStopped(mStopped);
}
if (LOCAL_LOGV) {
@@ -2707,6 +2709,13 @@
// shortly before the draw commands get send to the renderer.
final boolean updated = updateContentDrawBounds();
+ if (mReportNextDraw) {
+ // report next draw overrides setStopped()
+ // This value is re-sync'd to the value of mStopped
+ // in the handling of mReportNextDraw post-draw.
+ mAttachInfo.mHardwareRenderer.setStopped(false);
+ }
+
mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
if (updated) {
@@ -3376,6 +3385,16 @@
}
@Override
+ public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
+ if (msg.what == MSG_REQUEST_KEYBOARD_SHORTCUTS && msg.obj == null) {
+ // Debugging for b/27963013
+ throw new NullPointerException(
+ "Attempted to call MSG_REQUEST_KEYBOARD_SHORTCUTS with null receiver:");
+ }
+ return super.sendMessageAtTime(msg, uptimeMillis);
+ }
+
+ @Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_INVALIDATE:
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 584233c..89e146b 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1482,6 +1482,16 @@
public boolean hasManualSurfaceInsets;
/**
+ * Whether the previous surface insets should be used vs. what is currently set. When set
+ * to {@code true}, the view root will ignore surfaces insets in this object and use what
+ * it currently has.
+ *
+ * @see #surfaceInsets
+ * @hide
+ */
+ public boolean preservePreviousSurfaceInsets = true;
+
+ /**
* The desired bitmap format. May be one of the constants in
* {@link android.graphics.PixelFormat}. Default is OPAQUE.
*/
@@ -1716,6 +1726,16 @@
*/
public CharSequence accessibilityTitle;
+ /**
+ * Sets a timeout in milliseconds before which the window will be removed
+ * by the window manager. Useful for transient notifications like toasts
+ * so we don't have to rely on client cooperation to ensure the window
+ * is removed. Must be specified at window creation time.
+ *
+ * @hide
+ */
+ public long removeTimeoutMilliseconds = -1;
+
public LayoutParams() {
super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
type = TYPE_APPLICATION;
@@ -1764,13 +1784,23 @@
title = "";
mTitle = TextUtils.stringOrSpannedString(title);
- accessibilityTitle = mTitle;
}
public final CharSequence getTitle() {
return mTitle != null ? mTitle : "";
}
+ /**
+ * Sets the surface insets based on the elevation (visual z position) of the input view.
+ * @hide
+ */
+ public final void setSurfaceInsets(View view, boolean manual, boolean preservePrevious) {
+ final int surfaceInset = (int) Math.ceil(view.getZ() * 2);
+ surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset);
+ hasManualSurfaceInsets = manual;
+ preservePreviousSurfaceInsets = preservePrevious;
+ }
+
/** @hide */
@SystemApi
public final void setUserActivityTimeout(long timeout) {
@@ -1822,9 +1852,11 @@
out.writeInt(surfaceInsets.right);
out.writeInt(surfaceInsets.bottom);
out.writeInt(hasManualSurfaceInsets ? 1 : 0);
+ out.writeInt(preservePreviousSurfaceInsets ? 1 : 0);
out.writeInt(needsMenuKey);
out.writeInt(accessibilityIdOfAnchor);
TextUtils.writeToParcel(accessibilityTitle, out, parcelableFlags);
+ out.writeLong(removeTimeoutMilliseconds);
}
public static final Parcelable.Creator<LayoutParams> CREATOR
@@ -1874,9 +1906,11 @@
surfaceInsets.right = in.readInt();
surfaceInsets.bottom = in.readInt();
hasManualSurfaceInsets = in.readInt() != 0;
+ preservePreviousSurfaceInsets = in.readInt() != 0;
needsMenuKey = in.readInt();
accessibilityIdOfAnchor = in.readInt();
accessibilityTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ removeTimeoutMilliseconds = in.readLong();
}
@SuppressWarnings({"PointlessBitwiseExpression"})
@@ -2075,6 +2109,11 @@
changes |= SURFACE_INSETS_CHANGED;
}
+ if (preservePreviousSurfaceInsets != o.preservePreviousSurfaceInsets) {
+ preservePreviousSurfaceInsets = o.preservePreviousSurfaceInsets;
+ changes |= SURFACE_INSETS_CHANGED;
+ }
+
if (needsMenuKey != o.needsMenuKey) {
needsMenuKey = o.needsMenuKey;
changes |= NEEDS_MENU_KEY_CHANGED;
@@ -2092,6 +2131,9 @@
changes |= ACCESSIBILITY_TITLE_CHANGED;
}
+ // This can't change, it's only set at window creation time.
+ removeTimeoutMilliseconds = o.removeTimeoutMilliseconds;
+
return changes;
}
@@ -2200,11 +2242,15 @@
sb.append(" userActivityTimeout=").append(userActivityTimeout);
}
if (surfaceInsets.left != 0 || surfaceInsets.top != 0 || surfaceInsets.right != 0 ||
- surfaceInsets.bottom != 0 || hasManualSurfaceInsets) {
+ surfaceInsets.bottom != 0 || hasManualSurfaceInsets
+ || !preservePreviousSurfaceInsets) {
sb.append(" surfaceInsets=").append(surfaceInsets);
if (hasManualSurfaceInsets) {
sb.append(" (manual)");
}
+ if (!preservePreviousSurfaceInsets) {
+ sb.append(" (!preservePreviousSurfaceInsets)");
+ }
}
if (needsMenuKey != NEEDS_MENU_UNSET) {
sb.append(" needsMenuKey=");
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 02d2a8b..c1076e7 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -3842,7 +3842,15 @@
*/
public static RangeInfo obtain(int type, float min, float max, float current) {
RangeInfo info = sPool.acquire();
- return (info != null) ? info : new RangeInfo(type, min, max, current);
+ if (info == null) {
+ return new RangeInfo(type, min, max, current);
+ }
+
+ info.mType = type;
+ info.mMin = min;
+ info.mMax = max;
+ info.mCurrent = current;
+ return info;
}
/**
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..dc4db01 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -20,6 +20,9 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.content.res.Configuration;
+import android.icu.text.DisplayContext;
+import android.icu.text.LocaleDisplayNames;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -68,6 +71,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 +161,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 +272,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 +297,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) {
@@ -417,39 +424,97 @@
}
/**
- * @param context Context will be used for getting Locale and PackageManager.
- * @param packageName The package name of the IME
- * @param appInfo The application info of the IME
- * @return a display name for this subtype. The string resource of the label (mSubtypeNameResId)
- * may have exactly one %s in it. If there is, the %s part will be replaced with the locale's
- * display name by the formatter. If there is not, this method returns the string specified by
- * mSubtypeNameResId. If mSubtypeNameResId is not specified (== 0), it's up to the framework to
- * generate an appropriate display name.
+ * Returns a display name for this subtype.
+ *
+ * <p>If {@code subtypeNameResId} is specified (!= 0) text generated from that resource will
+ * be returned. The localized string resource of the label should be capitalized for inclusion
+ * in UI lists. The string resource may contain at most one {@code %s}. If present, the
+ * {@code %s} will be replaced with the display name of the subtype locale in the user's locale.
+ *
+ * <p>If {@code subtypeNameResId} is not specified (== 0) the framework returns the display name
+ * of the subtype locale, as capitalized for use in UI lists, in the user's locale.
+ *
+ * @param context {@link Context} will be used for getting {@link Locale} and
+ * {@link android.content.pm.PackageManager}.
+ * @param packageName The package name of the input method.
+ * @param appInfo The {@link ApplicationInfo} of the input method.
+ * @return a display name for this subtype.
*/
+ @NonNull
public CharSequence getDisplayName(
Context context, String packageName, ApplicationInfo appInfo) {
- final Locale locale = getLocaleObject();
- final String localeStr = locale != null ? locale.getDisplayName() : mSubtypeLocale;
if (mSubtypeNameResId == 0) {
- return localeStr;
+ return getLocaleDisplayName(getLocaleFromContext(context), getLocaleObject(),
+ DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU);
}
+
final CharSequence subtypeName = context.getPackageManager().getText(
packageName, mSubtypeNameResId, appInfo);
- if (!TextUtils.isEmpty(subtypeName)) {
- final String replacementString =
- containsExtraValueKey(EXTRA_KEY_UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)
- ? getExtraValueOf(EXTRA_KEY_UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)
- : localeStr;
- try {
- return String.format(
- subtypeName.toString(), replacementString != null ? replacementString : "");
- } catch (IllegalFormatException e) {
- Slog.w(TAG, "Found illegal format in subtype name("+ subtypeName + "): " + e);
- return "";
- }
- } else {
- return localeStr;
+ if (TextUtils.isEmpty(subtypeName)) {
+ return "";
}
+ final String subtypeNameString = subtypeName.toString();
+ String replacementString;
+ if (containsExtraValueKey(EXTRA_KEY_UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)) {
+ replacementString = getExtraValueOf(
+ EXTRA_KEY_UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME);
+ } else {
+ final DisplayContext displayContext;
+ if (TextUtils.equals(subtypeNameString, "%s")) {
+ displayContext = DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU;
+ } else if (subtypeNameString.startsWith("%s")) {
+ displayContext = DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE;
+ } else {
+ displayContext = DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE;
+ }
+ replacementString = getLocaleDisplayName(getLocaleFromContext(context),
+ getLocaleObject(), displayContext);
+ }
+ if (replacementString == null) {
+ replacementString = "";
+ }
+ try {
+ return String.format(subtypeNameString, replacementString);
+ } catch (IllegalFormatException e) {
+ Slog.w(TAG, "Found illegal format in subtype name("+ subtypeName + "): " + e);
+ return "";
+ }
+ }
+
+ @Nullable
+ private static Locale getLocaleFromContext(@Nullable final Context context) {
+ if (context == null) {
+ return null;
+ }
+ if (context.getResources() == null) {
+ return null;
+ }
+ final Configuration configuration = context.getResources().getConfiguration();
+ if (configuration == null) {
+ return null;
+ }
+ return configuration.getLocales().get(0);
+ }
+
+ /**
+ * @param displayLocale {@link Locale} to be used to display {@code localeToDisplay}
+ * @param localeToDisplay {@link Locale} to be displayed in {@code displayLocale}
+ * @param displayContext context parameter to be used to display {@code localeToDisplay} in
+ * {@code displayLocale}
+ * @return Returns the name of the {@code localeToDisplay} in the user's current locale.
+ */
+ @NonNull
+ private static String getLocaleDisplayName(
+ @Nullable Locale displayLocale, @Nullable Locale localeToDisplay,
+ final DisplayContext displayContext) {
+ if (localeToDisplay == null) {
+ return "";
+ }
+ final Locale nonNullDisplayLocale =
+ displayLocale != null ? displayLocale : Locale.getDefault();
+ return LocaleDisplayNames
+ .getInstance(nonNullDisplayLocale, displayContext)
+ .localeDisplayName(localeToDisplay);
}
private HashMap<String, String> getExtraValueHashMap() {
@@ -501,6 +566,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/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 0ac5731..f13cbae 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -18,13 +18,14 @@
import android.annotation.SystemApi;
import android.app.ActivityManagerInternal;
+import android.app.ActivityManagerNative;
import android.app.AppGlobals;
import android.app.Application;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.res.XmlResourceParser;
+import android.content.pm.Signature;
import android.os.Build;
import android.os.Process;
import android.os.RemoteException;
@@ -32,27 +33,21 @@
import android.os.StrictMode;
import android.os.SystemProperties;
import android.os.Trace;
-import android.provider.Settings;
-import android.provider.Settings.Secure;
import android.text.TextUtils;
import android.util.AndroidRuntimeException;
+import android.util.ArraySet;
import android.util.Log;
-import com.android.internal.util.XmlUtils;
import com.android.server.LocalServices;
import dalvik.system.VMRuntime;
import java.io.File;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
-import org.xmlpull.v1.XmlPullParserException;
-
/**
* Top level factory, used creating all the main WebView implementation classes.
*
@@ -192,52 +187,126 @@
}
}
+ /**
+ * Returns true if the signatures match, false otherwise
+ */
+ private static boolean signaturesEquals(Signature[] s1, Signature[] s2) {
+ if (s1 == null) {
+ return s2 == null;
+ }
+ if (s2 == null) return false;
+
+ ArraySet<Signature> set1 = new ArraySet<>();
+ for(Signature signature : s1) {
+ set1.add(signature);
+ }
+ ArraySet<Signature> set2 = new ArraySet<>();
+ for(Signature signature : s2) {
+ set2.add(signature);
+ }
+ return set1.equals(set2);
+ }
+
+ // Throws MissingWebViewPackageException on failure
+ private static void verifyPackageInfo(PackageInfo chosen, PackageInfo toUse) {
+ if (!chosen.packageName.equals(toUse.packageName)) {
+ throw new MissingWebViewPackageException("Failed to verify WebView provider, "
+ + "packageName mismatch, expected: "
+ + chosen.packageName + " actual: " + toUse.packageName);
+ }
+ if (chosen.versionCode > toUse.versionCode) {
+ throw new MissingWebViewPackageException("Failed to verify WebView provider, "
+ + "version code mismatch, expected: " + chosen.versionCode
+ + " actual: " + toUse.versionCode);
+ }
+ if (getWebViewLibrary(toUse.applicationInfo) == null) {
+ throw new MissingWebViewPackageException("Tried to load an invalid WebView provider: "
+ + toUse.packageName);
+ }
+ if (!signaturesEquals(chosen.signatures, toUse.signatures)) {
+ throw new MissingWebViewPackageException("Failed to verify WebView provider, "
+ + "signature mismatch");
+ }
+ }
+
+ private static Context getWebViewContextAndSetProvider() {
+ Application initialApplication = AppGlobals.getInitialApplication();
+ try {
+ WebViewProviderResponse response = null;
+ Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW,
+ "WebViewUpdateService.waitForAndGetProvider()");
+ try {
+ response = getUpdateService().waitForAndGetProvider();
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
+ }
+ if (response.status != LIBLOAD_SUCCESS) {
+ throw new MissingWebViewPackageException("Failed to load WebView provider: "
+ + getWebViewPreparationErrorReason(response.status));
+ }
+ // Register to be killed before fetching package info - so that we will be
+ // killed if the package info goes out-of-date.
+ Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "ActivityManager.addPackageDependency()");
+ try {
+ ActivityManagerNative.getDefault().addPackageDependency(
+ response.packageInfo.packageName);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
+ }
+ // Fetch package info and verify it against the chosen package
+ PackageInfo newPackageInfo = null;
+ Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "PackageManager.getPackageInfo()");
+ try {
+ newPackageInfo = initialApplication.getPackageManager().getPackageInfo(
+ response.packageInfo.packageName,
+ PackageManager.GET_SHARED_LIBRARY_FILES
+ | PackageManager.MATCH_DEBUG_TRIAGED_MISSING
+ // Make sure that we fetch the current provider even if its not
+ // installed for the current user
+ | PackageManager.MATCH_UNINSTALLED_PACKAGES
+ // Fetch signatures for verification
+ | PackageManager.GET_SIGNATURES
+ // Get meta-data for meta data flag verification
+ | PackageManager.GET_META_DATA);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
+ }
+
+ // Validate the newly fetched package info, throws MissingWebViewPackageException on
+ // failure
+ verifyPackageInfo(response.packageInfo, newPackageInfo);
+
+ Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW,
+ "initialApplication.createApplicationContext");
+ try {
+ // Construct an app context to load the Java code into the current app.
+ Context webViewContext = initialApplication.createApplicationContext(
+ newPackageInfo.applicationInfo,
+ Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+ sPackageInfo = response.packageInfo;
+ return webViewContext;
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
+ }
+ } catch (RemoteException | PackageManager.NameNotFoundException e) {
+ throw new MissingWebViewPackageException("Failed to load WebView provider: " + e);
+ }
+ }
+
private static Class<WebViewFactoryProvider> getProviderClass() {
+ Context webViewContext = null;
+ Application initialApplication = AppGlobals.getInitialApplication();
+
try {
Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW,
- "WebViewFactory.waitForProviderAndSetPackageInfo()");
+ "WebViewFactory.getWebViewContextAndSetProvider()");
try {
- // First fetch the package info so we can log the webview package version.
- int res = waitForProviderAndSetPackageInfo();
- if (res != LIBLOAD_SUCCESS) {
- throw new MissingWebViewPackageException(
- "Failed to load WebView provider, error: "
- + getWebViewPreparationErrorReason(res));
- }
+ webViewContext = getWebViewContextAndSetProvider();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
}
Log.i(LOGTAG, "Loading " + sPackageInfo.packageName + " version " +
- sPackageInfo.versionName + " (code " + sPackageInfo.versionCode + ")");
-
- Application initialApplication = AppGlobals.getInitialApplication();
- Context webViewContext = null;
- Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "PackageManager.getApplicationInfo()");
- try {
- // Construct a package context to load the Java code into the current app.
- // This is done as early as possible since by constructing a package context we
- // register the WebView package as a dependency for the current application so that
- // when the WebView package is updated this application will be killed.
- ApplicationInfo applicationInfo =
- initialApplication.getPackageManager().getApplicationInfo(
- sPackageInfo.packageName, PackageManager.GET_SHARED_LIBRARY_FILES
- | PackageManager.MATCH_DEBUG_TRIAGED_MISSING
- // make sure that we fetch the current provider even if its not installed
- // for the current user
- | PackageManager.MATCH_UNINSTALLED_PACKAGES);
- Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW,
- "initialApplication.createApplicationContext");
- try {
- webViewContext = initialApplication.createApplicationContext(applicationInfo,
- Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
- }
- } catch (PackageManager.NameNotFoundException e) {
- throw new MissingWebViewPackageException(e);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
- }
+ sPackageInfo.versionName + " (code " + sPackageInfo.versionCode + ")");
Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()");
try {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 0d8d8ed..bb883ea 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1290,9 +1290,7 @@
// We may wrap that in another view, so we'll need to manually specify
// the surface insets.
- final int surfaceInset = (int) Math.ceil(mBackgroundView.getZ() * 2);
- p.surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset);
- p.hasManualSurfaceInsets = true;
+ p.setSurfaceInsets(mBackgroundView, true /*manual*/, true /*preservePrevious*/);
mPopupViewInitialLayoutDirectionInherited =
(mContentView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT);
@@ -1514,6 +1512,24 @@
outParams.x = drawingLocation[0] + xOffset;
outParams.y = drawingLocation[1] + anchorHeight + yOffset;
+ // Let the window manager know to align the top to y.
+ outParams.gravity = Gravity.LEFT | Gravity.TOP;
+ outParams.width = width;
+ outParams.height = height;
+
+ // If width or height is unspecified. We can leave it to the window manager to match
+ // to the parent size, but for our local purposes of calculating positioning, we need
+ // to fill in real width and height values.
+ final Rect displayFrame = new Rect();
+ anchor.getWindowVisibleDisplayFrame(displayFrame);
+ if (width < 0) {
+ width = displayFrame.right - displayFrame.left;
+ }
+ if (height < 0) {
+ height = displayFrame.bottom - displayFrame.top;
+ }
+
+
// If we need to adjust for gravity RIGHT, align to the bottom-right
// corner of the anchor (still accounting for offsets).
final int hgrav = Gravity.getAbsoluteGravity(gravity, anchor.getLayoutDirection())
@@ -1522,17 +1538,9 @@
outParams.x -= width - anchorWidth;
}
- // Let the window manager know to align the top to y.
- outParams.gravity = Gravity.LEFT | Gravity.TOP;
- outParams.width = width;
- outParams.height = height;
-
final int[] screenLocation = mTmpScreenLocation;
anchor.getLocationOnScreen(screenLocation);
- final Rect displayFrame = new Rect();
- anchor.getWindowVisibleDisplayFrame(displayFrame);
-
// First, attempt to fit the popup vertically without resizing.
final boolean fitsVertical = tryFitVertical(outParams, yOffset, height,
anchorHeight, drawingLocation[1], screenLocation[1], displayFrame.top,
@@ -1581,7 +1589,7 @@
return true;
}
- final int spaceAbove = displayFrameTop + anchorTopInScreen - anchorHeight;
+ final int spaceAbove = anchorTopInScreen - anchorHeight - displayFrameTop;
if (height <= spaceAbove) {
// Move everything up.
if (mOverlapAnchor) {
@@ -2116,10 +2124,10 @@
// If an explicit width/height has not specified, use the most recent
// explicitly specified value (either from setWidth/Height or update).
- if (width == -1) {
+ if (width < 0) {
width = mWidth;
}
- if (height == -1) {
+ if (height < 0) {
height = mHeight;
}
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index e9fa26c..9c9784b 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -1347,6 +1347,13 @@
if (d instanceof LayerDrawable) {
d = ((LayerDrawable) d).findDrawableByLayerId(id);
+ if (d == null) {
+ // If we can't find the requested layer, fall back to setting
+ // the level of the entire drawable. This will break if
+ // progress is set on multiple elements, but the theme-default
+ // drawable will always have all layer IDs present.
+ d = mCurrentDrawable;
+ }
}
if (d != null) {
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 7220256..24d2c8e 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -58,8 +58,8 @@
private static final String TAG = "RadialTimePickerView";
- private static final int HOURS = 0;
- private static final int MINUTES = 1;
+ public static final int HOURS = 0;
+ public static final int MINUTES = 1;
private static final int HOURS_INNER = 2;
private static final int SELECTOR_CIRCLE = 0;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 6d2cea6..a9b7f4e 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1856,6 +1856,7 @@
public static final int LAYOUT_MARGIN_END = 1;
/** Set width */
public static final int LAYOUT_WIDTH = 2;
+ public static final int LAYOUT_MARGIN_BOTTOM = 3;
/**
* @param viewId ID of the view alter
@@ -1898,6 +1899,12 @@
target.setLayoutParams(layoutParams);
}
break;
+ case LAYOUT_MARGIN_BOTTOM:
+ if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
+ ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin = value;
+ target.setLayoutParams(layoutParams);
+ }
+ break;
case LAYOUT_WIDTH:
layoutParams.width = value;
target.setLayoutParams(layoutParams);
@@ -2870,6 +2877,16 @@
}
/**
+ * Equivalent to setting {@link android.view.ViewGroup.MarginLayoutParams#bottomMargin}.
+ *
+ * @hide
+ */
+ public void setViewLayoutMarginBottom(int viewId, int bottomMargin) {
+ addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_MARGIN_BOTTOM,
+ bottomMargin));
+ }
+
+ /**
* Equivalent to setting {@link android.view.ViewGroup.LayoutParams#width}.
* @hide
*/
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index ee716df..1a81d20 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -849,10 +849,12 @@
mEnabledDayStart = MathUtils.constrain(enabledDayStart, 1, mDaysInMonth);
mEnabledDayEnd = MathUtils.constrain(enabledDayEnd, mEnabledDayStart, mDaysInMonth);
+ updateMonthYearLabel();
+ updateDayOfWeekLabels();
+
// Invalidate cached accessibility information.
mTouchHelper.invalidateRoot();
-
- updateMonthYearLabel();
+ invalidate();
if (DEBUG_WRONG_DATE) {
Log.d(LOG_TAG, "mMonth = " + mMonth);
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
index ff10287..a585d75 100644
--- a/core/java/android/widget/TextClock.java
+++ b/core/java/android/widget/TextClock.java
@@ -555,7 +555,15 @@
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
- getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());
+ // OK, this is gross but needed. This class is supported by the
+ // remote views mechanism and as a part of that the remote views
+ // can be inflated by a context for another user without the app
+ // having interact users permission - just for loading resources.
+ // For example, when adding widgets from a managed profile to the
+ // home screen. Therefore, we register the receiver as the user
+ // the app is running as not the one the context is for.
+ getContext().registerReceiverAsUser(mIntentReceiver, android.os.Process.myUserHandle(),
+ filter, null, getHandler());
}
private void registerObserver() {
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 4a24e26..0c3892d 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -58,8 +58,8 @@
private static final long DELAY_COMMIT_MILLIS = 2000;
// Index used by RadialPickerLayout
- private static final int HOUR_INDEX = 0;
- private static final int MINUTE_INDEX = 1;
+ private static final int HOUR_INDEX = RadialTimePickerView.HOURS;
+ private static final int MINUTE_INDEX = RadialTimePickerView.MINUTES;
// NOT a real index for the purpose of what's showing.
private static final int AMPM_INDEX = 2;
@@ -82,6 +82,10 @@
private final Calendar mTempCalendar;
+ // Accessibility strings.
+ private final String mSelectHours;
+ private final String mSelectMinutes;
+
private boolean mIsEnabled = true;
private boolean mAllowAutoAdvance;
private int mInitialHourOfDay;
@@ -89,10 +93,6 @@
private boolean mIs24Hour;
private boolean mIsAmPmAtStart;
- // Accessibility strings.
- private String mSelectHours;
- private String mSelectMinutes;
-
// Localization data.
private boolean mHourFormatShowLeadingZero;
private boolean mHourFormatStartsAtZero;
@@ -520,11 +520,15 @@
} else {
flags |= DateUtils.FORMAT_12HOUR;
}
+
mTempCalendar.set(Calendar.HOUR_OF_DAY, getHour());
mTempCalendar.set(Calendar.MINUTE, getMinute());
- String selectedDate = DateUtils.formatDateTime(mContext,
+
+ final String selectedTime = DateUtils.formatDateTime(mContext,
mTempCalendar.getTimeInMillis(), flags);
- event.getText().add(selectedDate);
+ final String selectionMode = mRadialTimePickerView.getCurrentItemShowing() == HOUR_INDEX ?
+ mSelectHours : mSelectMinutes;
+ event.getText().add(selectedTime + " " + selectionMode);
}
/**
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 207f675..7762675 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -163,6 +163,7 @@
*/
public void setDuration(@Duration int duration) {
mDuration = duration;
+ mTN.mDuration = duration;
}
/**
@@ -342,7 +343,7 @@
};
private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
- final Handler mHandler = new Handler();
+ final Handler mHandler = new Handler();
int mGravity;
int mX, mY;
@@ -352,9 +353,13 @@
View mView;
View mNextView;
+ int mDuration;
WindowManager mWM;
+ static final long SHORT_DURATION_TIMEOUT = 5000;
+ static final long LONG_DURATION_TIMEOUT = 1000;
+
TN() {
// XXX This should be changed to use a Dialog, with a Theme.Toast
// defined that sets up the layout params appropriately.
@@ -417,6 +422,8 @@
mParams.verticalMargin = mVerticalMargin;
mParams.horizontalMargin = mHorizontalMargin;
mParams.packageName = packageName;
+ mParams.removeTimeoutMilliseconds = mDuration ==
+ Toast.LENGTH_LONG ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT;
if (mView.getParent() != null) {
if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
mWM.removeView(mView);
diff --git a/core/java/com/android/internal/app/LocaleHelper.java b/core/java/com/android/internal/app/LocaleHelper.java
index a9d5113..7e9587a 100644
--- a/core/java/com/android/internal/app/LocaleHelper.java
+++ b/core/java/com/android/internal/app/LocaleHelper.java
@@ -90,6 +90,15 @@
return str.toUpperCase();
}
+ // For some locales we want to use a "dialect" form, for instance
+ // "Dari" instead of "Persian (Afghanistan)", or "Moldavian" instead of "Romanian (Moldova)"
+ private static boolean shouldUseDialectName(Locale locale) {
+ final String lang = locale.getLanguage();
+ return "fa".equals(lang) // Persian
+ || "ro".equals(lang) // Romanian
+ || "zh".equals(lang); // Chinese
+ }
+
/**
* Returns the locale localized for display in the provided locale.
*
@@ -99,8 +108,10 @@
* @return the localized name of the locale.
*/
public static String getDisplayName(Locale locale, Locale displayLocale, boolean sentenceCase) {
- String result = ULocale.getDisplayNameWithDialect(locale.toLanguageTag(),
- ULocale.forLocale(displayLocale));
+ final ULocale displayULocale = ULocale.forLocale(displayLocale);
+ String result = shouldUseDialectName(locale)
+ ? ULocale.getDisplayNameWithDialect(locale.toLanguageTag(), displayULocale)
+ : ULocale.getDisplayName(locale.toLanguageTag(), displayULocale);
return sentenceCase ? toSentenceCase(result, displayLocale) : result;
}
@@ -112,9 +123,7 @@
* @return the localized name of the locale.
*/
public static String getDisplayName(Locale locale, boolean sentenceCase) {
- String result = ULocale.getDisplayNameWithDialect(locale.toLanguageTag(),
- ULocale.getDefault());
- return sentenceCase ? toSentenceCase(result, Locale.getDefault()) : result;
+ return getDisplayName(locale, Locale.getDefault(), sentenceCase);
}
/**
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index f2bf9e1..085e159 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -16,7 +16,9 @@
package com.android.internal.app;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StringRes;
import android.app.Activity;
import android.app.ActivityThread;
import android.app.VoiceInteractor.PickOptionRequest;
@@ -24,6 +26,7 @@
import android.app.VoiceInteractor.Prompt;
import android.content.pm.ComponentInfo;
import android.os.AsyncTask;
+import android.provider.MediaStore;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Slog;
@@ -119,37 +122,62 @@
}
};
+ /**
+ * Get the string resource to be used as a label for the link to the resolver activity for an
+ * action.
+ *
+ * @param action The action to resolve
+ *
+ * @return The string resource to be used as a label
+ */
+ public static @StringRes int getLabelRes(String action) {
+ return ActionTitle.forAction(action).labelRes;
+ }
+
private enum ActionTitle {
VIEW(Intent.ACTION_VIEW,
com.android.internal.R.string.whichViewApplication,
- com.android.internal.R.string.whichViewApplicationNamed),
+ com.android.internal.R.string.whichViewApplicationNamed,
+ com.android.internal.R.string.whichViewApplicationLabel),
EDIT(Intent.ACTION_EDIT,
com.android.internal.R.string.whichEditApplication,
- com.android.internal.R.string.whichEditApplicationNamed),
+ com.android.internal.R.string.whichEditApplicationNamed,
+ com.android.internal.R.string.whichEditApplicationLabel),
SEND(Intent.ACTION_SEND,
com.android.internal.R.string.whichSendApplication,
- com.android.internal.R.string.whichSendApplicationNamed),
+ com.android.internal.R.string.whichSendApplicationNamed,
+ com.android.internal.R.string.whichSendApplicationLabel),
SENDTO(Intent.ACTION_SENDTO,
com.android.internal.R.string.whichSendToApplication,
- com.android.internal.R.string.whichSendToApplicationNamed),
+ com.android.internal.R.string.whichSendToApplicationNamed,
+ com.android.internal.R.string.whichSendToApplicationLabel),
SEND_MULTIPLE(Intent.ACTION_SEND_MULTIPLE,
com.android.internal.R.string.whichSendApplication,
- com.android.internal.R.string.whichSendApplicationNamed),
+ com.android.internal.R.string.whichSendApplicationNamed,
+ com.android.internal.R.string.whichSendApplicationLabel),
+ CAPTURE_IMAGE(MediaStore.ACTION_IMAGE_CAPTURE,
+ com.android.internal.R.string.whichImageCaptureApplication,
+ com.android.internal.R.string.whichImageCaptureApplicationNamed,
+ com.android.internal.R.string.whichImageCaptureApplicationLabel),
DEFAULT(null,
com.android.internal.R.string.whichApplication,
- com.android.internal.R.string.whichApplicationNamed),
+ com.android.internal.R.string.whichApplicationNamed,
+ com.android.internal.R.string.whichApplicationLabel),
HOME(Intent.ACTION_MAIN,
com.android.internal.R.string.whichHomeApplication,
- com.android.internal.R.string.whichHomeApplicationNamed);
+ com.android.internal.R.string.whichHomeApplicationNamed,
+ com.android.internal.R.string.whichHomeApplicationLabel);
public final String action;
public final int titleRes;
public final int namedTitleRes;
+ public final @StringRes int labelRes;
- ActionTitle(String action, int titleRes, int namedTitleRes) {
+ ActionTitle(String action, int titleRes, int namedTitleRes, @StringRes int labelRes) {
this.action = action;
this.titleRes = titleRes;
this.namedTitleRes = namedTitleRes;
+ this.labelRes = labelRes;
}
public static ActionTitle forAction(String action) {
@@ -640,12 +668,19 @@
&& mAdapter.mOrigResolveList != null) {
// Build a reasonable intent filter, based on what matched.
IntentFilter filter = new IntentFilter();
- String action = intent.getAction();
+ Intent filterIntent;
+ if (intent.getSelector() != null) {
+ filterIntent = intent.getSelector();
+ } else {
+ filterIntent = intent;
+ }
+
+ String action = filterIntent.getAction();
if (action != null) {
filter.addAction(action);
}
- Set<String> categories = intent.getCategories();
+ Set<String> categories = filterIntent.getCategories();
if (categories != null) {
for (String cat : categories) {
filter.addCategory(cat);
@@ -654,9 +689,9 @@
filter.addCategory(Intent.CATEGORY_DEFAULT);
int cat = ri.match & IntentFilter.MATCH_CATEGORY_MASK;
- Uri data = intent.getData();
+ Uri data = filterIntent.getData();
if (cat == IntentFilter.MATCH_CATEGORY_TYPE) {
- String mimeType = intent.resolveType(this);
+ String mimeType = filterIntent.resolveType(this);
if (mimeType != null) {
try {
filter.addDataType(mimeType);
@@ -760,7 +795,7 @@
} else {
try {
AppGlobals.getPackageManager().setLastChosenActivity(intent,
- intent.resolveTypeIfNeeded(getContentResolver()),
+ intent.resolveType(getContentResolver()),
PackageManager.MATCH_DEFAULT_ONLY,
filter, bestMatch, intent.getComponent());
} catch (RemoteException re) {
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index 06542f7..2f80b86 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -516,7 +516,7 @@
out.writeInt((int)val);
} else {
int top = ~((int)((val>>32)&0x7fffffff));
- int bottom = (int)(val&0xfffffff);
+ int bottom = (int)(val&0x0ffffffffL);
out.writeInt(top);
out.writeInt(bottom);
}
diff --git a/core/java/com/android/internal/app/procstats/SparseMappingTable.java b/core/java/com/android/internal/app/procstats/SparseMappingTable.java
index cd4f7b6..f941836 100644
--- a/core/java/com/android/internal/app/procstats/SparseMappingTable.java
+++ b/core/java/com/android/internal/app/procstats/SparseMappingTable.java
@@ -68,11 +68,8 @@
* A table of data as stored in a SparseMappingTable.
*/
public static class Table {
- // When mSequence is this this our data better be empty
- private static final int UNINITIALIZED_SEQUENCE = -1;
-
private SparseMappingTable mParent;
- private int mSequence = UNINITIALIZED_SEQUENCE;
+ private int mSequence = 1;
private int[] mTable;
private int mSize;
@@ -119,12 +116,6 @@
* but should be considered opaque to the caller.
*/
public int getOrAddKey(byte id, int count) {
- // This is the only place we add data to mParent.mLongs, so this is the time
- // to update our sequence to match there.
- if (mSequence == UNINITIALIZED_SEQUENCE) {
- mSequence = mParent.mSequence;
- }
-
assertConsistency();
final int idx = binarySearch(id);
@@ -311,7 +302,7 @@
// Reset our sequence number. This will make all read/write calls
// start to fail, and then when we re-allocate it will be re-synced
// to that of mParent.
- mSequence = UNINITIALIZED_SEQUENCE;
+ mSequence = mParent.mSequence;
}
/**
@@ -377,27 +368,19 @@
// 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
+ // we have been reset and our. If our sequence is UNITIALIZED_SEQUENCE, then
+ // it's possible that everything is working fine and we just haven't been
+ // written to since the last resetTable().
if (mSequence != mParent.mSequence) {
if (mSequence < mParent.mSequence) {
- logOrThrow("Sequence mismatch. SparseMappingTable.resetTable()"
+ logOrThrow("Sequence mismatch. SparseMappingTable.reset()"
+ " called but not Table.resetTable() -- "
+ dumpInternalState());
return;
} else if (mSequence > mParent.mSequence) {
logOrThrow("Sequence mismatch. Table.resetTable()"
- + " called but not SparseMappingTable.resetTable() -- "
+ + " called but not SparseMappingTable.reset() -- "
+ dumpInternalState());
return;
}
@@ -494,6 +477,10 @@
}
}
+ public SparseMappingTable() {
+ mLongs.add(new long[ARRAY_SIZE]);
+ }
+
/**
* Wipe out all the data.
*/
@@ -545,6 +532,35 @@
}
/**
+ * Return a string for debugging.
+ */
+ public String dumpInternalState(boolean includeData) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("SparseMappingTable{");
+ sb.append("mSequence=");
+ sb.append(mSequence);
+ sb.append(" mNextIndex=");
+ sb.append(mNextIndex);
+ sb.append(" mLongs.size=");
+ final int N = mLongs.size();
+ sb.append(N);
+ sb.append("\n");
+ if (includeData) {
+ for (int i=0; i<N; i++) {
+ final long[] array = mLongs.get(i);
+ for (int j=0; j<array.length; j++) {
+ if (i == N-1 && j == mNextIndex) {
+ break;
+ }
+ sb.append(String.format(" %4d %d 0x%016x %-19d\n", i, j, array[j], array[j]));
+ }
+ }
+ }
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
* Write the long array to the parcel in a compacted form. Does not allow negative
* values in the array.
*/
@@ -559,7 +575,7 @@
out.writeInt((int)val);
} else {
int top = ~((int)((val>>32)&0x7fffffff));
- int bottom = (int)(val&0xfffffff);
+ int bottom = (int)(val&0x0ffffffffL);
out.writeInt(top);
out.writeInt(bottom);
}
@@ -629,7 +645,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..8d11783 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -16,6 +16,7 @@
package com.android.internal.inputmethod;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;
import android.text.TextUtils;
@@ -284,8 +285,22 @@
return -1;
}
+ /**
+ * Provides the basic operation to implement bi-directional IME rotation.
+ * @param onlyCurrentIme {@code true} to limit the search space to IME subtypes that belong
+ * to {@code imi}.
+ * @param imi {@link InputMethodInfo} that will be used in conjunction with {@code subtype}
+ * from which we find the adjacent IME subtype.
+ * @param subtype {@link InputMethodSubtype} that will be used in conjunction with
+ * {@code imi} from which we find the next IME subtype. {@code null} if the input method
+ * does not have a subtype.
+ * @param forward {@code true} to do forward search the next IME subtype. Specify
+ * {@code false} to do backward search.
+ * @return The IME subtype found. {@code null} if no IME subtype is found.
+ */
+ @Nullable
public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme,
- InputMethodInfo imi, InputMethodSubtype subtype) {
+ InputMethodInfo imi, @Nullable InputMethodSubtype subtype, boolean forward) {
if (imi == null) {
return null;
}
@@ -297,8 +312,9 @@
return null;
}
final int N = mImeSubtypeList.size();
- for (int offset = 1; offset < N; ++offset) {
- // Start searching the next IME/subtype from the next of the current index.
+ for (int i = 1; i < N; ++i) {
+ // Start searching the next IME/subtype from +/- 1 indices.
+ 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
@@ -370,8 +386,22 @@
mUsageHistoryOfSubtypeListItemIndex[0] = currentItemIndex;
}
+ /**
+ * Provides the basic operation to implement bi-directional IME rotation.
+ * @param onlyCurrentIme {@code true} to limit the search space to IME subtypes that belong
+ * to {@code imi}.
+ * @param imi {@link InputMethodInfo} that will be used in conjunction with {@code subtype}
+ * from which we find the adjacent IME subtype.
+ * @param subtype {@link InputMethodSubtype} that will be used in conjunction with
+ * {@code imi} from which we find the next IME subtype. {@code null} if the input method
+ * does not have a subtype.
+ * @param forward {@code true} to do forward search the next IME subtype. Specify
+ * {@code false} to do backward search.
+ * @return The IME subtype found. {@code null} if no IME subtype is found.
+ */
+ @Nullable
public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme,
- InputMethodInfo imi, InputMethodSubtype subtype) {
+ InputMethodInfo imi, @Nullable InputMethodSubtype subtype, boolean forward) {
int currentUsageRank = getUsageRank(imi, subtype);
if (currentUsageRank < 0) {
if (DEBUG) {
@@ -381,7 +411,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 =
@@ -454,17 +485,31 @@
mSwitchingUnawareRotationList = switchingUnawareRotationList;
}
+ /**
+ * Provides the basic operation to implement bi-directional IME rotation.
+ * @param onlyCurrentIme {@code true} to limit the search space to IME subtypes that belong
+ * to {@code imi}.
+ * @param imi {@link InputMethodInfo} that will be used in conjunction with {@code subtype}
+ * from which we find the adjacent IME subtype.
+ * @param subtype {@link InputMethodSubtype} that will be used in conjunction with
+ * {@code imi} from which we find the next IME subtype. {@code null} if the input method
+ * does not have a subtype.
+ * @param forward {@code true} to do forward search the next IME subtype. Specify
+ * {@code false} to do backward search.
+ * @return The IME subtype found. {@code null} if no IME subtype is found.
+ */
+ @Nullable
public ImeSubtypeListItem getNextInputMethod(boolean onlyCurrentIme, InputMethodInfo imi,
- InputMethodSubtype subtype) {
+ @Nullable 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 +577,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/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index bbefcb5..10afdb8 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -1745,6 +1745,9 @@
}
public void add(String name, T obj) {
+ if (name == null) {
+ name = "";
+ }
mMap.put(name, obj);
if (OVERFLOW_NAME.equals(name)) {
mCurOverflow = obj;
@@ -1776,6 +1779,9 @@
}
public T startObject(String name) {
+ if (name == null) {
+ name = "";
+ }
T obj = mMap.get(name);
if (obj != null) {
return obj;
@@ -1825,6 +1831,9 @@
}
public T stopObject(String name) {
+ if (name == null) {
+ name = "";
+ }
T obj = mMap.get(name);
if (obj != null) {
return obj;
diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java
index 113768e..c26fc3a 100644
--- a/core/java/com/android/internal/os/HandlerCaller.java
+++ b/core/java/com/android/internal/os/HandlerCaller.java
@@ -209,6 +209,18 @@
return mH.obtainMessage(what, 0, 0, args);
}
+ public Message obtainMessageOOOOII(int what, Object arg1, Object arg2,
+ Object arg3, Object arg4, int arg5, int arg6) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = arg1;
+ args.arg2 = arg2;
+ args.arg3 = arg3;
+ args.arg4 = arg4;
+ args.argi5 = arg5;
+ args.argi6 = arg6;
+ return mH.obtainMessage(what, 0, 0, args);
+ }
+
public Message obtainMessageIIII(int what, int arg1, int arg2,
int arg3, int arg4) {
SomeArgs args = SomeArgs.obtain();
@@ -218,7 +230,7 @@
args.argi4 = arg4;
return mH.obtainMessage(what, 0, 0, args);
}
-
+
public Message obtainMessageIIIIII(int what, int arg1, int arg2,
int arg3, int arg4, int arg5, int arg6) {
SomeArgs args = SomeArgs.obtain();
@@ -230,7 +242,7 @@
args.argi6 = arg6;
return mH.obtainMessage(what, 0, 0, args);
}
-
+
public Message obtainMessageIIIIO(int what, int arg1, int arg2,
int arg3, int arg4, Object arg5) {
SomeArgs args = SomeArgs.obtain();
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/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 5980ab6..78b5d61 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -43,6 +43,7 @@
import dalvik.system.DexFile;
import dalvik.system.PathClassLoader;
import dalvik.system.VMRuntime;
+import dalvik.system.ZygoteHooks;
import libcore.io.IoUtils;
@@ -597,6 +598,10 @@
}
public static void main(String argv[]) {
+ // Mark zygote start. This ensures that thread creation will throw
+ // an error.
+ ZygoteHooks.startZygoteNoThreadCreation();
+
try {
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
RuntimeInit.enableDdms();
@@ -648,6 +653,8 @@
// Zygote process unmounts root storage spaces.
Zygote.nativeUnmountStorageOnInit();
+ ZygoteHooks.stopZygoteNoThreadCreation();
+
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index f9ac563..3aa7719 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -210,7 +210,6 @@
private Drawable mResizingBackgroundDrawable;
private Drawable mCaptionBackgroundDrawable;
private Drawable mUserCaptionBackgroundDrawable;
- private Drawable mOriginalBackgroundDrawable;
private float mAvailableWidth;
@@ -891,11 +890,6 @@
mBackgroundPadding.setEmpty();
}
drawableChanged();
-
- // Make sure we don't reset to the old drawable when finishing resizing.
- if (mResizeMode != RESIZE_MODE_INVALID) {
- mOriginalBackgroundDrawable = null;
- }
}
}
@@ -1960,9 +1954,6 @@
updateElevation();
updateColorViews(null /* insets */, false);
-
- mOriginalBackgroundDrawable = getBackground();
- setBackgroundDrawable(null);
}
mResizeMode = resizeMode;
getViewRootImpl().requestInvalidateRootRenderNode();
@@ -1974,10 +1965,6 @@
updateColorViews(null /* insets */, false);
mResizeMode = RESIZE_MODE_INVALID;
getViewRootImpl().requestInvalidateRootRenderNode();
- if (mOriginalBackgroundDrawable != null) {
- setBackgroundDrawable(mOriginalBackgroundDrawable);
- mOriginalBackgroundDrawable = null;
- }
}
@Override
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 d2ff9bc..fe63267 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -1403,10 +1403,12 @@
@Override
public final void setElevation(float elevation) {
mElevation = elevation;
+ final WindowManager.LayoutParams attrs = getAttributes();
if (mDecor != null) {
mDecor.setElevation(elevation);
+ attrs.setSurfaceInsets(mDecor, true /*manual*/, false /*preservePrevious*/);
}
- dispatchWindowAttributesChanged(getAttributes());
+ dispatchWindowAttributesChanged(attrs);
}
@Override
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 ddca51f..5cb307f 100644
--- a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
@@ -347,14 +347,21 @@
final LayoutInflater inflater = LayoutInflater.from(mContext);
final MenuAdapter adapter = new MenuAdapter(menu, inflater, mOverflowOnly);
- // 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.
+ // Apply "force show icon" setting. There are 4 cases:
+ // (1) This is the top level menu. Only add spacing for icons if forced.
+ // (2) This is a submenu. Add spacing if any of the visible menu items has an icon.
+ // (3) This is a top level menu that is not an overflow menu. Add spacing if any of the
+ // visible menu items has an icon.
+ // (4) This is an overflow menu or a top level menu that doesn't have "force" set.
+ // Don't allow spacing.
if (!isShowing() && mForceShowIcon) {
- adapter.setForceShowIcon(mForceShowIcon);
- } else {
- adapter.setForceShowIcon(MenuPopup.shouldPreserveIconSpacing(menu));
+ // Case 1
+ adapter.setForceShowIcon(true);
+ } else if (isShowing() || !isShowing() && !mForceShowIcon && !mOverflowOnly) {
+ // Case 2 or 3
+ adapter.setForceShowIcon(MenuPopup.shouldPreserveIconSpacing(menu));
}
+ // Case 4: Else, don't allow spacing for icons.
final int menuWidth = measureIndividualMenuWidth(adapter, null, mContext, mMenuMaxWidth);
final MenuPopupWindow popupWindow = createPopupWindow();
@@ -734,4 +741,4 @@
return window.getListView();
}
}
-}
\ No newline at end of file
+}
diff --git a/core/java/com/android/internal/view/menu/MenuPopup.java b/core/java/com/android/internal/view/menu/MenuPopup.java
index 16e4156..10bd66f 100644
--- a/core/java/com/android/internal/view/menu/MenuPopup.java
+++ b/core/java/com/android/internal/view/menu/MenuPopup.java
@@ -187,6 +187,11 @@
/**
* Returns whether icon spacing needs to be preserved for the given menu, based on whether any
* of its items contains an icon.
+ *
+ * NOTE: This should only be used for non-overflow-only menus, because this method does not
+ * take into account whether the menu items are being shown as part of the popup or or being
+ * shown as actions in the action bar.
+ *
* @param menu
* @return Whether to preserve icon spacing.
*/
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 21c4d12..b2fc2bb 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -43,4 +43,5 @@
void unregisterStrongAuthTracker(in IStrongAuthTracker tracker);
void requireStrongAuth(int strongAuthReason, int userId);
void systemReady();
+ void userPresent(int userId);
}
diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java
index 78c5e34..e2d8ffc 100644
--- a/core/java/com/android/internal/widget/ImageFloatingTextView.java
+++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java
@@ -16,13 +16,18 @@
package com.android.internal.widget;
+import com.android.internal.R;
+
import android.annotation.Nullable;
import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
import android.text.BoringLayout;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.util.TypedValue;
import android.view.RemotableViewMethod;
import android.widget.RemoteViews;
import android.widget.TextView;
@@ -35,7 +40,8 @@
@RemoteViews.RemoteView
public class ImageFloatingTextView extends TextView {
- private boolean mHasImage;
+ /** Number of lines from the top to indent */
+ private int mIndentLines;
public ImageFloatingTextView(Context context) {
this(context, null);
@@ -69,10 +75,16 @@
.setEllipsizedWidth(ellipsisWidth)
.setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
- // we set the endmargin on the first 2 lines. this works just in our case but that's
- // sufficient for now.
- int endMargin = (int) (getResources().getDisplayMetrics().density * 52);
- int[] margins = mHasImage ? new int[] {endMargin, endMargin, 0} : null;
+ // we set the endmargin on the requested number of lines.
+ int endMargin = getContext().getResources().getDimensionPixelSize(
+ R.dimen.notification_content_picture_margin);
+ int[] margins = null;
+ if (mIndentLines > 0) {
+ margins = new int[mIndentLines + 1];
+ for (int i = 0; i < mIndentLines; i++) {
+ margins[i] = endMargin;
+ }
+ }
if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
builder.setIndents(margins, null);
} else {
@@ -84,8 +96,22 @@
@RemotableViewMethod
public void setHasImage(boolean hasImage) {
- mHasImage = hasImage;
+ mIndentLines = hasImage ? 2 : 0;
// The new layout will be automatically created when the text is
// set again by the notification.
}
+
+ /**
+ * @param lines the number of lines at the top that should be indented by indentEnd
+ * @return whether a change was made
+ */
+ public boolean setNumIndentLines(int lines) {
+ if (mIndentLines != lines) {
+ mIndentLines = lines;
+ // Invalidate layout.
+ setHint(getHint());
+ return true;
+ }
+ return false;
+ }
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index bceeaca..d9b6329 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -172,6 +172,14 @@
}
}
+ public void userPresent(int userId) {
+ try {
+ getLockSettings().userPresent(userId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
public static final class RequestThrottledException extends Exception {
private int mTimeoutMs;
public RequestThrottledException(int timeoutMs) {
diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java
new file mode 100644
index 0000000..dc7b7f5
--- /dev/null
+++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.widget;
+
+import com.android.internal.R;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.RemotableViewMethod;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RemoteViews;
+
+/**
+ * A custom-built layout for the Notification.MessagingStyle.
+ *
+ * Evicts children until they all fit.
+ */
+@RemoteViews.RemoteView
+public class MessagingLinearLayout extends ViewGroup {
+
+ /**
+ * Spacing to be applied between views.
+ */
+ private int mSpacing;
+
+ /**
+ * The maximum height allowed.
+ */
+ private int mMaxHeight;
+
+ private int mIndentLines;
+
+ public MessagingLinearLayout(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+
+ final TypedArray a = context.obtainStyledAttributes(attrs,
+ R.styleable.MessagingLinearLayout, 0,
+ 0);
+
+ final int N = a.getIndexCount();
+ for (int i = 0; i < N; i++) {
+ int attr = a.getIndex(i);
+ switch (attr) {
+ case R.styleable.MessagingLinearLayout_maxHeight:
+ mMaxHeight = a.getDimensionPixelSize(i, 0);
+ break;
+ case R.styleable.MessagingLinearLayout_spacing:
+ mSpacing = a.getDimensionPixelSize(i, 0);
+ break;
+ }
+ }
+
+ if (mMaxHeight <= 0) {
+ throw new IllegalStateException(
+ "MessagingLinearLayout: Must specify positive maxHeight");
+ }
+
+ a.recycle();
+ }
+
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // This is essentially a bottom-up linear layout that only adds children that fit entirely
+ // up to a maximum height.
+
+ switch (MeasureSpec.getMode(heightMeasureSpec)) {
+ case MeasureSpec.AT_MOST:
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ Math.min(mMaxHeight, MeasureSpec.getSize(heightMeasureSpec)),
+ MeasureSpec.AT_MOST);
+ break;
+ case MeasureSpec.UNSPECIFIED:
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ mMaxHeight,
+ MeasureSpec.AT_MOST);
+ break;
+ case MeasureSpec.EXACTLY:
+ break;
+ }
+ final int targetHeight = MeasureSpec.getSize(heightMeasureSpec);
+ final int count = getChildCount();
+
+ for (int i = 0; i < count; ++i) {
+ final View child = getChildAt(i);
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ lp.hide = true;
+ }
+
+ int totalHeight = mPaddingTop + mPaddingBottom;
+ boolean first = true;
+
+ // Starting from the bottom: we measure every view as if it were the only one. If it still
+ // fits, we take it, otherwise we stop there.
+ for (int i = count - 1; i >= 0 && totalHeight < targetHeight; i--) {
+ if (getChildAt(i).getVisibility() == GONE) {
+ continue;
+ }
+ final View child = getChildAt(i);
+ LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
+
+ if (child instanceof ImageFloatingTextView) {
+ // Pretend we need the image padding for all views, we don't know which
+ // one will end up needing to do this (might end up not using all the space,
+ // but calculating this exactly would be more expensive).
+ ((ImageFloatingTextView) child).setNumIndentLines(mIndentLines);
+ }
+
+ measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
+
+ final int childHeight = child.getMeasuredHeight();
+ int newHeight = Math.max(totalHeight, totalHeight + childHeight + lp.topMargin +
+ lp.bottomMargin + (first ? 0 : mSpacing));
+ first = false;
+
+ if (newHeight <= targetHeight) {
+ totalHeight = newHeight;
+ lp.hide = false;
+ } else {
+ break;
+ }
+ }
+
+ // Now that we know which views to take, fix up the indents and see what width we get.
+ int measuredWidth = mPaddingLeft + mPaddingRight;
+ int imageLines = mIndentLines;
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+ if (child.getVisibility() == GONE || lp.hide) {
+ continue;
+ }
+
+ if (child instanceof ImageFloatingTextView) {
+ ImageFloatingTextView textChild = (ImageFloatingTextView) child;
+ if (imageLines == 2 && textChild.getLineCount() > 2) {
+ // HACK: If we need indent for two lines, and they're coming from the same
+ // view, we need extra spacing to compensate for the lack of margins,
+ // so add an extra line of indent.
+ imageLines = 3;
+ }
+ boolean changed = textChild.setNumIndentLines(Math.max(0, imageLines));
+ if (changed) {
+ measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
+ }
+ imageLines -= textChild.getLineCount();
+ }
+
+ measuredWidth = Math.max(measuredWidth,
+ child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin
+ + mPaddingLeft + mPaddingRight);
+ }
+
+
+ setMeasuredDimension(
+ resolveSize(Math.max(getSuggestedMinimumWidth(), measuredWidth),
+ widthMeasureSpec),
+ resolveSize(Math.max(getSuggestedMinimumHeight(), totalHeight),
+ heightMeasureSpec));
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ final int paddingLeft = mPaddingLeft;
+
+ int childTop;
+
+ // Where right end of child should go
+ final int width = right - left;
+ final int childRight = width - mPaddingRight;
+
+ final int layoutDirection = getLayoutDirection();
+ final int count = getChildCount();
+
+ childTop = mPaddingTop;
+
+ boolean first = true;
+
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+ if (child.getVisibility() == GONE || lp.hide) {
+ continue;
+ }
+
+ final int childWidth = child.getMeasuredWidth();
+ final int childHeight = child.getMeasuredHeight();
+
+ int childLeft;
+ if (layoutDirection == LAYOUT_DIRECTION_RTL) {
+ childLeft = childRight - childWidth - lp.rightMargin;
+ } else {
+ childLeft = paddingLeft + lp.leftMargin;
+ }
+
+ if (!first) {
+ childTop += mSpacing;
+ }
+
+ childTop += lp.topMargin;
+ child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
+
+ childTop += childHeight + lp.bottomMargin;
+
+ first = false;
+ }
+ }
+
+ @Override
+ protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ if (lp.hide) {
+ return true;
+ }
+ return super.drawChild(canvas, child, drawingTime);
+ }
+
+ @Override
+ public LayoutParams generateLayoutParams(AttributeSet attrs) {
+ return new LayoutParams(mContext, attrs);
+ }
+
+ @Override
+ protected LayoutParams generateDefaultLayoutParams() {
+ return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+
+ }
+
+ @Override
+ protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
+ LayoutParams copy = new LayoutParams(lp.width, lp.height);
+ if (lp instanceof MarginLayoutParams) {
+ copy.copyMarginsFrom((MarginLayoutParams) lp);
+ }
+ return copy;
+ }
+
+ @RemotableViewMethod
+ /**
+ * Sets how many lines should be indented to avoid a floating image.
+ */
+ public void setNumIndentLines(int numberLines) {
+ mIndentLines = numberLines;
+ }
+
+ public static class LayoutParams extends MarginLayoutParams {
+
+ boolean hide = false;
+
+ public LayoutParams(Context c, AttributeSet attrs) {
+ super(c, attrs);
+ }
+
+ public LayoutParams(int width, int height) {
+ super(width, height);
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index 25b487e..8b9d503 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -17,7 +17,8 @@
package com.android.internal.widget;
-import android.annotation.NonNull;
+import com.android.internal.R;
+
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
@@ -43,7 +44,6 @@
import android.view.animation.AnimationUtils;
import android.widget.AbsListView;
import android.widget.OverScroller;
-import com.android.internal.R;
public class ResolverDrawerLayout extends ViewGroup {
private static final String TAG = "ResolverDrawerLayout";
@@ -90,10 +90,8 @@
private final float mMinFlingVelocity;
private final OverScroller mScroller;
private final VelocityTracker mVelocityTracker;
- private final Drawable mScrollIndicatorDrawable;
- private final Drawable mFakeForeground;
- private View mButtonBar;
+ private Drawable mScrollIndicatorDrawable;
private OnDismissedListener mOnDismissedListener;
private RunOnDismissedListener mRunOnDismissedListener;
@@ -115,8 +113,6 @@
}
};
- private final int[] mTempOffset = new int[2];
-
public ResolverDrawerLayout(Context context) {
this(context, null);
}
@@ -139,7 +135,6 @@
a.recycle();
mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
- mFakeForeground = new ColorDrawable(Color.TRANSPARENT);
mScroller = new OverScroller(context, AnimationUtils.loadInterpolator(context,
android.R.interpolator.decelerate_quint));
@@ -152,13 +147,6 @@
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- mButtonBar = findViewById(R.id.button_bar);
- }
-
public void setSmallCollapsed(boolean smallCollapsed) {
mSmallCollapsed = smallCollapsed;
requestLayout();
@@ -474,8 +462,9 @@
notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
- // Set a fake foreground so that we receive onDrawForeground().
- setForeground(isCollapsed ? mFakeForeground : null);
+ if (mScrollIndicatorDrawable != null) {
+ setWillNotDraw(!isCollapsed);
+ }
}
void dispatchOnDismissed() {
@@ -737,15 +726,7 @@
@Override
public void onDrawForeground(Canvas canvas) {
- if (isCollapsed() && mButtonBar != null) {
- // Draw the scroll indicator directly above the button bar.
- final int height = mScrollIndicatorDrawable.getIntrinsicHeight();
- mButtonBar.getLocationInWindow(mTempOffset);
- final int barTop = mTempOffset[1];
- getLocationInWindow(mTempOffset);
- final int myTop = mTempOffset[1];
- final int top = (barTop - myTop) - height;
- mScrollIndicatorDrawable.setBounds(0, top, getWidth(), top + height);
+ if (mScrollIndicatorDrawable != null) {
mScrollIndicatorDrawable.draw(canvas);
}
@@ -838,6 +819,8 @@
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int width = getWidth();
+ View indicatorHost = null;
+
int ypos = mTopOffset;
int leftEdge = getPaddingLeft();
int rightEdge = width - getPaddingRight();
@@ -846,6 +829,9 @@
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ if (lp.hasNestedScrollIndicator) {
+ indicatorHost = child;
+ }
if (child.getVisibility() == GONE) {
continue;
@@ -866,6 +852,20 @@
ypos = bottom + lp.bottomMargin;
}
+
+ if (mScrollIndicatorDrawable != null) {
+ if (indicatorHost != null) {
+ final int left = indicatorHost.getLeft();
+ final int right = indicatorHost.getRight();
+ final int bottom = indicatorHost.getTop();
+ final int top = bottom - mScrollIndicatorDrawable.getIntrinsicHeight();
+ mScrollIndicatorDrawable.setBounds(left, top, right, bottom);
+ setWillNotDraw(!isCollapsed());
+ } else {
+ mScrollIndicatorDrawable = null;
+ setWillNotDraw(true);
+ }
+ }
}
@Override
@@ -905,6 +905,7 @@
public static class LayoutParams extends MarginLayoutParams {
public boolean alwaysShow;
public boolean ignoreOffset;
+ public boolean hasNestedScrollIndicator;
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
@@ -917,6 +918,9 @@
ignoreOffset = a.getBoolean(
R.styleable.ResolverDrawerLayout_LayoutParams_layout_ignoreOffset,
false);
+ hasNestedScrollIndicator = a.getBoolean(
+ R.styleable.ResolverDrawerLayout_LayoutParams_layout_hasNestedScrollIndicator,
+ false);
a.recycle();
}
@@ -928,6 +932,7 @@
super(source);
this.alwaysShow = source.alwaysShow;
this.ignoreOffset = source.ignoreOffset;
+ this.hasNestedScrollIndicator = source.hasNestedScrollIndicator;
}
public LayoutParams(MarginLayoutParams source) {
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 7ff38fd5..d3dca5d9 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -592,6 +592,7 @@
char jitinitialsizeOptsBuf[sizeof("-Xjitinitialsize:")-1 + PROPERTY_VALUE_MAX];
char jitthresholdOptsBuf[sizeof("-Xjitthreshold:")-1 + PROPERTY_VALUE_MAX];
char useJitProfilesOptsBuf[sizeof("-Xjitsaveprofilinginfo:")-1 + PROPERTY_VALUE_MAX];
+ char jitprithreadweightOptBuf[sizeof("-Xjitprithreadweight:")-1 + PROPERTY_VALUE_MAX];
char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX];
char backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1 + PROPERTY_VALUE_MAX];
char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
@@ -701,6 +702,9 @@
if (strcmp(useJitProfilesOptsBuf, "true") == 0) {
addOption("-Xjitsaveprofilinginfo");
}
+ parseRuntimeOption("dalvik.vm.jitprithreadweight",
+ jitprithreadweightOptBuf,
+ "-Xjitprithreadweight:");
property_get("ro.config.low_ram", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 6e9830e..dc9b656 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -36,7 +36,7 @@
// ----------------------------------------------------------------------------
-#define EGL_QCOM_PROTECTED_CONTENT 0x32E0
+#define EGL_PROTECTED_CONTENT_EXT 0x32C0
namespace android {
@@ -64,19 +64,12 @@
EGLDisplay dpy = eglGetCurrentDisplay();
EGLContext ctx = eglGetCurrentContext();
- if (dpy == EGL_NO_DISPLAY) {
- ALOGI("isProtectedSurface: invalid current EGLDisplay");
- return false;
- }
-
- if (ctx == EGL_NO_CONTEXT) {
- ALOGI("isProtectedSurface: invalid current EGLContext");
+ if (dpy == EGL_NO_DISPLAY || ctx == EGL_NO_CONTEXT) {
return false;
}
EGLint isProtected = EGL_FALSE;
- // TODO: Change the enum value below when an extension is ratified.
- eglQueryContext(dpy, ctx, EGL_QCOM_PROTECTED_CONTENT, &isProtected);
+ eglQueryContext(dpy, ctx, EGL_PROTECTED_CONTENT_EXT, &isProtected);
return isProtected;
}
diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp
index e5c4a2d..0de6549 100644
--- a/core/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -175,7 +175,7 @@
PathParser::ParseResult result;
PathData data;
- PathParser::getPathDataFromString(&data, &result, pathString, stringLength);
+ PathParser::getPathDataFromAsciiString(&data, &result, pathString, stringLength);
if (result.failureOccurred) {
doThrowIAE(env, result.failureMessage.c_str());
}
@@ -343,7 +343,7 @@
}
static const JNINativeMethod gMethods[] = {
- {"nCreateRenderer", "!(J)J", (void*)createTree},
+ {"nCreateTree", "!(J)J", (void*)createTree},
{"nSetRendererViewportSize", "!(JFF)V", (void*)setTreeViewportSize},
{"nSetRootAlpha", "!(JF)Z", (void*)setRootAlpha},
{"nGetRootAlpha", "!(J)F", (void*)getRootAlpha},
diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp
index 91a3b4f..5c961d9 100644
--- a/core/jni/android_hardware_location_ContextHubService.cpp
+++ b/core/jni/android_hardware_location_ContextHubService.cpp
@@ -21,8 +21,8 @@
#include <inttypes.h>
#include <jni.h>
-#include <map>
#include <queue>
+#include <unordered_map>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
@@ -105,7 +105,7 @@
context_hub_info_s hubInfo;
jniInfo_s jniInfo;
std::queue<int> freeIds;
- std::map<int, app_instance_info_s *> appInstances;
+ std::unordered_map<int, app_instance_info_s> appInstances;
};
} // unnamed namespace
@@ -137,7 +137,7 @@
const context_hub_t *info = get_hub_info(hubHandle);
if (info) {
- msg->app = info->os_app_name;
+ msg->app_name = info->os_app_name;
return 0;
} else {
ALOGD("%s: Hub information is null for hubHandle %d", __FUNCTION__, hubHandle);
@@ -154,23 +154,23 @@
}
static int get_hub_id_for_app_instance(int id) {
- if (db.appInstances.find(id) == db.appInstances.end()) {
+ if (!db.appInstances.count(id)) {
ALOGD("%s: Cannot find app for app instance %d", __FUNCTION__, id);
return -1;
}
- int hubHandle = db.appInstances[id]->hubHandle;
+ int hubHandle = db.appInstances[id].hubHandle;
return db.hubInfo.hubs[hubHandle].hub_id;
}
static int set_dest_app(hub_message_t *msg, int id) {
- if (db.appInstances.find(id) == db.appInstances.end()) {
+ if (!db.appInstances.count(id)) {
ALOGD("%s: Cannod find app for app instance %d", __FUNCTION__, id);
return -1;
}
- msg->app = db.appInstances[id]->appInfo.name;
+ msg->app_name = db.appInstances[id].appInfo.app_name;
return 0;
}
@@ -210,76 +210,43 @@
int add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle, JNIEnv *env) {
// Not checking if the apps are indeed distinct
-
- app_instance_info_s *entry;
- void *appName;
- hub_app_name_t *name;
-
- assert(appInfo && appInfo->name && appInfo->name->app_name);
-
- entry = (app_instance_info_s *) malloc(sizeof(app_instance_info_s));
- appName = malloc(appInfo->name->app_name_len);
- name = (hub_app_name_t *) malloc(sizeof(hub_app_name_t));
-
+ app_instance_info_s entry;
int appInstanceHandle = generate_id();
- if (appInstanceHandle < 0 || !appName || !entry || !name) {
- ALOGE("Cannot find resources to add app instance %d, %p, %p",
- appInstanceHandle, appName, entry);
+ assert(appInfo);
- free(appName);
- free(entry);
- free(name);
-
- if (appInstanceHandle >= 0) {
- return_id(appInstanceHandle);
- }
-
+ if (appInstanceHandle < 0) {
+ ALOGE("Cannot find resources to add app instance %d",
+ appInstanceHandle);
return -1;
}
- memcpy(&(entry->appInfo), appInfo, sizeof(entry->appInfo));
- memcpy(appName, appInfo->name->app_name, appInfo->name->app_name_len);
- name->app_name = appName;
- name->app_name_len = appInfo->name->app_name_len;
- entry->appInfo.name = name;
- entry->truncName = 0;
- memcpy(&(entry->truncName), name->app_name,
- sizeof(entry->truncName) < name->app_name_len ?
- sizeof(entry->truncName) : name->app_name_len);
-
- // Not checking for sanity of hubId
- entry->hubHandle = hubHandle;
- entry->instanceId = appInstanceHandle;
+ entry.appInfo = *appInfo;
+ entry.instanceId = appInstanceHandle;
+ entry.truncName = appInfo->app_name.id;
+ entry.hubHandle = hubHandle;
db.appInstances[appInstanceHandle] = entry;
// Finally - let the service know of this app instance
env->CallIntMethod(db.jniInfo.jContextHubService,
db.jniInfo.contextHubServiceAddAppInstance,
- hubHandle, entry->instanceId, entry->truncName,
- entry->appInfo.version);
+ hubHandle, entry.instanceId, entry.truncName,
+ entry.appInfo.version);
ALOGW("Added App 0x%" PRIx64 " on hub Handle %" PRId32
- " as appInstance %d, original name_length %" PRId32, entry->truncName,
- entry->hubHandle, appInstanceHandle, name->app_name_len);
+ " as appInstance %d", entry.truncName,
+ entry.hubHandle, appInstanceHandle);
return appInstanceHandle;
}
int delete_app_instance(int id) {
- if (db.appInstances.find(id) == db.appInstances.end()) {
+ if (!db.appInstances.count(id)) {
return -1;
}
return_id(id);
-
- if (db.appInstances[id]) {
- // Losing the const cast below. This is intentional.
- free((void *)db.appInstances[id]->appInfo.name->app_name);
- free((void *)db.appInstances[id]->appInfo.name);
- free(db.appInstances[id]);
- db.appInstances.erase(id);
- }
+ db.appInstances.erase(id);
return 0;
}
@@ -353,27 +320,20 @@
}
int handle_query_apps_response(char *msg, int msgLen, uint32_t hubHandle) {
- int i;
JNIEnv *env;
if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
return -1;
}
int numApps = msgLen/sizeof(hub_app_info);
- hub_app_info *info = (hub_app_info *)malloc(msgLen); // handle possible alignment
+ hub_app_info info;
+ hub_app_info *unalignedInfoAddr = (hub_app_info*)msg;
- if (!info) {
- return -1;
+ for (int i = 0; i < numApps; i++, unalignedInfoAddr++) {
+ memcpy(&info, unalignedInfoAddr, sizeof(info));
+ add_app_instance(&info, hubHandle, env);
}
- memcpy(info, msg, msgLen);
- for (i = 0; i < numApps; i++) {
- add_app_instance(info, hubHandle, env);
- info++;
- }
-
- free(info);
-
return 0;
}
@@ -410,10 +370,6 @@
retVal = 0;
break;
- case CONTEXT_HUB_LOAD_OS:
- retVal = 0;
- break;
-
default:
retVal = -1;
break;
diff --git a/core/jni/android_util_PathParser.cpp b/core/jni/android_util_PathParser.cpp
index 0c867f1..53669a8 100644
--- a/core/jni/android_util_PathParser.cpp
+++ b/core/jni/android_util_PathParser.cpp
@@ -34,7 +34,7 @@
SkPath* skPath = reinterpret_cast<SkPath*>(skPathHandle);
PathParser::ParseResult result;
- PathParser::parseStringForSkPath(skPath, &result, pathString, strLength);
+ PathParser::parseAsciiStringForSkPath(skPath, &result, pathString, strLength);
env->ReleaseStringUTFChars(inputPathStr, pathString);
if (result.failureOccurred) {
doThrowIAE(env, result.failureMessage.c_str());
@@ -56,7 +56,7 @@
const char* pathString = env->GetStringUTFChars(inputStr, NULL);
PathData* pathData = new PathData();
PathParser::ParseResult result;
- PathParser::getPathDataFromString(pathData, &result, pathString, strLength);
+ PathParser::getPathDataFromAsciiString(pathData, &result, pathString, strLength);
env->ReleaseStringUTFChars(inputStr, pathString);
if (!result.failureOccurred) {
return reinterpret_cast<jlong>(pathData);
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index ef45c87..68c818e 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -669,6 +669,14 @@
proxy->setContentDrawBounds(left, top, right, bottom);
}
+static jboolean android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env,
+ jobject clazz, jobject jsurface, jobject jbitmap) {
+ SkBitmap bitmap;
+ GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
+ sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
+ return RenderProxy::copySurfaceInto(surface, &bitmap);
+}
+
// ----------------------------------------------------------------------------
// FrameMetricsObserver
// ----------------------------------------------------------------------------
@@ -775,6 +783,8 @@
{ "nRemoveFrameMetricsObserver",
"(JJ)V",
(void*)android_view_ThreadedRenderer_removeFrameMetricsObserver },
+ { "nCopySurfaceInto", "(Landroid/view/Surface;Landroid/graphics/Bitmap;)Z",
+ (void*)android_view_ThreadedRenderer_copySurfaceInto },
};
int register_android_view_ThreadedRenderer(JNIEnv* env) {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9a2e39c7..1ed93cc 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -420,6 +420,7 @@
<protected-broadcast android:name="android.os.storage.action.VOLUME_STATE_CHANGED" />
<protected-broadcast android:name="android.os.storage.action.DISK_SCANNED" />
<protected-broadcast android:name="com.android.server.action.UPDATE_TWILIGHT_STATE" />
+ <protected-broadcast android:name="com.android.server.action.RESET_TWILIGHT_AUTO" />
<protected-broadcast android:name="com.android.server.device_idle.STEP_IDLE_STATE" />
<protected-broadcast android:name="com.android.server.device_idle.STEP_LIGHT_IDLE_STATE" />
<protected-broadcast android:name="com.android.server.Wifi.action.TOGGLE_PNO" />
@@ -3007,6 +3008,12 @@
<permission android:name="android.permission.UPDATE_LOCK_TASK_PACKAGES"
android:protectionLevel="signature|setup" />
+ <!-- @SystemApi Allows an application to replace the app name displayed alongside notifications
+ in the N-release and later.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"
+ android:protectionLevel="signature|privileged" />
+
<application android:process="system"
android:persistent="true"
android:hasCode="false"
diff --git a/core/res/res/drawable-hdpi/ic_launcher_android.png b/core/res/res/drawable-hdpi/ic_launcher_android.png
index cce5187..2e9b196 100644
--- a/core/res/res/drawable-hdpi/ic_launcher_android.png
+++ b/core/res/res/drawable-hdpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_launcher_android.png b/core/res/res/drawable-ldpi/ic_launcher_android.png
index 628a8de..245e4b7 100644
--- a/core/res/res/drawable-ldpi/ic_launcher_android.png
+++ b/core/res/res/drawable-ldpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_launcher_android.png b/core/res/res/drawable-mdpi/ic_launcher_android.png
index 6a97d5b..baacd4f 100644
--- a/core/res/res/drawable-mdpi/ic_launcher_android.png
+++ b/core/res/res/drawable-mdpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_launcher_android.png b/core/res/res/drawable-xhdpi/ic_launcher_android.png
index b1097d6..00b69a5 100644
--- a/core/res/res/drawable-xhdpi/ic_launcher_android.png
+++ b/core/res/res/drawable-xhdpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_launcher_android.png b/core/res/res/drawable-xxhdpi/ic_launcher_android.png
new file mode 100644
index 0000000..ad05cd5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_launcher_android.png
Binary files differ
diff --git a/core/res/res/drawable/ic_input_extract_action_done.xml b/core/res/res/drawable/ic_input_extract_action_done.xml
index a0ebf92..f6e872e 100644
--- a/core/res/res/drawable/ic_input_extract_action_done.xml
+++ b/core/res/res/drawable/ic_input_extract_action_done.xml
@@ -1,3 +1,18 @@
+<!--
+ 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 android:height="24dp" android:viewportHeight="48.0"
android:viewportWidth="48.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFF" android:pathData="M18,32.34L9.66,24l-2.83,2.83L18,38l24,-24 -2.83,-2.83z"/>
diff --git a/core/res/res/drawable/ic_input_extract_action_go.xml b/core/res/res/drawable/ic_input_extract_action_go.xml
index c24f5a0..edbc826 100644
--- a/core/res/res/drawable/ic_input_extract_action_go.xml
+++ b/core/res/res/drawable/ic_input_extract_action_go.xml
@@ -1,3 +1,18 @@
+<!--
+ 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 android:height="24dp" android:viewportHeight="48.0"
android:viewportWidth="48.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFF" android:pathData="M6,22h28.34l-7.17,-7.17L30,12l12,12 -12,12 -2.83,-2.83L34.34,26H6z"/>
diff --git a/core/res/res/drawable/ic_input_extract_action_next.xml b/core/res/res/drawable/ic_input_extract_action_next.xml
index fa0b178..ffef346 100644
--- a/core/res/res/drawable/ic_input_extract_action_next.xml
+++ b/core/res/res/drawable/ic_input_extract_action_next.xml
@@ -1,3 +1,18 @@
+<!--
+ 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 android:height="24dp" android:viewportHeight="48.0"
android:viewportWidth="48.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFF" android:pathData="M23.17,14.83L30.34,22H2v4h28.34l-7.17,7.17L26,36l12,-12 -12,-12 -2.83,2.83zM40,12v24h4V12h-4z"/>
diff --git a/core/res/res/drawable/ic_input_extract_action_previous.xml b/core/res/res/drawable/ic_input_extract_action_previous.xml
index 5e1823c..89777b0 100644
--- a/core/res/res/drawable/ic_input_extract_action_previous.xml
+++ b/core/res/res/drawable/ic_input_extract_action_previous.xml
@@ -1,3 +1,18 @@
+<!--
+ 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 android:height="24dp" android:viewportHeight="48.0"
android:viewportWidth="48.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFF" android:pathData="M22.83,14.83L15.66,22H44v4H15.66l7.17,7.17L20,36 8,24l12,-12 2.83,2.83zM6,12v24H2V12h4z"/>
diff --git a/core/res/res/drawable/ic_input_extract_action_return.xml b/core/res/res/drawable/ic_input_extract_action_return.xml
index c46a4a2..cb2de5a 100644
--- a/core/res/res/drawable/ic_input_extract_action_return.xml
+++ b/core/res/res/drawable/ic_input_extract_action_return.xml
@@ -1,3 +1,18 @@
+<!--
+ 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 android:height="24dp" android:viewportHeight="48.0"
android:viewportWidth="48.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFF" android:pathData="M38,14v8H11.66l7.17,-7.17L16,12 4,24l12,12 2.83,-2.83L11.66,26H42V14z"/>
diff --git a/core/res/res/drawable/ic_input_extract_action_search.xml b/core/res/res/drawable/ic_input_extract_action_search.xml
index fd1dcea..dcbcdbf 100644
--- a/core/res/res/drawable/ic_input_extract_action_search.xml
+++ b/core/res/res/drawable/ic_input_extract_action_search.xml
@@ -1,3 +1,18 @@
+<!--
+ 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 android:height="24dp" android:viewportHeight="48.0"
android:viewportWidth="48.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFF" android:pathData="M31,28h-1.59l-0.55,-0.55C30.82,25.18 32,22.23 32,19c0,-7.18 -5.82,-13 -13,-13S6,11.82 6,19s5.82,13 13,13c3.23,0 6.18,-1.18 8.45,-3.13l0.55,0.55L28,31l10,9.98L40.98,38 31,28zM19,28c-4.97,0 -9,-4.03 -9,-9s4.03,-9 9,-9 9,4.03 9,9 -4.03,9 -9,9z"/>
diff --git a/core/res/res/drawable/ic_input_extract_action_send.xml b/core/res/res/drawable/ic_input_extract_action_send.xml
index 0f3754b..6494bee 100644
--- a/core/res/res/drawable/ic_input_extract_action_send.xml
+++ b/core/res/res/drawable/ic_input_extract_action_send.xml
@@ -1,3 +1,18 @@
+<!--
+ 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"
diff --git a/core/res/res/drawable/input_extract_action_bg_material_dark.xml b/core/res/res/drawable/input_extract_action_bg_material_dark.xml
index 2457bb9..9c6a6c3 100644
--- a/core/res/res/drawable/input_extract_action_bg_material_dark.xml
+++ b/core/res/res/drawable/input_extract_action_bg_material_dark.xml
@@ -1,4 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/input_extract_action_bg_pressed_material_dark"
android:state_pressed="true"/>
diff --git a/core/res/res/drawable/input_extract_action_bg_normal_material_dark.xml b/core/res/res/drawable/input_extract_action_bg_normal_material_dark.xml
index 9e36253..8449978 100644
--- a/core/res/res/drawable/input_extract_action_bg_normal_material_dark.xml
+++ b/core/res/res/drawable/input_extract_action_bg_normal_material_dark.xml
@@ -1,4 +1,19 @@
<?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.
+-->
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="@color/material_deep_teal_200"/>
</shape>
diff --git a/core/res/res/drawable/input_extract_action_bg_pressed_material_dark.xml b/core/res/res/drawable/input_extract_action_bg_pressed_material_dark.xml
index 2328ce3..adade104 100644
--- a/core/res/res/drawable/input_extract_action_bg_pressed_material_dark.xml
+++ b/core/res/res/drawable/input_extract_action_bg_pressed_material_dark.xml
@@ -1,4 +1,19 @@
<?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.
+-->
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="@color/material_deep_teal_100"/>
</shape>
diff --git a/core/res/res/layout-watch/input_method_extract_view.xml b/core/res/res/layout-watch/input_method_extract_view.xml
index cd921f1..e3cd2ce 100644
--- a/core/res/res/layout-watch/input_method_extract_view.xml
+++ b/core/res/res/layout-watch/input_method_extract_view.xml
@@ -1,5 +1,19 @@
<?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.
+-->
<android.inputmethodservice.CompactExtractEditLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
diff --git a/core/res/res/layout/notification_template_material_messaging.xml b/core/res/res/layout/notification_template_material_messaging.xml
new file mode 100644
index 0000000..7d718e0
--- /dev/null
+++ b/core/res/res/layout/notification_template_material_messaging.xml
@@ -0,0 +1,80 @@
+<?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
+ -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/status_bar_latest_event_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:tag="messaging"
+ >
+ <include layout="@layout/notification_template_header" />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="top"
+ android:layout_marginTop="@dimen/notification_content_margin_top"
+ android:clipToPadding="false"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/notification_main_column"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:paddingStart="@dimen/notification_content_margin_start"
+ android:paddingEnd="@dimen/notification_content_margin_end"
+ android:minHeight="@dimen/notification_min_content_height"
+ android:clipToPadding="false"
+ android:orientation="vertical"
+ >
+ <include layout="@layout/notification_template_part_line1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <com.android.internal.widget.MessagingLinearLayout
+ android:id="@+id/notification_messaging"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="@dimen/notification_content_margin_bottom"
+ android:spacing="@dimen/notification_messaging_spacing"
+ android:maxHeight="212dp">
+ <com.android.internal.widget.ImageFloatingTextView android:id="@+id/inbox_text0"
+ style="@style/Widget.Material.Notification.MessagingText"
+ />
+ <com.android.internal.widget.ImageFloatingTextView android:id="@+id/inbox_text1"
+ style="@style/Widget.Material.Notification.MessagingText"
+ />
+ <com.android.internal.widget.ImageFloatingTextView android:id="@+id/inbox_text2"
+ style="@style/Widget.Material.Notification.MessagingText"
+ />
+ <com.android.internal.widget.ImageFloatingTextView android:id="@+id/inbox_text3"
+ style="@style/Widget.Material.Notification.MessagingText"
+ />
+ <com.android.internal.widget.ImageFloatingTextView android:id="@+id/inbox_text4"
+ style="@style/Widget.Material.Notification.MessagingText"
+ />
+ <com.android.internal.widget.ImageFloatingTextView android:id="@+id/inbox_text5"
+ style="@style/Widget.Material.Notification.MessagingText"
+ />
+ <com.android.internal.widget.ImageFloatingTextView android:id="@+id/inbox_text6"
+ style="@style/Widget.Material.Notification.MessagingText"
+ />
+ </com.android.internal.widget.MessagingLinearLayout>
+ </LinearLayout>
+ <include layout="@layout/notification_material_action_list" />
+ </LinearLayout>
+ <include layout="@layout/notification_template_right_icon" />
+</FrameLayout>
diff --git a/core/res/res/layout/notification_template_right_icon.xml b/core/res/res/layout/notification_template_right_icon.xml
index 15ccc67..65a5015 100644
--- a/core/res/res/layout/notification_template_right_icon.xml
+++ b/core/res/res/layout/notification_template_right_icon.xml
@@ -18,7 +18,7 @@
<ImageView android:id="@+id/right_icon" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="40dp"
android:layout_height="40dp"
- android:layout_marginEnd="16dp"
+ android:layout_marginEnd="@dimen/notification_content_margin_end"
android:layout_marginTop="36dp"
android:layout_gravity="top|end"
android:scaleType="centerCrop"
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index fe43e1c..ae94503 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -75,15 +75,16 @@
android:scrollIndicators="top|bottom"
android:divider="@null" />
- <TextView
- android:id="@+id/empty"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alwaysShow="true"
- android:text="@string/noApplications"
- android:padding="32dp"
- android:gravity="center"
- android:visibility="gone" />
+ <TextView android:id="@+id/empty"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@color/white"
+ android:elevation="8dp"
+ android:layout_alwaysShow="true"
+ android:text="@string/noApplications"
+ android:padding="32dp"
+ android:gravity="center"
+ android:visibility="gone" />
<LinearLayout
android:id="@+id/button_bar"
@@ -93,6 +94,7 @@
android:layout_height="wrap_content"
android:layout_ignoreOffset="true"
android:layout_alwaysShow="true"
+ android:layout_hasNestedScrollIndicator="true"
android:gravity="end|center_vertical"
android:orientation="horizontal"
android:layoutDirection="locale"
diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml
index ed7ef5e..02dc2ed 100644
--- a/core/res/res/layout/resolver_list_with_default.xml
+++ b/core/res/res/layout/resolver_list_with_default.xml
@@ -153,7 +153,6 @@
android:background="@color/white"
android:elevation="8dp"
android:nestedScrollingEnabled="true"
- android:divider="@null"
- android:scrollIndicators="top|bottom" />
+ android:divider="@null" />
</com.android.internal.widget.ResolverDrawerLayout>
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-mcc310-mnc160/strings.xml b/core/res/res/values-mcc310-mnc160/strings.xml
deleted file mode 100644
index 526d08b..0000000
--- a/core/res/res/values-mcc310-mnc160/strings.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?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 my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- WFC Operator Error Codes -->
- <string-array name="wfcOperatorErrorCodes" translatable="false">
- <item>REG09</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as alerts -->
- <string-array name="wfcOperatorErrorAlertMessages">
- <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as notifications -->
- <string-array name="wfcOperatorErrorNotificationMessages">
- <item>Register with your carrier</item>
- </string-array>
- <!-- Template for showing cellular network operator name while WFC is active -->
- <string name="wfcSpnFormat">%s Wi-Fi Calling</string>
-</resources>
diff --git a/core/res/res/values-mcc310-mnc200/strings.xml b/core/res/res/values-mcc310-mnc200/strings.xml
deleted file mode 100644
index 526d08b..0000000
--- a/core/res/res/values-mcc310-mnc200/strings.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?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 my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- WFC Operator Error Codes -->
- <string-array name="wfcOperatorErrorCodes" translatable="false">
- <item>REG09</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as alerts -->
- <string-array name="wfcOperatorErrorAlertMessages">
- <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as notifications -->
- <string-array name="wfcOperatorErrorNotificationMessages">
- <item>Register with your carrier</item>
- </string-array>
- <!-- Template for showing cellular network operator name while WFC is active -->
- <string name="wfcSpnFormat">%s Wi-Fi Calling</string>
-</resources>
diff --git a/core/res/res/values-mcc310-mnc210/strings.xml b/core/res/res/values-mcc310-mnc210/strings.xml
deleted file mode 100644
index 526d08b..0000000
--- a/core/res/res/values-mcc310-mnc210/strings.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?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 my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- WFC Operator Error Codes -->
- <string-array name="wfcOperatorErrorCodes" translatable="false">
- <item>REG09</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as alerts -->
- <string-array name="wfcOperatorErrorAlertMessages">
- <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as notifications -->
- <string-array name="wfcOperatorErrorNotificationMessages">
- <item>Register with your carrier</item>
- </string-array>
- <!-- Template for showing cellular network operator name while WFC is active -->
- <string name="wfcSpnFormat">%s Wi-Fi Calling</string>
-</resources>
diff --git a/core/res/res/values-mcc310-mnc220/strings.xml b/core/res/res/values-mcc310-mnc220/strings.xml
deleted file mode 100644
index 526d08b..0000000
--- a/core/res/res/values-mcc310-mnc220/strings.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?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 my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- WFC Operator Error Codes -->
- <string-array name="wfcOperatorErrorCodes" translatable="false">
- <item>REG09</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as alerts -->
- <string-array name="wfcOperatorErrorAlertMessages">
- <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as notifications -->
- <string-array name="wfcOperatorErrorNotificationMessages">
- <item>Register with your carrier</item>
- </string-array>
- <!-- Template for showing cellular network operator name while WFC is active -->
- <string name="wfcSpnFormat">%s Wi-Fi Calling</string>
-</resources>
diff --git a/core/res/res/values-mcc310-mnc230/strings.xml b/core/res/res/values-mcc310-mnc230/strings.xml
deleted file mode 100644
index 526d08b..0000000
--- a/core/res/res/values-mcc310-mnc230/strings.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?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 my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- WFC Operator Error Codes -->
- <string-array name="wfcOperatorErrorCodes" translatable="false">
- <item>REG09</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as alerts -->
- <string-array name="wfcOperatorErrorAlertMessages">
- <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as notifications -->
- <string-array name="wfcOperatorErrorNotificationMessages">
- <item>Register with your carrier</item>
- </string-array>
- <!-- Template for showing cellular network operator name while WFC is active -->
- <string name="wfcSpnFormat">%s Wi-Fi Calling</string>
-</resources>
diff --git a/core/res/res/values-mcc310-mnc240/strings.xml b/core/res/res/values-mcc310-mnc240/strings.xml
deleted file mode 100644
index 526d08b..0000000
--- a/core/res/res/values-mcc310-mnc240/strings.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?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 my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- WFC Operator Error Codes -->
- <string-array name="wfcOperatorErrorCodes" translatable="false">
- <item>REG09</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as alerts -->
- <string-array name="wfcOperatorErrorAlertMessages">
- <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as notifications -->
- <string-array name="wfcOperatorErrorNotificationMessages">
- <item>Register with your carrier</item>
- </string-array>
- <!-- Template for showing cellular network operator name while WFC is active -->
- <string name="wfcSpnFormat">%s Wi-Fi Calling</string>
-</resources>
diff --git a/core/res/res/values-mcc310-mnc250/strings.xml b/core/res/res/values-mcc310-mnc250/strings.xml
deleted file mode 100644
index 526d08b..0000000
--- a/core/res/res/values-mcc310-mnc250/strings.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?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 my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- WFC Operator Error Codes -->
- <string-array name="wfcOperatorErrorCodes" translatable="false">
- <item>REG09</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as alerts -->
- <string-array name="wfcOperatorErrorAlertMessages">
- <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as notifications -->
- <string-array name="wfcOperatorErrorNotificationMessages">
- <item>Register with your carrier</item>
- </string-array>
- <!-- Template for showing cellular network operator name while WFC is active -->
- <string name="wfcSpnFormat">%s Wi-Fi Calling</string>
-</resources>
diff --git a/core/res/res/values-mcc310-mnc260/strings.xml b/core/res/res/values-mcc310-mnc260/strings.xml
deleted file mode 100644
index dc79877..0000000
--- a/core/res/res/values-mcc310-mnc260/strings.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2015, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- WFC Operator Error Codes -->
- <string-array name="wfcOperatorErrorCodes" translatable="false">
- <item>REG09</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as alerts -->
- <string-array name="wfcOperatorErrorAlertMessages">
- <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as notifications -->
- <string-array name="wfcOperatorErrorNotificationMessages">
- <item>Register with your carrier</item>
- </string-array>
- <!-- Template for showing cellular network operator name while WFC is active -->
- <string name="wfcSpnFormat">%s Wi-Fi Calling</string>
-</resources>
diff --git a/core/res/res/values-mcc310-mnc270/strings.xml b/core/res/res/values-mcc310-mnc270/strings.xml
deleted file mode 100644
index 526d08b..0000000
--- a/core/res/res/values-mcc310-mnc270/strings.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?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 my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- WFC Operator Error Codes -->
- <string-array name="wfcOperatorErrorCodes" translatable="false">
- <item>REG09</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as alerts -->
- <string-array name="wfcOperatorErrorAlertMessages">
- <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as notifications -->
- <string-array name="wfcOperatorErrorNotificationMessages">
- <item>Register with your carrier</item>
- </string-array>
- <!-- Template for showing cellular network operator name while WFC is active -->
- <string name="wfcSpnFormat">%s Wi-Fi Calling</string>
-</resources>
diff --git a/core/res/res/values-mcc310-mnc310/strings.xml b/core/res/res/values-mcc310-mnc310/strings.xml
deleted file mode 100644
index 526d08b..0000000
--- a/core/res/res/values-mcc310-mnc310/strings.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?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 my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- WFC Operator Error Codes -->
- <string-array name="wfcOperatorErrorCodes" translatable="false">
- <item>REG09</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as alerts -->
- <string-array name="wfcOperatorErrorAlertMessages">
- <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as notifications -->
- <string-array name="wfcOperatorErrorNotificationMessages">
- <item>Register with your carrier</item>
- </string-array>
- <!-- Template for showing cellular network operator name while WFC is active -->
- <string name="wfcSpnFormat">%s Wi-Fi Calling</string>
-</resources>
diff --git a/core/res/res/values-mcc310-mnc490/strings.xml b/core/res/res/values-mcc310-mnc490/strings.xml
deleted file mode 100644
index 526d08b..0000000
--- a/core/res/res/values-mcc310-mnc490/strings.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?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 my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- WFC Operator Error Codes -->
- <string-array name="wfcOperatorErrorCodes" translatable="false">
- <item>REG09</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as alerts -->
- <string-array name="wfcOperatorErrorAlertMessages">
- <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as notifications -->
- <string-array name="wfcOperatorErrorNotificationMessages">
- <item>Register with your carrier</item>
- </string-array>
- <!-- Template for showing cellular network operator name while WFC is active -->
- <string name="wfcSpnFormat">%s Wi-Fi Calling</string>
-</resources>
diff --git a/core/res/res/values-mcc310-mnc660/strings.xml b/core/res/res/values-mcc310-mnc660/strings.xml
deleted file mode 100644
index 526d08b..0000000
--- a/core/res/res/values-mcc310-mnc660/strings.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?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 my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- WFC Operator Error Codes -->
- <string-array name="wfcOperatorErrorCodes" translatable="false">
- <item>REG09</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as alerts -->
- <string-array name="wfcOperatorErrorAlertMessages">
- <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as notifications -->
- <string-array name="wfcOperatorErrorNotificationMessages">
- <item>Register with your carrier</item>
- </string-array>
- <!-- Template for showing cellular network operator name while WFC is active -->
- <string name="wfcSpnFormat">%s Wi-Fi Calling</string>
-</resources>
diff --git a/core/res/res/values-mcc310-mnc800/strings.xml b/core/res/res/values-mcc310-mnc800/strings.xml
deleted file mode 100644
index 526d08b..0000000
--- a/core/res/res/values-mcc310-mnc800/strings.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?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 my obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- WFC Operator Error Codes -->
- <string-array name="wfcOperatorErrorCodes" translatable="false">
- <item>REG09</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as alerts -->
- <string-array name="wfcOperatorErrorAlertMessages">
- <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
- </string-array>
- <!-- WFC Operator Error Messages showed as notifications -->
- <string-array name="wfcOperatorErrorNotificationMessages">
- <item>Register with your carrier</item>
- </string-array>
- <!-- Template for showing cellular network operator name while WFC is active -->
- <string name="wfcSpnFormat">%s Wi-Fi Calling</string>
-</resources>
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..4e88bb4 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-round-watch/dimens.xml b/core/res/res/values-round-watch/dimens.xml
index f4b250c..a12f499 100644
--- a/core/res/res/values-round-watch/dimens.xml
+++ b/core/res/res/values-round-watch/dimens.xml
@@ -1,21 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-/* //device/apps/common/assets/res/any/dimens.xml
-**
-** 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.
-*/
+ 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>
<!-- each of these are relative to the display size -->
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 b2dba7e..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-w170dp-notround-watch/dimens.xml b/core/res/res/values-w170dp-notround-watch/dimens.xml
index 9f30ac1..c91cbc1 100644
--- a/core/res/res/values-w170dp-notround-watch/dimens.xml
+++ b/core/res/res/values-w170dp-notround-watch/dimens.xml
@@ -1,21 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-/* //device/apps/common/assets/res/any/dimens.xml
-**
-** 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.
-*/
+ 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>
<!-- each of these are relative to the display size -->
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-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-watch/dimens.xml b/core/res/res/values-watch/dimens.xml
index f79a0a5..f103aa9 100644
--- a/core/res/res/values-watch/dimens.xml
+++ b/core/res/res/values-watch/dimens.xml
@@ -1,21 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-/* //device/apps/common/assets/res/any/dimens.xml
-**
-** 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.
-*/
+ 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>
<!-- each of these are relative to the display size -->
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/attrs.xml b/core/res/res/values/attrs.xml
index 0ed1f13..85e0b88 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8129,10 +8129,16 @@
<attr name="maxCollapsedHeightSmall" format="dimension" />
</declare-styleable>
+ <declare-styleable name="MessagingLinearLayout">
+ <attr name="maxHeight" />
+ <attr name="spacing" />
+ </declare-styleable>
+
<declare-styleable name="ResolverDrawerLayout_LayoutParams">
<attr name="layout_alwaysShow" format="boolean" />
<attr name="layout_ignoreOffset" format="boolean" />
<attr name="layout_gravity" />
+ <attr name="layout_hasNestedScrollIndicator" format="boolean" />
</declare-styleable>
<!-- @hide -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5cbe672..aada05d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -420,9 +420,6 @@
<!-- Boolean indicating we re-try re-associating once upon disconnection and RSSI is high failure -->
<bool translatable="true" name="config_wifi_enable_disconnection_debounce">true</bool>
- <!-- Boolean indicating autojoin will prefer 5GHz and choose 5GHz BSSIDs -->
- <bool translatable="true" name="config_wifi_enable_5GHz_preference">true</bool>
-
<!-- Boolean indicating whether or not to revert to default country code when cellular
radio is unable to find any MCC information to infer wifi country code from -->
<bool translatable="false" name="config_wifi_revert_country_code_on_cellular_loss">false</bool>
@@ -439,8 +436,6 @@
<!-- Integer specifying the basic autojoin parameters -->
<integer translatable="false" name="config_wifi_framework_5GHz_preference_boost_threshold">-65</integer>
<integer translatable="false" name="config_wifi_framework_5GHz_preference_boost_factor">40</integer>
- <integer translatable="false" name="config_wifi_framework_current_association_hysteresis_high">16</integer>
- <integer translatable="false" name="config_wifi_framework_current_association_hysteresis_low">10</integer>
<integer translatable="false" name="config_wifi_framework_5GHz_preference_penalty_threshold">-75</integer>
<integer translatable="false" name="config_wifi_framework_RSSI_SCORE_OFFSET">85</integer>
<integer translatable="false" name="config_wifi_framework_RSSI_SCORE_SLOPE">4</integer>
@@ -495,15 +490,9 @@
<!-- Integer indicating disconnect mode short scan interval in milliseconds -->
<integer translatable="false" name="config_wifi_disconnected_short_scan_interval">15000</integer>
- <!-- Integer indicating disconnect mode long scan interval in milliseconds -->
- <integer translatable="false" name="config_wifi_disconnected_long_scan_interval">120000</integer>
-
<!-- Integer indicating associated partial scan short interval in milliseconds -->
<integer translatable="false" name="config_wifi_associated_short_scan_interval">20000</integer>
- <!-- Integer indicating associated partial scan long interval in milliseconds -->
- <integer translatable="false" name="config_wifi_associated_long_scan_interval">180000</integer>
-
<!-- Integer indicating associated full scan backoff, representing a fraction: xx/8 -->
<integer translatable="false" name="config_wifi_framework_associated_full_scan_backoff">12</integer>
@@ -516,18 +505,6 @@
<!-- Integer indicating associated full scan max num active channels -->
<integer translatable="false" name="config_wifi_framework_associated_partial_scan_max_num_active_channels">6</integer>
- <!-- Integer indicating associated full scan max num passive channels -->
- <integer translatable="false" name="config_wifi_framework_associated_partial_scan_max_num_passive_channels">3</integer>
-
- <!-- Integer indicating number of association errors leading to blacklisting of the network -->
- <integer translatable="false" name="config_wifi_framework_max_connection_errors_to_blacklist">4</integer>
-
- <!-- Integer indicating number of authentication errors leading to blacklisting of the network -->
- <integer translatable="false" name="config_wifi_framework_max_auth_errors_to_blacklist">4</integer>
-
- <!-- Integer indicating minimum blacklisting delay of a wofo configuration due to connectin or auth errors -->
- <integer translatable="false" name="config_wifi_framework_network_black_list_min_time_milli">120000</integer>
-
<!-- Integer indicating RSSI boost given to current network -->
<integer translatable="false" name="config_wifi_framework_current_network_boost">16</integer>
@@ -543,12 +520,6 @@
<!-- Wifi driver supports batched scan -->
<bool translatable="false" name="config_wifi_batched_scan_supported">false</bool>
- <!-- Wifi HAL supported PNO -->
- <bool translatable="false" name="config_wifi_hal_pno_enable">false</bool>
-
- <!-- Wifi SSID white list (can't be enabled if config_wifi_hal_pno_enable is not) -->
- <bool translatable="false" name="config_wifi_ssid_white_list_enable">true</bool>
-
<!-- Idle Receive current for wifi radio. 0 by default-->
<integer translatable="false" name="config_wifi_idle_receive_cur_ma">0</integer>
@@ -2421,10 +2392,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 9aec1bb..8200df8 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -181,6 +181,9 @@
<!-- The margin of the content to an image-->
<dimen name="notification_content_image_margin_end">8dp</dimen>
+ <!-- The spacing between messages in Notification.MessagingStyle -->
+ <dimen name="notification_messaging_spacing">6dp</dimen>
+
<!-- Preferred width of the search view. -->
<dimen name="search_view_preferred_width">320dip</dimen>
@@ -455,4 +458,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/public.xml b/core/res/res/values/public.xml
index 6ff7139..80b3a64 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2713,11 +2713,14 @@
<public type="attr" name="forceHasOverlappingRendering" />
<public type="attr" name="contentInsetStartWithNavigation" />
<public type="attr" name="contentInsetEndWithActions" />
+ <public type="attr" name="numberPickerStyle" />
<public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
<public type="style" name="Widget.Material.SeekBar.Discrete" />
<public type="style" name="Widget.Material.CompoundButton.Switch" />
<public type="style" name="Widget.Material.Light.CompoundButton.Switch" />
+ <public type="style" name="Widget.Material.NumberPicker" />
+ <public type="style" name="Widget.Material.Light.NumberPicker" />
<public type="id" name="accessibilityActionSetProgress" />
<public type="id" name="icon_frame" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 96731cf..836efde 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -245,16 +245,19 @@
<!-- Displayed when WFC registration fails -->
<string name="wfcRegErrorTitle">Wi-Fi Calling</string>
- <!-- WFC Operator Error Codes -->
- <string-array name="wfcOperatorErrorCodes" translatable="false" />
<!-- WFC Operator Error Messages showed as alerts -->
- <string-array name="wfcOperatorErrorAlertMessages" />
+ <string-array name="wfcOperatorErrorAlertMessages">
+ <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
+ </string-array>
<!-- WFC Operator Error Messages showed as notifications -->
- <string-array name="wfcOperatorErrorNotificationMessages" />
+ <string-array name="wfcOperatorErrorNotificationMessages">
+ <item>Register with your carrier</item>
+ </string-array>
<!-- Template for showing cellular network operator name while WFC is active -->
- <string name="wfcSpnFormat">%s</string>
- <!-- Template for showing operator name for data connection while WFC is active -->
- <string name="wfcDataSpnFormat">%s</string>
+ <string-array name="wfcSpnFormats">
+ <item>%s</item>
+ <item>%s Wi-Fi Calling</item>
+ </string-array>
<!-- WFC, summary for Disabled -->
<string name="wifi_calling_off_summary">Off</string>
<!-- WFC, summary for Wi-Fi Preferred -->
@@ -349,18 +352,18 @@
<!-- SSL CA cert notification --> <skip />
<!-- Shows up when there is a user SSL CA Cert installed on the
device. Indicates to the user that SSL traffic can be intercepted. [CHAR LIMIT=NONE] -->
- <string name="ssl_ca_cert_warning">Network may be monitored</string>
- <!-- Content text for a notification. The Title of the notification is "ssl_ca_cert_warning",
- i.e. "Network may be monitored". This says that an unknown party is doing the monitoring.
- [CHAR LIMIT=100]-->
+ <plurals name="ssl_ca_cert_warning">
+ <item quantity="one">Certificate authority installed</item>
+ <item quantity="other">Certificate authorities installed</item>
+ </plurals>
+ <!-- Content text for a notification. The Title of the notification is "ssl_ca_cert_warning".
+ This says that an unknown party is doing the monitoring. [CHAR LIMIT=100]-->
<string name="ssl_ca_cert_noti_by_unknown">By an unknown third party</string>
- <!-- Content text for a notification. The Title of the notification is "ssl_ca_cert_warning",
- i.e. "Network may be monitored". This indicates that an unspecified administrator is doing
- the monitoring. [CHAR LIMIT=100]-->
+ <!-- Content text for a notification. The Title of the notification is "ssl_ca_cert_warning".
+ This indicates that an unspecified administrator is doing the monitoring. [CHAR LIMIT=100]-->
<string name="ssl_ca_cert_noti_by_administrator">By your work profile administrator</string>
- <!-- Content text for a notification. The Title of the notification is "ssl_ca_cert_warning",
- i.e. "Network may be monitored". This indicates who is doing the monitoring.
- [CHAR LIMIT=100]-->
+ <!-- Content text for a notification. The Title of the notification is "ssl_ca_cert_warning".
+ This indicates who is doing the monitoring. [CHAR LIMIT=100]-->
<string name="ssl_ca_cert_noti_managed">By <xliff:g id="managing_domain">%s</xliff:g></string>
<!-- Work profile deleted notification--> <skip />
@@ -2552,21 +2555,29 @@
<!-- Title of intent resolver dialog when selecting an application to run
and a previously used application is known. -->
<string name="whichApplicationNamed">Complete action using %1$s</string>
+ <!-- Generic label for a link to a intent resolver. -->
+ <string name="whichApplicationLabel">Complete action</string>
<!-- Title of intent resolver dialog when selecting a viewer application to run. -->
<string name="whichViewApplication">Open with</string>
<!-- Title of intent resolver dialog when selecting a viewer application to run
and a previously used application is known. -->
<string name="whichViewApplicationNamed">Open with %1$s</string>
+ <!-- Label for a link to a intent resolver dialog to view something -->
+ <string name="whichViewApplicationLabel">Open</string>
<!-- Title of intent resolver dialog when selecting an editor application to run. -->
<string name="whichEditApplication">Edit with</string>
<!-- Title of intent resolver dialog when selecting an editor application to run
and a previously used application is known. -->
<string name="whichEditApplicationNamed">Edit with %1$s</string>
+ <!-- Label for a link to a intent resolver dialog when selecting an editor application -->
+ <string name="whichEditApplicationLabel">Edit</string>
<!-- Title of intent resolver dialog when selecting a sharing application to run. -->
<string name="whichSendApplication">Share with</string>
<!-- Title of intent resolver dialog when selecting a sharing application to run
and a previously used application is known. -->
<string name="whichSendApplicationNamed">Share with %1$s</string>
+ <!-- Label for a link to a intent resolver dialog to sharing something -->
+ <string name="whichSendApplicationLabel">Share</string>
<!-- Title of intent resolver dialog when selecting an application to run to
send content to a specific recipient. Often used for email. -->
<string name="whichSendToApplication">Send using</string>
@@ -2574,11 +2585,23 @@
send content to a specific recipient and a previously used application is known.
Often used for email. -->
<string name="whichSendToApplicationNamed">Send using %1$s</string>
+ <!-- Label for a link to a intent resolver dialog to send content to a specific recipient. -->
+ <string name="whichSendToApplicationLabel">Send</string>
<!-- Title of intent resolver dialog when selecting a HOME application to run. -->
<string name="whichHomeApplication">Select a Home app</string>
<!-- Title of intent resolver dialog when selecting a HOME application to run
and a previously used application is known. -->
<string name="whichHomeApplicationNamed">Use %1$s as Home</string>
+ <!-- Label for a link to a intent resolver dialog when selecting a HOME -->
+ <string name="whichHomeApplicationLabel">Capture image</string>
+ <!-- Option to always use the selected application resolution in the future. See the "Complete action using" dialog title-->
+ <!-- Title of intent resolver dialog when capturing an image. -->
+ <string name="whichImageCaptureApplication">Capture image with</string>
+ <!-- Title of intent resolver dialog when capturing an image
+ and a previously used application is known. -->
+ <string name="whichImageCaptureApplicationNamed">Capture image with %1$s</string>
+ <!-- Label for a link to a intent resolver dialog when capturing an image -->
+ <string name="whichImageCaptureApplicationLabel">Capture image</string>
<!-- Option to always use the selected application resolution in the future. See the "Complete action using" dialog title-->
<string name="alwaysUse">Use by default for this action.</string>
<!-- Title of the list of alternate options to complete an action shown when the
@@ -4028,6 +4051,9 @@
<!-- [CHAR_LIMIT=NONE] Battery saver: Feature description -->
<string name="battery_saver_description">To help improve battery life, battery saver reduces your device’s performance and limits vibration, location services, and most background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging.</string>
+ <!-- [CHAR_LIMIT=NONE] Data saver: Feature description -->
+ <string name="data_saver_description">To help reduce data usage, Data Saver prevents some apps from sending or receiving data in the background. An app you’re currently using can access data, but may do so less frequently. This may mean, for example, that images don’t display until you tap them.</string>
+
<!-- Zen mode condition - summary: time duration in minutes. [CHAR LIMIT=NONE] -->
<plurals name="zen_mode_duration_minutes_summary">
<item quantity="one">For one minute (until <xliff:g id="formattedTime" example="10:00 PM">%2$s</xliff:g>)</item>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 2420c1a..8a33406 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -456,6 +456,14 @@
<style name="Widget.Material.Notification.ProgressBar" parent="Widget.Material.Light.ProgressBar.Horizontal" />
+ <style name="Widget.Material.Notification.MessagingText" parent="Widget.Material.Light.TextView">
+ <item name="layout_width">match_parent</item>
+ <item name="layout_height">wrap_content</item>
+ <item name="ellipsize">end</item>
+ <item name="visibility">gone</item>
+ <item name="textAppearance">@style/TextAppearance.Material.Notification</item>
+ </style>
+
<!-- Widget Styles -->
<style name="Material"/>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d218509..a35b409 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -295,7 +295,6 @@
<java-symbol type="bool" name="config_wifi_framework_enable_associated_network_selection" />
<java-symbol type="bool" name="config_wifi_only_link_same_credential_configurations" />
<java-symbol type="bool" name="config_wifi_enable_disconnection_debounce" />
- <java-symbol type="bool" name="config_wifi_enable_5GHz_preference" />
<java-symbol type="bool" name="config_wifi_revert_country_code_on_cellular_loss" />
<java-symbol type="bool" name="config_wifi_enable_wifi_firmware_debugging" />
<java-symbol type="integer" name="config_wifi_logger_ring_buffer_size_limit_kb" />
@@ -312,8 +311,6 @@
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_threshold" />
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_factor" />
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_penalty_threshold" />
- <java-symbol type="integer" name="config_wifi_framework_current_association_hysteresis_high" />
- <java-symbol type="integer" name="config_wifi_framework_current_association_hysteresis_low" />
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_penalty_threshold" />
<java-symbol type="integer" name="config_wifi_framework_RSSI_SCORE_OFFSET" />
<java-symbol type="integer" name="config_wifi_framework_RSSI_SCORE_SLOPE" />
@@ -322,14 +319,11 @@
<java-symbol type="integer" name="config_wifi_framework_PASSPOINT_SECURITY_AWARD" />
<java-symbol type="integer" name="config_wifi_framework_SECURITY_AWARD" />
<java-symbol type="integer" name="config_wifi_disconnected_short_scan_interval" />
- <java-symbol type="integer" name="config_wifi_disconnected_long_scan_interval" />
<java-symbol type="integer" name="config_wifi_associated_short_scan_interval" />
- <java-symbol type="integer" name="config_wifi_associated_long_scan_interval" />
<java-symbol type="integer" name="config_wifi_framework_associated_full_scan_backoff" />
<java-symbol type="integer" name="config_wifi_framework_associated_full_scan_max_interval" />
<java-symbol type="integer" name="config_wifi_framework_associated_full_scan_max_total_dwell_time" />
<java-symbol type="integer" name="config_wifi_framework_associated_partial_scan_max_num_active_channels" />
- <java-symbol type="integer" name="config_wifi_framework_associated_partial_scan_max_num_passive_channels" />
<java-symbol type="integer" name="config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz" />
<java-symbol type="integer" name="config_wifi_framework_wifi_score_low_rssi_threshold_24GHz" />
<java-symbol type="integer" name="config_wifi_framework_wifi_score_good_rssi_threshold_24GHz" />
@@ -359,9 +353,6 @@
<java-symbol type="integer" name="config_wifi_framework_associated_partial_scan_rx_packet_threshold" />
<java-symbol type="integer" name="config_wifi_framework_network_switch_tx_packet_threshold" />
<java-symbol type="integer" name="config_wifi_framework_network_switch_rx_packet_threshold" />
- <java-symbol type="integer" name="config_wifi_framework_max_connection_errors_to_blacklist" />
- <java-symbol type="integer" name="config_wifi_framework_max_auth_errors_to_blacklist" />
- <java-symbol type="integer" name="config_wifi_framework_network_black_list_min_time_milli" />
<java-symbol type="integer" name="config_wifi_framework_current_network_boost" />
<java-symbol type="integer" name="config_bluetooth_max_advertisers" />
<java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
@@ -399,9 +390,7 @@
<java-symbol type="integer" name="config_wifi_supplicant_scan_interval" />
<java-symbol type="integer" name="config_wifi_no_network_periodic_scan_interval" />
<java-symbol type="integer" name="config_wifi_scan_interval_p2p_connected" />
- <java-symbol type="bool" name="config_wifi_hal_pno_enable" />
<java-symbol type="integer" name="config_windowOutsetBottom" />
- <java-symbol type="bool" name="config_wifi_ssid_white_list_enable" />
<java-symbol type="integer" name="db_connection_pool_size" />
<java-symbol type="integer" name="db_journal_size_limit" />
<java-symbol type="integer" name="db_wal_autocheckpoint" />
@@ -782,11 +771,9 @@
<java-symbol type="string" name="phoneTypeWorkMobile" />
<java-symbol type="string" name="phoneTypeWorkPager" />
<java-symbol type="string" name="wfcRegErrorTitle" />
- <java-symbol type="array" name="wfcOperatorErrorCodes" />
<java-symbol type="array" name="wfcOperatorErrorAlertMessages" />
<java-symbol type="array" name="wfcOperatorErrorNotificationMessages" />
- <java-symbol type="string" name="wfcSpnFormat" />
- <java-symbol type="string" name="wfcDataSpnFormat" />
+ <java-symbol type="array" name="wfcSpnFormats" />
<java-symbol type="string" name="wifi_calling_off_summary" />
<java-symbol type="string" name="wfc_mode_wifi_preferred_summary" />
<java-symbol type="string" name="wfc_mode_cellular_preferred_summary" />
@@ -1106,7 +1093,6 @@
<java-symbol type="string" name="ssl_ca_cert_noti_by_unknown" />
<java-symbol type="string" name="ssl_ca_cert_noti_by_administrator" />
<java-symbol type="string" name="ssl_ca_cert_noti_managed" />
- <java-symbol type="string" name="ssl_ca_cert_warning" />
<java-symbol type="string" name="work_profile_deleted" />
<java-symbol type="string" name="work_profile_deleted_description" />
<java-symbol type="string" name="work_profile_deleted_details" />
@@ -1126,6 +1112,7 @@
<java-symbol type="plurals" name="matches_found" />
<java-symbol type="plurals" name="restr_pin_countdown" />
<java-symbol type="plurals" name="pinpuk_attempts" />
+ <java-symbol type="plurals" name="ssl_ca_cert_warning" />
<java-symbol type="array" name="carrier_properties" />
<java-symbol type="array" name="config_sms_enabled_locking_shift_tables" />
@@ -1397,7 +1384,6 @@
<java-symbol type="xml" name="password_kbd_qwerty" />
<java-symbol type="xml" name="autotext" />
- <java-symbol type="xml" name="eri" />
<java-symbol type="xml" name="password_kbd_numeric" />
<java-symbol type="xml" name="password_kbd_qwerty_shifted" />
<java-symbol type="xml" name="password_kbd_symbols" />
@@ -1726,7 +1712,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"/>
@@ -2114,6 +2100,7 @@
<java-symbol type="dimen" name="timepicker_text_size_normal" />
<java-symbol type="dimen" name="timepicker_text_size_inner" />
<java-symbol type="string" name="battery_saver_description" />
+ <java-symbol type="string" name="data_saver_description" />
<java-symbol type="string" name="zen_mode_forever" />
<java-symbol type="string" name="zen_mode_forever_dnd" />
<java-symbol type="string" name="zen_mode_rule_name_combination" />
@@ -2210,14 +2197,22 @@
<java-symbol type="attr" name="touchscreenBlocksFocus" />
<java-symbol type="layout" name="resolver_list_with_default" />
<java-symbol type="string" name="whichApplicationNamed" />
+ <java-symbol type="string" name="whichApplicationLabel" />
<java-symbol type="string" name="whichViewApplication" />
<java-symbol type="string" name="whichViewApplicationNamed" />
+ <java-symbol type="string" name="whichViewApplicationLabel" />
<java-symbol type="string" name="whichEditApplication" />
<java-symbol type="string" name="whichEditApplicationNamed" />
+ <java-symbol type="string" name="whichEditApplicationLabel" />
<java-symbol type="string" name="whichSendApplication" />
<java-symbol type="string" name="whichSendApplicationNamed" />
+ <java-symbol type="string" name="whichSendApplicationLabel" />
<java-symbol type="string" name="whichSendToApplication" />
<java-symbol type="string" name="whichSendToApplicationNamed" />
+ <java-symbol type="string" name="whichSendToApplicationLabel" />
+ <java-symbol type="string" name="whichImageCaptureApplication" />
+ <java-symbol type="string" name="whichImageCaptureApplicationNamed" />
+ <java-symbol type="string" name="whichImageCaptureApplicationLabel" />
<java-symbol type="attr" name="lightY" />
<java-symbol type="attr" name="lightZ" />
<java-symbol type="attr" name="lightRadius" />
@@ -2247,6 +2242,7 @@
<java-symbol type="array" name="networks_not_clear_data" />
<java-symbol type="bool" name="config_switch_phone_on_voice_reg_state_change" />
<java-symbol type="string" name="whichHomeApplicationNamed" />
+ <java-symbol type="string" name="whichHomeApplicationLabel" />
<java-symbol type="bool" name="config_sms_force_7bit_encoding" />
<java-symbol type="bool" name="config_defaultWindowFeatureOptionsPanel" />
<java-symbol type="bool" name="config_defaultWindowFeatureContextMenu" />
@@ -2505,6 +2501,8 @@
<java-symbol type="bool" name="config_strongAuthRequiredOnBoot" />
<java-symbol type="layout" name="app_anr_dialog" />
+ <java-symbol type="layout" name="notification_template_material_messaging" />
+
<java-symbol type="id" name="aerr_wait" />
<java-symbol type="id" name="notification_content_container" />
@@ -2534,12 +2532,16 @@
<java-symbol type="string" name="carrier_app_notification_text" />
<java-symbol type="string" name="negative_duration" />
+ <java-symbol type="dimen" name="notification_messaging_spacing" />
+
<!-- WallpaperManager config -->
<java-symbol type="string" name="config_wallpaperCropperPackage" />
<java-symbol type="id" name="textSpacerNoTitle" />
<java-symbol type="id" name="titleDividerNoCustom" />
+ <java-symbol type="id" name="notification_messaging" />
+
<java-symbol type="bool" name="config_sustainedPerformanceModeSupported" />
<!-- Wearable input extract edit view -->
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/res/res/xml/eri.xml b/core/res/res/xml/eri.xml
deleted file mode 100644
index cd66f14..0000000
--- a/core/res/res/xml/eri.xml
+++ /dev/null
@@ -1,118 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- Note that IconMode can be only 0, ON or 1, FLASHING
- The icon is turned OFF if then IconIndex = 1 -->
-
-<EriFile VersionNumber="1357"
- NumberOfEriEntries="12"
- EriFileType="1">
-
- <CallPromptId Id="0"
- CallPromptText="CallPromptId0"/>
-
- <CallPromptId Id="1"
- CallPromptText="CallPromptId1"/>
-
- <CallPromptId Id="2"
- CallPromptText="CallPromptId2"/>
-
- <EriInfo RoamingIndicator="64"
- IconIndex="1"
- IconMode="0"
- EriText="T-CDMA 64"
- CallPromptId="0"
- AlertId="0"/>
-
- <EriInfo RoamingIndicator="65"
- IconIndex="65"
- IconMode="0"
- EriText="T-CDMA 65"
- CallPromptId="0"
- AlertId="0"/>
-
- <EriInfo RoamingIndicator="66"
- IconIndex="1"
- IconMode="0"
- EriText="T-CDMA Ext 66"
- CallPromptId="0"
- AlertId="0"/>
-
- <EriInfo RoamingIndicator="67"
- IconIndex="67"
- IconMode="0"
- EriText="T-CDMA Ext 67"
- CallPromptId="0"
- AlertId="0"/>
-
- <EriInfo RoamingIndicator="68"
- IconIndex="68"
- IconMode="0"
- EriText="T-CDMA Roam 68"
- CallPromptId="0"
- AlertId="0"/>
-
- <EriInfo RoamingIndicator="69"
- IconIndex="69"
- IconMode="1"
- EriText="T-CDMA Ext 69"
- CallPromptId="0"
- AlertId="0"/>
-
- <EriInfo RoamingIndicator="70"
- IconIndex="70"
- IconMode="1"
- EriText="T-CDMA Roam 70"
- CallPromptId="0"
- AlertId="0"/>
-
- <EriInfo RoamingIndicator="71"
- IconIndex="1"
- IconMode="0"
- EriText="T-CDMA Ext 71"
- CallPromptId="0"
- AlertId="0"/>
-
- <EriInfo RoamingIndicator="72"
- IconIndex="72"
- IconMode="0"
- EriText="T-CDMA Ext 72"
- CallPromptId="0"
- AlertId="0"/>
-
- <EriInfo RoamingIndicator="73"
- IconIndex="73"
- IconMode="0"
- EriText="T-CDMA Roam 73"
- CallPromptId="0"
- AlertId="0"/>
-
- <EriInfo RoamingIndicator="74"
- IconIndex="74"
- IconMode="1"
- EriText="T-CDMA Ext 74"
- CallPromptId="0"
- AlertId="0"/>
-
- <EriInfo RoamingIndicator="75"
- IconIndex="75"
- IconMode="1"
- EriText="T-CDMA Roam 75"
- CallPromptId="0"
- AlertId="0"/>
-
-</EriFile>
diff --git a/core/tests/coretests/src/android/util/PatternsTest.java b/core/tests/coretests/src/android/util/PatternsTest.java
index 348f8fd..edb3082 100644
--- a/core/tests/coretests/src/android/util/PatternsTest.java
+++ b/core/tests/coretests/src/android/util/PatternsTest.java
@@ -419,6 +419,36 @@
Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
}
+ @SmallTest
+ public void testAutoLinkWebUrl_doesNotMatchUnicodeSpaces() throws Exception {
+ String part1 = "http://and";
+ String part2 = "roid";
+ String[] emptySpaces = new String[]{
+ "\u00A0", // no-break space
+ "\u2000", // en quad
+ "\u2001", // em quad
+ "\u2002", // en space
+ "\u2003", // em space
+ "\u2004", // three-per-em space
+ "\u2005", // four-per-em space
+ "\u2006", // six-per-em space
+ "\u2007", // figure space
+ "\u2008", // punctuation space
+ "\u2009", // thin space
+ "\u200A", // hair space
+ "\u2028", // line separator
+ "\u2029", // paragraph separator
+ "\u202F", // narrow no-break space
+ "\u3000" // ideographic space
+ };
+
+ for (String emptySpace : emptySpaces) {
+ String url = part1 + emptySpace + part2;
+ assertFalse("Should not match empty space - code:" + emptySpace.codePointAt(0),
+ Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
+ }
+ }
+
// Tests for Patterns.IP_ADDRESS
@SmallTest
diff --git a/core/tests/coretests/src/com/android/internal/app/procstats/SparseMappingTableTest.java b/core/tests/coretests/src/com/android/internal/app/procstats/SparseMappingTableTest.java
new file mode 100644
index 0000000..fd57baa
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/app/procstats/SparseMappingTableTest.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app.procstats;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+
+import android.os.BatteryStats;
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.mockito.Mockito;
+
+/**
+ * Provides test cases for SparseMappingTable.
+ */
+public class SparseMappingTableTest extends TestCase {
+ private static final String TAG = "SparseMappingTableTest";
+
+ final byte ID1 = 1;
+ final byte ID2 = 2;
+
+ final long VALUE1 = 100;
+ final long VALUE2 = 10000000000L;
+
+ /**
+ * Test the parceling and unparceling logic when there is no data.
+ */
+ @SmallTest
+ public void testParcelingEmpty() throws Exception {
+ final SparseMappingTable data = new SparseMappingTable();
+ final SparseMappingTable.Table table = new SparseMappingTable.Table(data);
+
+ final Parcel dataParcel = Parcel.obtain();
+ data.writeToParcel(dataParcel);
+
+ final Parcel tableParcel = Parcel.obtain();
+ table.writeToParcel(tableParcel);
+
+ dataParcel.setDataPosition(0);
+ final SparseMappingTable data1 = new SparseMappingTable();
+ data1.readFromParcel(dataParcel);
+ Assert.assertEquals(0, dataParcel.dataAvail());
+ dataParcel.recycle();
+
+ tableParcel.setDataPosition(0);
+ final SparseMappingTable.Table table1 = new SparseMappingTable.Table(data1);
+ table1.readFromParcel(tableParcel);
+ Assert.assertEquals(0, tableParcel.dataAvail());
+ tableParcel.recycle();
+ }
+
+ /**
+ * Test the parceling and unparceling logic.
+ */
+ @SmallTest
+ public void testParceling() throws Exception {
+ int key;
+ final SparseMappingTable data = new SparseMappingTable();
+ final SparseMappingTable.Table table = new SparseMappingTable.Table(data);
+
+ key = table.getOrAddKey(ID1, 1);
+ table.setValue(key, VALUE1);
+
+ key = table.getOrAddKey(ID2, 1);
+ table.setValue(key, VALUE2);
+
+ final Parcel dataParcel = Parcel.obtain();
+ data.writeToParcel(dataParcel);
+
+ final Parcel tableParcel = Parcel.obtain();
+ table.writeToParcel(tableParcel);
+
+ dataParcel.setDataPosition(0);
+ final SparseMappingTable data1 = new SparseMappingTable();
+ data1.readFromParcel(dataParcel);
+ Assert.assertEquals(0, dataParcel.dataAvail());
+ dataParcel.recycle();
+
+ tableParcel.setDataPosition(0);
+ final SparseMappingTable.Table table1 = new SparseMappingTable.Table(data1);
+ table1.readFromParcel(tableParcel);
+ Assert.assertEquals(0, tableParcel.dataAvail());
+ tableParcel.recycle();
+
+ key = table1.getKey(ID1);
+ Assert.assertEquals(VALUE1, table1.getValue(key));
+
+ key = table1.getKey(ID2);
+ Assert.assertEquals(VALUE2, table1.getValue(key));
+ }
+
+
+ /**
+ * Test that after resetting you can still read data, you just get no values.
+ */
+ @SmallTest
+ public void testParcelingWithReset() throws Exception {
+ int key;
+ final SparseMappingTable data = new SparseMappingTable();
+ final SparseMappingTable.Table table = new SparseMappingTable.Table(data);
+
+ key = table.getOrAddKey(ID1, 1);
+ table.setValue(key, VALUE1);
+
+ data.reset();
+ table.resetTable();
+
+ key = table.getOrAddKey(ID2, 1);
+ table.setValue(key, VALUE2);
+
+ Log.d(TAG, "before: " + data.dumpInternalState(true));
+ Log.d(TAG, "before: " + table.dumpInternalState());
+
+ final Parcel dataParcel = Parcel.obtain();
+ data.writeToParcel(dataParcel);
+
+ final Parcel tableParcel = Parcel.obtain();
+ table.writeToParcel(tableParcel);
+
+ dataParcel.setDataPosition(0);
+ final SparseMappingTable data1 = new SparseMappingTable();
+ data1.readFromParcel(dataParcel);
+ Assert.assertEquals(0, dataParcel.dataAvail());
+ dataParcel.recycle();
+
+ tableParcel.setDataPosition(0);
+ final SparseMappingTable.Table table1 = new SparseMappingTable.Table(data1);
+ table1.readFromParcel(tableParcel);
+ Assert.assertEquals(0, tableParcel.dataAvail());
+ tableParcel.recycle();
+
+ key = table1.getKey(ID1);
+ Assert.assertEquals(SparseMappingTable.INVALID_KEY, key);
+
+ key = table1.getKey(ID2);
+ Assert.assertEquals(VALUE2, table1.getValue(key));
+
+ Log.d(TAG, " after: " + data1.dumpInternalState(true));
+ Log.d(TAG, " after: " + table1.dumpInternalState());
+ }
+
+ /**
+ * Test that it fails if you reset the data and not the table.
+ *
+ * Resetting the table and not the data is basically okay. The data in the
+ * SparseMappingTable will be leaked.
+ */
+ @SmallTest
+ public void testResetDataOnlyFails() throws Exception {
+ int key;
+ final SparseMappingTable data = new SparseMappingTable();
+ final SparseMappingTable.Table table = new SparseMappingTable.Table(data);
+
+ key = table.getOrAddKey(ID1, 1);
+ table.setValue(key, VALUE1);
+
+ Assert.assertEquals(VALUE1, table.getValue(key));
+
+ data.reset();
+
+ try {
+ table.getValue(key);
+ throw new Exception("Exception not thrown after mismatched reset calls.");
+ } catch (RuntimeException ex) {
+ // Good
+ }
+ }
+
+ /**
+ * Test that trying to get data that you didn't add fails correctly.
+ */
+ @SmallTest
+ public void testInvalidKey() throws Exception {
+ int key;
+ final SparseMappingTable data = new SparseMappingTable();
+ final SparseMappingTable.Table table = new SparseMappingTable.Table(data);
+
+ key = table.getKey(ID1);
+
+ // The key should be INVALID_KEY
+ Assert.assertEquals(SparseMappingTable.INVALID_KEY, key);
+
+ // If you get the value with getValueForId you get 0.
+ Assert.assertEquals(0, table.getValueForId(ID1));
+ }
+}
+
+
+
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/data/etc/platform.xml b/data/etc/platform.xml
index d412d7c..8a7d39b 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -111,6 +111,20 @@
<group gid="media" />
</permission>
+ <!-- These are permissions that were mapped to gids but we need
+ to keep them here until an upgrade from L to the current
+ version is to be supported. These permissions are built-in
+ and in L were not stored in packages.xml as a result if they
+ are not defined here while parsing packages.xml we would
+ ignore these permissions being granted to apps and not
+ propagate the granted state. From N we are storing the
+ built-in permissions in packages.xml as the saved storage
+ is negligible (one tag with the permission) compared to
+ the fragility as one can remove a built-in permission which
+ no longer needs to be mapped to gids and break grant propagation. -->
+ <permission name="android.permission.READ_EXTERNAL_STORAGE" />
+ <permission name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
<!-- ================================================================== -->
<!-- ================================================================== -->
<!-- ================================================================== -->
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index bcac6a1..117e17b 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -320,6 +320,7 @@
</family>
<family lang="und-Tibt">
<font weight="400" style="normal">NotoSansTibetan-Regular.ttf</font>
+ <font weight="700" style="normal">NotoSansTibetan-Bold.ttf</font>
</family>
<family lang="und-Tfng">
<font weight="400" style="normal">NotoSansTifinagh-Regular.ttf</font>
@@ -350,6 +351,9 @@
<font weight="400" style="normal">NotoColorEmoji.ttf</font>
</family>
<family>
+ <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted2.ttf</font>
+ </family>
+ <family>
<font weight="400" style="normal">DroidSansFallback.ttf</font>
</family>
<!--
diff --git a/docs/html/guide/topics/manifest/application-element.jd b/docs/html/guide/topics/manifest/application-element.jd
index 5600b5c..887b4ea 100644
--- a/docs/html/guide/topics/manifest/application-element.jd
+++ b/docs/html/guide/topics/manifest/application-element.jd
@@ -472,6 +472,8 @@
{@link android.os.StrictMode.VmPolicy.Builder#detectCleartextNetwork() StrictMode.VmPolicy.Builder.detectCleartextNetwork()}.
<p>This attribute was added in API level 23.</p>
+
+<p>This flag is ignored on Android N and above if an Android Network Security Config is present.</p>
</dd>
<dt><a name="vmSafeMode"></a>{@code android:vmSafeMode}</dt>
diff --git a/docs/html/training/articles/keystore.jd b/docs/html/training/articles/keystore.jd
index aa1ed0a..026f7a0 100644
--- a/docs/html/training/articles/keystore.jd
+++ b/docs/html/training/articles/keystore.jd
@@ -152,8 +152,10 @@
<p>Generating a new {@link java.security.PrivateKey} requires that
you also specify the initial X.509 attributes that the self-signed
- certificate will have. You can replace the certificate at a later
- time with a certificate signed by a Certificate Authority.</p>
+ certificate will have. You can use
+ {@link java.security.KeyStore#setKeyEntry(String, java.security.Key, char[], java.security.cert.Certificate[]) KeyStore.setKeyEntry}
+ to replace the certificate at a later time with a certificate signed
+ by a Certificate Authority (CA).</p>
<p>To generate the key, use a {@link java.security.KeyPairGenerator}
with {@link android.security.KeyPairGeneratorSpec}:</p>
diff --git a/graphics/java/android/graphics/PixelCopy.java b/graphics/java/android/graphics/PixelCopy.java
new file mode 100644
index 0000000..c599126
--- /dev/null
+++ b/graphics/java/android/graphics/PixelCopy.java
@@ -0,0 +1,104 @@
+package android.graphics;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.view.Surface;
+import android.view.SurfaceView;
+import android.view.ThreadedRenderer;
+
+/**
+ * Provides a mechanisms to issue pixel copy requests to allow for copy
+ * operations from {@link Surface} to {@link Bitmap}
+ *
+ * @hide
+ */
+public final class PixelCopy {
+ /**
+ * Contains the result of a pixel copy request
+ */
+ public static final class Response {
+ /**
+ * Indicates whether or not the copy request completed successfully.
+ * If this is true, then {@link #bitmap} contains the result of the copy.
+ * If this is false, {@link #bitmap} is unmodified from the originally
+ * passed destination.
+ *
+ * For example a request might fail if the source is protected content
+ * so copies are not allowed. Similarly if the source has nothing to
+ * copy from, because either no frames have been produced yet or because
+ * it has already been destroyed, then this will be false.
+ */
+ public boolean success;
+
+ /**
+ * The output bitmap. This is always the same object that was passed
+ * to request() as the 'dest' bitmap. If {@link #success} is true this
+ * contains a copy of the pixels of the source object. If {@link #success}
+ * is false then this is unmodified.
+ */
+ @NonNull
+ public Bitmap bitmap;
+ }
+
+ public interface OnPixelCopyFinished {
+ /**
+ * Callback for when a pixel copy request has completed. This will be called
+ * regardless of whether the copy succeeded or failed.
+ *
+ * @param response Contains the result of the copy request which includes
+ * whether or not the copy was successful.
+ */
+ void onPixelCopyFinished(PixelCopy.Response response);
+ }
+
+ /**
+ * Requests for the display content of a {@link SurfaceView} to be copied
+ * into a provided {@link Bitmap}.
+ *
+ * The contents of the source will be scaled to fit exactly inside the bitmap.
+ * The pixel format of the source buffer will be converted, as part of the copy,
+ * to fit the the bitmap's {@link Bitmap.Config}. The most recently queued buffer
+ * in the SurfaceView's Surface will be used as the source of the copy.
+ *
+ * @param source The source from which to copy
+ * @param dest The destination of the copy. The source will be scaled to
+ * match the width, height, and format of this bitmap.
+ * @param listener Callback for when the pixel copy request completes
+ * @param listenerThread The callback will be invoked on this Handler when
+ * the copy is finished.
+ */
+ public static void request(@NonNull SurfaceView source, @NonNull Bitmap dest,
+ @NonNull OnPixelCopyFinished listener, @NonNull Handler listenerThread) {
+ request(source.getHolder().getSurface(), dest, listener, listenerThread);
+ }
+
+ /**
+ * Requests a copy of the pixels from a {@link Surface} to be copied into
+ * a provided {@link Bitmap}.
+ *
+ * The contents of the source will be scaled to fit exactly inside the bitmap.
+ * The pixel format of the source buffer will be converted, as part of the copy,
+ * to fit the the bitmap's {@link Bitmap.Config}. The most recently queued buffer
+ * in the Surface will be used as the source of the copy.
+ *
+ * @param source The source from which to copy
+ * @param dest The destination of the copy. The source will be scaled to
+ * match the width, height, and format of this bitmap.
+ * @param listener Callback for when the pixel copy request completes
+ * @param listenerThread The callback will be invoked on this Handler when
+ * the copy is finished.
+ */
+ public static void request(@NonNull Surface source, @NonNull Bitmap dest,
+ @NonNull OnPixelCopyFinished listener, @NonNull Handler listenerThread) {
+ // TODO: Make this actually async and fast and cool and stuff
+ final PixelCopy.Response response = new PixelCopy.Response();
+ response.success = ThreadedRenderer.copySurfaceInto(source, dest);
+ response.bitmap = dest;
+ listenerThread.post(new Runnable() {
+ @Override
+ public void run() {
+ listener.onPixelCopyFinished(response);
+ }
+ });
+ }
+}
diff --git a/graphics/java/android/graphics/PixelFormat.java b/graphics/java/android/graphics/PixelFormat.java
index 832b9c3..98082ca 100644
--- a/graphics/java/android/graphics/PixelFormat.java
+++ b/graphics/java/android/graphics/PixelFormat.java
@@ -16,8 +16,18 @@
package android.graphics;
-public class PixelFormat
-{
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+public class PixelFormat {
+
+ /** @hide */
+ @IntDef({UNKNOWN, TRANSLUCENT, TRANSPARENT, OPAQUE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Opacity {}
+
/* these constants need to match those in hardware/hardware.h */
public static final int UNKNOWN = 0;
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index f15aff7..2886f0d 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -19,6 +19,7 @@
import android.content.res.AssetManager;
import android.util.Log;
import android.util.LongSparseArray;
+import android.util.LruCache;
import android.util.SparseArray;
import org.xmlpull.v1.XmlPullParserException;
@@ -63,6 +64,11 @@
private static final LongSparseArray<SparseArray<Typeface>> sTypefaceCache =
new LongSparseArray<SparseArray<Typeface>>(3);
+ /**
+ * Cache for Typeface objects dynamically loaded from assets. Currently max size is 16.
+ */
+ private static final LruCache<String, Typeface> sDynamicTypefaceCache = new LruCache<>(16);
+
static Typeface sDefaultTypeface;
static Map<String, Typeface> sSystemFontMap;
static FontFamily[] sFallbackFonts;
@@ -176,22 +182,50 @@
/**
* Create a new typeface from the specified font data.
- * @param mgr The application's asset manager
- * @param path The file name of the font data in the assets directory
+ *
+ * @param mgr The application's asset manager
+ * @param path The file name of the font data in the assets directory
* @return The new typeface.
*/
public static Typeface createFromAsset(AssetManager mgr, String path) {
if (sFallbackFonts != null) {
- FontFamily fontFamily = new FontFamily();
- if (fontFamily.addFontFromAsset(mgr, path)) {
- FontFamily[] families = { fontFamily };
- return createFromFamiliesWithDefault(families);
+ synchronized (sDynamicTypefaceCache) {
+ final String key = createAssetUid(mgr, path);
+ Typeface typeface = sDynamicTypefaceCache.get(key);
+ if (typeface != null) return typeface;
+
+ FontFamily fontFamily = new FontFamily();
+ if (fontFamily.addFontFromAsset(mgr, path)) {
+ FontFamily[] families = { fontFamily };
+ typeface = createFromFamiliesWithDefault(families);
+ sDynamicTypefaceCache.put(key, typeface);
+ return typeface;
+ }
}
}
throw new RuntimeException("Font asset not found " + path);
}
/**
+ * Creates a unique id for a given AssetManager and asset path.
+ *
+ * @param mgr AssetManager instance
+ * @param path The path for the asset.
+ * @return Unique id for a given AssetManager and asset path.
+ */
+ private static String createAssetUid(final AssetManager mgr, String path) {
+ final SparseArray<String> pkgs = mgr.getAssignedPackageIdentifiers();
+ final StringBuilder builder = new StringBuilder();
+ final int size = pkgs.size();
+ for (int i = 0; i < size; i++) {
+ builder.append(pkgs.valueAt(i));
+ builder.append("-");
+ }
+ builder.append(path);
+ return builder.toString();
+ }
+
+ /**
* Create a new typeface from the specified font file.
*
* @param path The path to the font data.
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 4f600b4..7f3a437 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -16,7 +16,14 @@
package android.graphics.drawable;
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.annotation.AttrRes;
import android.annotation.ColorInt;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.ActivityInfo.Config;
@@ -47,17 +54,12 @@
import android.util.Xml;
import android.view.View;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Collection;
-import com.android.internal.R;
-
/**
* A Drawable is a general abstraction for "something that can be drawn." Most
* often you will deal with Drawable as the type of resource retrieved for
@@ -119,6 +121,47 @@
* whose overall size is modified based on the current level.
* </ul>
*
+ * <a name="Custom"></a>
+ * <h3>Custom drawables</h3>
+ *
+ * <p>
+ * All versions of Android allow the Drawable class to be extended and used at
+ * run time in place of framework-provided drawable classes. Starting in
+ * {@link android.os.Build.VERSION_CODES#N API 24}, custom drawables classes
+ * may also be used in XML.
+ * <p>
+ * <strong>Note:</strong> Custom drawable classes are only accessible from
+ * within your application package. Other applications will not be able to load
+ * them.
+ * <p>
+ * At a minimum, custom drawable classes must implement the abstract methods on
+ * Drawable and should override the {@link Drawable#draw(Canvas)} method to
+ * draw content.
+ * <p>
+ * Custom drawables classes may be used in XML in multiple ways:
+ * <ul>
+ * <li>
+ * Using the fully-qualified class name as the XML element name. For
+ * this method, the custom drawable class must be a public top-level
+ * class.
+ * <pre>
+ * <com.myapp.MyCustomDrawable xmlns:android="http://schemas.android.com/apk/res/android"
+ * android:color="#ffff0000" />
+ * </pre>
+ * </li>
+ * <li>
+ * Using <em>drawable</em> as the XML element name and specifying the
+ * fully-qualified class name from the <em>class</em> attribute. This
+ * method may be used for both public top-level classes and public
+ * static inner classes.
+ * <pre>
+ * <drawable xmlns:android="http://schemas.android.com/apk/res/android"
+ * class="com.myapp.MyTopLevelClass$InnerCustomDrawable"
+ * android:color="#ffff0000" />
+ * </pre>
+ * </li>
+ * </ul>
+ *
* <div class="special reference">
* <h3>Developer Guides</h3>
* <p>For more information about how to use drawables, read the
@@ -148,7 +191,7 @@
*
* @param canvas The canvas to draw into
*/
- public abstract void draw(Canvas canvas);
+ public abstract void draw(@NonNull Canvas canvas);
/**
* Specify a bounding rectangle for the Drawable. This is where the drawable
@@ -176,7 +219,7 @@
* Specify a bounding rectangle for the Drawable. This is where the drawable
* will draw when its draw() method is called.
*/
- public void setBounds(Rect bounds) {
+ public void setBounds(@NonNull Rect bounds) {
setBounds(bounds.left, bounds.top, bounds.right, bounds.bottom);
}
@@ -188,7 +231,7 @@
* @param bounds Rect to receive the drawable's bounds (allocated by the
* caller).
*/
- public final void copyBounds(Rect bounds) {
+ public final void copyBounds(@NonNull Rect bounds) {
bounds.set(mBounds);
}
@@ -200,6 +243,7 @@
*
* @return A copy of the drawable's bounds
*/
+ @NonNull
public final Rect copyBounds() {
return new Rect(mBounds);
}
@@ -219,6 +263,7 @@
* @see #copyBounds()
* @see #copyBounds(android.graphics.Rect)
*/
+ @NonNull
public final Rect getBounds() {
if (mBounds == ZERO_BOUNDS_RECT) {
mBounds = new Rect();
@@ -237,6 +282,7 @@
*
* @return The dirty bounds of this drawable
*/
+ @NonNull
public Rect getDirtyBounds() {
return getBounds();
}
@@ -354,8 +400,8 @@
*
* @see #getCallback()
*/
- public final void setCallback(Callback cb) {
- mCallback = new WeakReference<Callback>(cb);
+ public final void setCallback(@Nullable Callback cb) {
+ mCallback = cb != null ? new WeakReference<>(cb) : null;
}
/**
@@ -366,11 +412,9 @@
*
* @see #setCallback(android.graphics.drawable.Drawable.Callback)
*/
+ @Nullable
public Callback getCallback() {
- if (mCallback != null) {
- return mCallback.get();
- }
- return null;
+ return mCallback != null ? mCallback.get() : null;
}
/**
@@ -399,7 +443,7 @@
*
* @see Callback#scheduleDrawable
*/
- public void scheduleSelf(Runnable what, long when) {
+ public void scheduleSelf(@NonNull Runnable what, long when) {
final Callback callback = getCallback();
if (callback != null) {
callback.scheduleDrawable(this, what, when);
@@ -415,7 +459,7 @@
*
* @see Callback#unscheduleDrawable
*/
- public void unscheduleSelf(Runnable what) {
+ public void unscheduleSelf(@NonNull Runnable what) {
final Callback callback = getCallback();
if (callback != null) {
callback.unscheduleDrawable(this, what);
@@ -429,7 +473,7 @@
* {@link android.view.View#LAYOUT_DIRECTION_RTL}
* @see #setLayoutDirection(int)
*/
- public int getLayoutDirection() {
+ public @View.ResolvedLayoutDir int getLayoutDirection() {
return mLayoutDirection;
}
@@ -441,6 +485,9 @@
* @param layoutDirection the resolved layout direction for the drawable,
* either {@link android.view.View#LAYOUT_DIRECTION_LTR}
* or {@link android.view.View#LAYOUT_DIRECTION_RTL}
+ * @return {@code true} if the layout direction change has caused the
+ * appearance of the drawable to change such that it needs to be
+ * re-drawn, {@code false} otherwise
* @see #getLayoutDirection()
*/
public final boolean setLayoutDirection(@View.ResolvedLayoutDir int layoutDirection) {
@@ -455,8 +502,9 @@
* Called when the drawable's resolved layout direction changes.
*
* @param layoutDirection the new resolved layout direction
- * @return true if the layout direction change has caused the appearance of
- * the drawable to change and it needs to be re-drawn
+ * @return {@code true} if the layout direction change has caused the
+ * appearance of the drawable to change such that it needs to be
+ * re-drawn, {@code false} otherwise
* @see #setLayoutDirection(int)
*/
public boolean onLayoutDirectionChanged(@View.ResolvedLayoutDir int layoutDirection) {
@@ -467,7 +515,7 @@
* Specify an alpha value for the drawable. 0 means fully transparent, and
* 255 means fully opaque.
*/
- public abstract void setAlpha(int alpha);
+ public abstract void setAlpha(@IntRange(from=0,to=255) int alpha);
/**
* Gets the current alpha value for the drawable. 0 means fully transparent,
@@ -476,6 +524,7 @@
* The default return value is 255 if the class does not override this method to return a value
* specific to its use of alpha.
*/
+ @IntRange(from=0,to=255)
public int getAlpha() {
return 0xFF;
}
@@ -489,7 +538,7 @@
* Drawables draw is private implementation detail, and not something apps
* should rely upon.
*/
- public void setXfermode(Xfermode mode) {
+ public void setXfermode(@Nullable Xfermode mode) {
// Base implementation drops it on the floor for compatibility. Whee!
}
@@ -592,7 +641,7 @@
*
* @return the current color filter, or {@code null} if none set
*/
- public ColorFilter getColorFilter() {
+ public @Nullable ColorFilter getColorFilter() {
return null;
}
@@ -629,7 +678,7 @@
* @param outRect the rect to populate with the hotspot bounds
* @see #setHotspotBounds(int, int, int, int)
*/
- public void getHotspotBounds(Rect outRect) {
+ public void getHotspotBounds(@NonNull Rect outRect) {
outRect.set(getBounds());
}
@@ -677,7 +726,7 @@
* of the Drawable to change (hence requiring an invalidate), otherwise
* returns false.
*/
- public boolean setState(final int[] stateSet) {
+ public boolean setState(@NonNull final int[] stateSet) {
if (!Arrays.equals(mStateSet, stateSet)) {
mStateSet = stateSet;
return onStateChange(stateSet);
@@ -692,7 +741,7 @@
* Some drawables may modify their imagery based on the selected state.
* @return An array of resource Ids describing the current state.
*/
- public int[] getState() {
+ public @NonNull int[] getState() {
return mStateSet;
}
@@ -709,7 +758,7 @@
* {@link StateListDrawable} and {@link LevelListDrawable} this will be the child drawable
* currently in use.
*/
- public Drawable getCurrent() {
+ public @NonNull Drawable getCurrent() {
return this;
}
@@ -729,7 +778,7 @@
* of the Drawable to change (hence requiring an invalidate), otherwise
* returns false.
*/
- public final boolean setLevel(int level) {
+ public final boolean setLevel(@IntRange(from=0,to=10000) int level) {
if (mLevel != level) {
mLevel = level;
return onLevelChange(level);
@@ -742,7 +791,7 @@
*
* @return int Current level, from 0 (minimum) to 10000 (maximum).
*/
- public final int getLevel() {
+ public final @IntRange(from=0,to=10000) int getLevel() {
return mLevel;
}
@@ -839,7 +888,7 @@
*
* @see android.graphics.PixelFormat
*/
- public abstract int getOpacity();
+ public abstract @PixelFormat.Opacity int getOpacity();
/**
* Return the appropriate opacity value for two source opacities. If
@@ -856,7 +905,8 @@
*
* @see #getOpacity
*/
- public static int resolveOpacity(int op1, int op2) {
+ public static @PixelFormat.Opacity int resolveOpacity(@PixelFormat.Opacity int op1,
+ @PixelFormat.Opacity int op2) {
if (op1 == op2) {
return op1;
}
@@ -885,7 +935,7 @@
* report, else a Region holding the parts of the Drawable's bounds that
* are transparent.
*/
- public Region getTransparentRegion() {
+ public @Nullable Region getTransparentRegion() {
return null;
}
@@ -898,7 +948,10 @@
* if it looks the same and there is no need to redraw it since its
* last state.
*/
- protected boolean onStateChange(int[] state) { return false; }
+ protected boolean onStateChange(int[] state) {
+ return false;
+ }
+
/** Override this in your subclass to change appearance if you vary based
* on level.
* @return Returns true if the level change has caused the appearance of
@@ -906,12 +959,17 @@
* if it looks the same and there is no need to redraw it since its
* last level.
*/
- protected boolean onLevelChange(int level) { return false; }
+ protected boolean onLevelChange(int level) {
+ return false;
+ }
+
/**
* Override this in your subclass to change appearance if you vary based on
* the bounds.
*/
- protected void onBoundsChange(Rect bounds) {}
+ protected void onBoundsChange(Rect bounds) {
+ // Stub method.
+ }
/**
* Returns the drawable's intrinsic width.
@@ -986,7 +1044,7 @@
*
* @hide
*/
- public Insets getOpticalInsets() {
+ public @NonNull Insets getOpticalInsets() {
return Insets.NONE;
}
@@ -1020,7 +1078,7 @@
* @see ConstantState
* @see #getConstantState()
*/
- public Drawable mutate() {
+ public @NonNull Drawable mutate() {
return this;
}
@@ -1126,9 +1184,10 @@
AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
- while ((type=parser.next()) != XmlPullParser.START_TAG &&
- type != XmlPullParser.END_DOCUMENT) {
- // Empty loop
+ //noinspection StatementWithEmptyBody
+ while ((type=parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // Empty loop.
}
if (type != XmlPullParser.START_TAG) {
@@ -1222,8 +1281,9 @@
* @throws XmlPullParserException
* @throws IOException
*/
- void inflateWithAttributes(@NonNull Resources r, @NonNull XmlPullParser parser,
- @NonNull TypedArray attrs, int visibleAttr) throws XmlPullParserException, IOException {
+ void inflateWithAttributes(@NonNull @SuppressWarnings("unused") Resources r,
+ @NonNull @SuppressWarnings("unused") XmlPullParser parser, @NonNull TypedArray attrs,
+ @AttrRes int visibleAttr) throws XmlPullParserException, IOException {
mVisible = attrs.getBoolean(visibleAttr, mVisible);
}
@@ -1254,8 +1314,7 @@
* @return a new drawable object based on this constant state
* @see {@link #newDrawable(Resources)}
*/
- @NonNull
- public abstract Drawable newDrawable();
+ public abstract @NonNull Drawable newDrawable();
/**
* Creates a new Drawable instance from its constant state using the
@@ -1269,8 +1328,7 @@
* be displayed
* @return a new drawable object based on this constant state
*/
- @NonNull
- public Drawable newDrawable(@Nullable Resources res) {
+ public @NonNull Drawable newDrawable(@Nullable Resources res) {
return newDrawable();
}
@@ -1288,8 +1346,8 @@
* displayed
* @return a new drawable object based on this constant state
*/
- @NonNull
- public Drawable newDrawable(@Nullable Resources res, @Nullable Theme theme) {
+ public @NonNull Drawable newDrawable(@Nullable Resources res,
+ @Nullable @SuppressWarnings("unused") Theme theme) {
return newDrawable(res);
}
@@ -1303,12 +1361,12 @@
* @return Total pixel count
* @hide
*/
- public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
+ public int addAtlasableBitmaps(@NonNull Collection<Bitmap> atlasList) {
return 0;
}
/** @hide */
- protected final boolean isAtlasable(Bitmap bitmap) {
+ protected final boolean isAtlasable(@Nullable Bitmap bitmap) {
return bitmap != null && bitmap.getConfig() == Bitmap.Config.ARGB_8888;
}
@@ -1327,7 +1385,7 @@
* @see ConstantState
* @see Drawable#mutate()
*/
- public ConstantState getConstantState() {
+ public @Nullable ConstantState getConstantState() {
return null;
}
@@ -1345,8 +1403,8 @@
* Ensures the tint filter is consistent with the current tint color and
* mode.
*/
- PorterDuffColorFilter updateTintFilter(PorterDuffColorFilter tintFilter, ColorStateList tint,
- PorterDuff.Mode tintMode) {
+ @Nullable PorterDuffColorFilter updateTintFilter(@Nullable PorterDuffColorFilter tintFilter,
+ @Nullable ColorStateList tint, @Nullable PorterDuff.Mode tintMode) {
if (tint == null || tintMode == null) {
return null;
}
@@ -1365,8 +1423,8 @@
* Obtains styled attributes from the theme, if available, or unstyled
* resources if the theme is null.
*/
- static TypedArray obtainAttributes(
- Resources res, Theme theme, AttributeSet set, int[] attrs) {
+ static @NonNull TypedArray obtainAttributes(@NonNull Resources res, @Nullable Theme theme,
+ @NonNull AttributeSet set, @NonNull int[] attrs) {
if (theme == null) {
return res.obtainAttributes(set, attrs);
}
@@ -1418,8 +1476,6 @@
final int rounded = Math.round(result);
if (rounded != 0) {
return rounded;
- } else if (pixels == 0) {
- return 0;
} else if (pixels > 0) {
return 1;
} else {
@@ -1440,7 +1496,7 @@
* @param cause the exception to re-throw
* @throws RuntimeException
*/
- static void rethrowAsRuntimeException(Exception cause) throws RuntimeException {
+ static void rethrowAsRuntimeException(@NonNull Exception cause) throws RuntimeException {
final RuntimeException e = new RuntimeException(cause);
e.setStackTrace(new StackTraceElement[0]);
throw e;
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index e75fb98..0e45780 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -534,13 +534,17 @@
public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
@NonNull AttributeSet attrs, @Nullable Theme theme)
throws XmlPullParserException, IOException {
- if (mVectorState.mRootGroup != null || mVectorState.mNativeRendererRefBase != null) {
+ if (mVectorState.mRootGroup != null || mVectorState.mNativeTree != null) {
// This VD has been used to display other VD resource content, clean up.
- mVectorState.mRootGroup = new VGroup();
- if (mVectorState.mNativeRendererRefBase != null) {
- mVectorState.mNativeRendererRefBase.release();
+ if (mVectorState.mRootGroup != null) {
+ // Remove child nodes' reference to tree
+ mVectorState.mRootGroup.setTree(null);
}
- mVectorState.createNativeRenderer(mVectorState.mRootGroup.mNativePtr);
+ mVectorState.mRootGroup = new VGroup();
+ if (mVectorState.mNativeTree != null) {
+ mVectorState.mNativeTree.release();
+ }
+ mVectorState.createNativeTree(mVectorState.mRootGroup);
}
final VectorDrawableState state = mVectorState;
state.setDensity(Drawable.resolveDensity(r, 0));
@@ -734,7 +738,7 @@
Insets mOpticalInsets = Insets.NONE;
String mRootName = null;
VGroup mRootGroup;
- VirtualRefBasePtr mNativeRendererRefBase = null;
+ VirtualRefBasePtr mNativeTree = null;
int mDensity = DisplayMetrics.DENSITY_DEFAULT;
final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<>();
@@ -755,7 +759,7 @@
mTintMode = copy.mTintMode;
mAutoMirrored = copy.mAutoMirrored;
mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
- createNativeRenderer(mRootGroup.mNativePtr);
+ createNativeTree(mRootGroup);
mBaseWidth = copy.mBaseWidth;
mBaseHeight = copy.mBaseHeight;
@@ -770,15 +774,16 @@
}
}
- private void createNativeRenderer(long rootGroupPtr) {
- mNativeRendererRefBase = new VirtualRefBasePtr(nCreateRenderer(rootGroupPtr));
+ private void createNativeTree(VGroup rootGroup) {
+ mNativeTree = new VirtualRefBasePtr(nCreateTree(rootGroup.mNativePtr));
+ mRootGroup.setTree(mNativeTree);
}
long getNativeRenderer() {
- if (mNativeRendererRefBase == null) {
+ if (mNativeTree == null) {
return 0;
}
- return mNativeRendererRefBase.get();
+ return mNativeTree.get();
}
public boolean canReuseCache() {
@@ -817,7 +822,7 @@
public VectorDrawableState() {
mRootGroup = new VGroup();
- createNativeRenderer(mRootGroup.mNativePtr);
+ createNativeTree(mRootGroup);
}
@Override
@@ -881,16 +886,16 @@
* has changed.
*/
public boolean setAlpha(float alpha) {
- return nSetRootAlpha(mNativeRendererRefBase.get(), alpha);
+ return nSetRootAlpha(mNativeTree.get(), alpha);
}
@SuppressWarnings("unused")
public float getAlpha() {
- return nGetRootAlpha(mNativeRendererRefBase.get());
+ return nGetRootAlpha(mNativeTree.get());
}
}
- static class VGroup implements VObject {
+ static class VGroup extends VObject {
private static final int ROTATE_INDEX = 0;
private static final int PIVOT_X_INDEX = 1;
private static final int PIVOT_Y_INDEX = 2;
@@ -984,11 +989,18 @@
public void addChild(VObject child) {
nAddChild(mNativePtr, child.getNativePtr());
mChildren.add(child);
-
mIsStateful |= child.isStateful();
}
@Override
+ public void setTree(VirtualRefBasePtr treeRoot) {
+ super.setTree(treeRoot);
+ for (int i = 0; i < mChildren.size(); i++) {
+ mChildren.get(i).setTree(treeRoot);
+ }
+ }
+
+ @Override
public long getNativePtr() {
return mNativePtr;
}
@@ -1101,79 +1113,93 @@
/* Setters and Getters, used by animator from AnimatedVectorDrawable. */
@SuppressWarnings("unused")
public float getRotation() {
- return nGetRotation(mNativePtr);
+ return isTreeValid() ? nGetRotation(mNativePtr) : 0;
}
@SuppressWarnings("unused")
public void setRotation(float rotation) {
- nSetRotation(mNativePtr, rotation);
+ if (isTreeValid()) {
+ nSetRotation(mNativePtr, rotation);
+ }
}
@SuppressWarnings("unused")
public float getPivotX() {
- return nGetPivotX(mNativePtr);
+ return isTreeValid() ? nGetPivotX(mNativePtr) : 0;
}
@SuppressWarnings("unused")
public void setPivotX(float pivotX) {
- nSetPivotX(mNativePtr, pivotX);
+ if (isTreeValid()) {
+ nSetPivotX(mNativePtr, pivotX);
+ }
}
@SuppressWarnings("unused")
public float getPivotY() {
- return nGetPivotY(mNativePtr);
+ return isTreeValid() ? nGetPivotY(mNativePtr) : 0;
}
@SuppressWarnings("unused")
public void setPivotY(float pivotY) {
- nSetPivotY(mNativePtr, pivotY);
+ if (isTreeValid()) {
+ nSetPivotY(mNativePtr, pivotY);
+ }
}
@SuppressWarnings("unused")
public float getScaleX() {
- return nGetScaleX(mNativePtr);
+ return isTreeValid() ? nGetScaleX(mNativePtr) : 0;
}
@SuppressWarnings("unused")
public void setScaleX(float scaleX) {
- nSetScaleX(mNativePtr, scaleX);
+ if (isTreeValid()) {
+ nSetScaleX(mNativePtr, scaleX);
+ }
}
@SuppressWarnings("unused")
public float getScaleY() {
- return nGetScaleY(mNativePtr);
+ return isTreeValid() ? nGetScaleY(mNativePtr) : 0;
}
@SuppressWarnings("unused")
public void setScaleY(float scaleY) {
- nSetScaleY(mNativePtr, scaleY);
+ if (isTreeValid()) {
+ nSetScaleY(mNativePtr, scaleY);
+ }
}
@SuppressWarnings("unused")
public float getTranslateX() {
- return nGetTranslateX(mNativePtr);
+ return isTreeValid() ? nGetTranslateX(mNativePtr) : 0;
}
@SuppressWarnings("unused")
public void setTranslateX(float translateX) {
- nSetTranslateX(mNativePtr, translateX);
+ if (isTreeValid()) {
+ nSetTranslateX(mNativePtr, translateX);
+ }
}
@SuppressWarnings("unused")
public float getTranslateY() {
- return nGetTranslateY(mNativePtr);
+ return isTreeValid() ? nGetTranslateY(mNativePtr) : 0;
}
@SuppressWarnings("unused")
public void setTranslateY(float translateY) {
- nSetTranslateY(mNativePtr, translateY);
+ if (isTreeValid()) {
+ nSetTranslateY(mNativePtr, translateY);
+ }
}
}
/**
* Common Path information for clip path and normal path.
*/
- static abstract class VPath implements VObject {
+ static abstract class VPath extends VObject {
protected PathParser.PathData mPathData = null;
String mPathName;
@@ -1203,7 +1229,9 @@
@SuppressWarnings("unused")
public void setPathData(PathParser.PathData pathData) {
mPathData.setPathData(pathData);
- nSetPathData(getNativePtr(), mPathData.getNativePtr());
+ if (isTreeValid()) {
+ nSetPathData(getNativePtr(), mPathData.getNativePtr());
+ }
}
}
@@ -1549,97 +1577,120 @@
/* Setters and Getters, used by animator from AnimatedVectorDrawable. */
@SuppressWarnings("unused")
int getStrokeColor() {
- return nGetStrokeColor(mNativePtr);
+ return isTreeValid() ? nGetStrokeColor(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setStrokeColor(int strokeColor) {
mStrokeColors = null;
- nSetStrokeColor(mNativePtr, strokeColor);
+ if (isTreeValid()) {
+ nSetStrokeColor(mNativePtr, strokeColor);
+ }
}
@SuppressWarnings("unused")
float getStrokeWidth() {
- return nGetStrokeWidth(mNativePtr);
+ return isTreeValid() ? nGetStrokeWidth(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setStrokeWidth(float strokeWidth) {
- nSetStrokeWidth(mNativePtr, strokeWidth);
+ if (isTreeValid()) {
+ nSetStrokeWidth(mNativePtr, strokeWidth);
+ }
}
@SuppressWarnings("unused")
float getStrokeAlpha() {
- return nGetStrokeAlpha(mNativePtr);
+ return isTreeValid() ? nGetStrokeAlpha(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setStrokeAlpha(float strokeAlpha) {
- nSetStrokeAlpha(mNativePtr, strokeAlpha);
+ if (isTreeValid()) {
+ nSetStrokeAlpha(mNativePtr, strokeAlpha);
+ }
}
@SuppressWarnings("unused")
int getFillColor() {
- return nGetFillColor(mNativePtr);
+ return isTreeValid() ? nGetFillColor(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setFillColor(int fillColor) {
mFillColors = null;
- nSetFillColor(mNativePtr, fillColor);
+ if (isTreeValid()) {
+ nSetFillColor(mNativePtr, fillColor);
+ }
}
@SuppressWarnings("unused")
float getFillAlpha() {
- return nGetFillAlpha(mNativePtr);
+ return isTreeValid() ? nGetFillAlpha(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setFillAlpha(float fillAlpha) {
- nSetFillAlpha(mNativePtr, fillAlpha);
+ if (isTreeValid()) {
+ nSetFillAlpha(mNativePtr, fillAlpha);
+ }
}
@SuppressWarnings("unused")
float getTrimPathStart() {
- return nGetTrimPathStart(mNativePtr);
+ return isTreeValid() ? nGetTrimPathStart(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setTrimPathStart(float trimPathStart) {
- nSetTrimPathStart(mNativePtr, trimPathStart);
+ if (isTreeValid()) {
+ nSetTrimPathStart(mNativePtr, trimPathStart);
+ }
}
@SuppressWarnings("unused")
float getTrimPathEnd() {
- return nGetTrimPathEnd(mNativePtr);
+ return isTreeValid() ? nGetTrimPathEnd(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setTrimPathEnd(float trimPathEnd) {
- nSetTrimPathEnd(mNativePtr, trimPathEnd);
+ if (isTreeValid()) {
+ nSetTrimPathEnd(mNativePtr, trimPathEnd);
+ }
}
@SuppressWarnings("unused")
float getTrimPathOffset() {
- return nGetTrimPathOffset(mNativePtr);
+ return isTreeValid() ? nGetTrimPathOffset(mNativePtr) : 0;
}
@SuppressWarnings("unused")
void setTrimPathOffset(float trimPathOffset) {
- nSetTrimPathOffset(mNativePtr, trimPathOffset);
+ if (isTreeValid()) {
+ nSetTrimPathOffset(mNativePtr, trimPathOffset);
+ }
}
}
- interface VObject {
- long getNativePtr();
- void inflate(Resources r, AttributeSet attrs, Theme theme);
- boolean canApplyTheme();
- void applyTheme(Theme t);
- boolean onStateChange(int[] state);
- boolean isStateful();
+ abstract static class VObject {
+ VirtualRefBasePtr mTreePtr = null;
+ boolean isTreeValid() {
+ return mTreePtr != null && mTreePtr.get() != 0;
+ }
+ void setTree(VirtualRefBasePtr ptr) {
+ mTreePtr = ptr;
+ }
+ abstract long getNativePtr();
+ abstract void inflate(Resources r, AttributeSet attrs, Theme theme);
+ abstract boolean canApplyTheme();
+ abstract void applyTheme(Theme t);
+ abstract boolean onStateChange(int[] state);
+ abstract boolean isStateful();
}
- private static native long nCreateRenderer(long rootGroupPtr);
+ private static native long nCreateTree(long rootGroupPtr);
private static native void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
float viewportHeight);
private static native boolean nSetRootAlpha(long rendererPtr, float alpha);
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 0606b0b..717a1e6 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -84,6 +84,7 @@
Properties.cpp \
PropertyValuesHolder.cpp \
PropertyValuesAnimatorSet.cpp \
+ Readback.cpp \
RenderBufferCache.cpp \
RenderNode.cpp \
RenderProperties.cpp \
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index bd71e0d..4d65782 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -226,7 +226,7 @@
// Set to 0 so that the animate() basically instantly finishes
mStartTime = 0;
}
- if (mDuration < 0 || mDuration > 50000) {
+ if (mDuration < 0) {
ALOGW("Your duration is strange and confusing: %" PRId64, mDuration);
}
}
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index 35fe06d..fe68239 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -253,7 +253,9 @@
path.transform(skTransform, &transformed);
SkRegion region;
regionFromPath(transformed, region);
- clipRegion(region, op);
+ enterRegionMode();
+ mClipRegion.op(region, op);
+ onClipRegionUpdated();
}
/*
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index e209e2a..aba5d4b 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -137,6 +137,9 @@
// whether children with non-zero Z in the chunk should be reordered
bool reorderChildren;
+#if HWUI_NEW_OPS
+ const ClipBase* reorderClip;
+#endif
};
DisplayList();
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index f12e523..6fc74a5 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -269,7 +269,8 @@
}
template <typename V>
-void FrameBuilder::defer3dChildren(ChildrenSelectMode mode, const V& zTranslatedNodes) {
+void FrameBuilder::defer3dChildren(const ClipBase* reorderClip, ChildrenSelectMode mode,
+ const V& zTranslatedNodes) {
const int size = zTranslatedNodes.size();
if (size == 0
|| (mode == ChildrenSelectMode::Negative&& zTranslatedNodes[0].key > 0.0f)
@@ -305,7 +306,7 @@
// attempt to render the shadow if the caster about to be drawn is its caster,
// OR if its caster's Z value is similar to the previous potential caster
if (shadowIndex == drawIndex || casterZ - lastCasterZ < 0.1f) {
- deferShadow(*casterNodeOp);
+ deferShadow(reorderClip, *casterNodeOp);
lastCasterZ = casterZ; // must do this even if current caster not casting a shadow
shadowIndex++;
@@ -319,7 +320,7 @@
}
}
-void FrameBuilder::deferShadow(const RenderNodeOp& casterNodeOp) {
+void FrameBuilder::deferShadow(const ClipBase* reorderClip, const RenderNodeOp& casterNodeOp) {
auto& node = *casterNodeOp.renderNode;
auto& properties = node.properties();
@@ -365,6 +366,10 @@
casterPath = frameAllocatedPath;
}
+ // apply reorder clip to shadow, so it respects clip at beginning of reorderable chunk
+ int restoreTo = mCanvasState.save(SaveFlags::MatrixClip);
+ mCanvasState.writableSnapshot()->applyClip(reorderClip,
+ *mCanvasState.currentSnapshot()->transform);
if (CC_LIKELY(!mCanvasState.getRenderTargetClipBounds().isEmpty())) {
Matrix4 shadowMatrixXY(casterNodeOp.localMatrix);
Matrix4 shadowMatrixZ(casterNodeOp.localMatrix);
@@ -386,6 +391,7 @@
currentLayer().deferUnmergeableOp(mAllocator, bakedOpState, OpBatchType::Shadow);
}
}
+ mCanvasState.restoreToCount(restoreTo);
}
void FrameBuilder::deferProjectedChildren(const RenderNode& renderNode) {
@@ -438,11 +444,11 @@
// can't be null, since DL=null node rejection happens before deferNodePropsAndOps
const DisplayList& displayList = *(renderNode.getDisplayList());
- for (const DisplayList::Chunk& chunk : displayList.getChunks()) {
+ for (auto& chunk : displayList.getChunks()) {
FatVector<ZRenderNodeOpPair, 16> zTranslatedNodes;
buildZSortedChildList(&zTranslatedNodes, displayList, chunk);
- defer3dChildren(ChildrenSelectMode::Negative, zTranslatedNodes);
+ defer3dChildren(chunk.reorderClip, ChildrenSelectMode::Negative, zTranslatedNodes);
for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
const RecordedOp* op = displayList.getOps()[opIndex];
receivers[op->opId](*this, *op);
@@ -453,7 +459,7 @@
deferProjectedChildren(renderNode);
}
}
- defer3dChildren(ChildrenSelectMode::Positive, zTranslatedNodes);
+ defer3dChildren(chunk.reorderClip, ChildrenSelectMode::Positive, zTranslatedNodes);
}
}
diff --git a/libs/hwui/FrameBuilder.h b/libs/hwui/FrameBuilder.h
index 039ab6b..a6fd761 100644
--- a/libs/hwui/FrameBuilder.h
+++ b/libs/hwui/FrameBuilder.h
@@ -193,9 +193,10 @@
void deferNodePropsAndOps(RenderNode& node);
template <typename V>
- void defer3dChildren(ChildrenSelectMode mode, const V& zTranslatedNodes);
+ void defer3dChildren(const ClipBase* reorderClip, ChildrenSelectMode mode,
+ const V& zTranslatedNodes);
- void deferShadow(const RenderNodeOp& casterOp);
+ void deferShadow(const ClipBase* reorderClip, const RenderNodeOp& casterOp);
void deferProjectedChildren(const RenderNode& renderNode);
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index d1ff670..9d4eccc 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -285,6 +285,7 @@
void JankTracker::reset() {
mData->jankTypeCounts.fill(0);
mData->frameCounts.fill(0);
+ mData->slowFrameCounts.fill(0);
mData->totalFrameCount = 0;
mData->jankFrameCount = 0;
mData->statStartTime = systemTime(CLOCK_MONOTONIC);
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 8f914ac..a8ace8c 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -19,6 +19,7 @@
#include <SkColor.h>
#include <SkPaint.h>
#include <SkPath.h>
+#include <SkPathEffect.h>
#include <SkRect.h>
#include <utils/JenkinsHash.h>
@@ -35,18 +36,34 @@
namespace android {
namespace uirenderer {
+template <class T>
+static bool compareWidthHeight(const T& lhs, const T& rhs) {
+ return (lhs.mWidth == rhs.mWidth) && (lhs.mHeight == rhs.mHeight);
+}
+
+static bool compareRoundRects(const PathDescription::Shape::RoundRect& lhs,
+ const PathDescription::Shape::RoundRect& rhs) {
+ return compareWidthHeight(lhs, rhs) && lhs.mRx == rhs.mRx && lhs.mRy == rhs.mRy;
+}
+
+static bool compareArcs(const PathDescription::Shape::Arc& lhs, const PathDescription::Shape::Arc& rhs) {
+ return compareWidthHeight(lhs, rhs) && lhs.mStartAngle == rhs.mStartAngle &&
+ lhs.mSweepAngle == rhs.mSweepAngle && lhs.mUseCenter == rhs.mUseCenter;
+}
+
///////////////////////////////////////////////////////////////////////////////
// Cache entries
///////////////////////////////////////////////////////////////////////////////
PathDescription::PathDescription()
- : type(kShapeNone)
+ : type(ShapeType::None)
, join(SkPaint::kDefault_Join)
, cap(SkPaint::kDefault_Cap)
, style(SkPaint::kFill_Style)
, miter(4.0f)
, strokeWidth(1.0f)
, pathEffect(nullptr) {
+ // Shape bits should be set to zeroes, because they are used for hash calculation.
memset(&shape, 0, sizeof(Shape));
}
@@ -58,11 +75,12 @@
, miter(paint->getStrokeMiter())
, strokeWidth(paint->getStrokeWidth())
, pathEffect(paint->getPathEffect()) {
+ // Shape bits should be set to zeroes, because they are used for hash calculation.
memset(&shape, 0, sizeof(Shape));
}
hash_t PathDescription::hash() const {
- uint32_t hash = JenkinsHashMix(0, type);
+ uint32_t hash = JenkinsHashMix(0, static_cast<int>(type));
hash = JenkinsHashMix(hash, join);
hash = JenkinsHashMix(hash, cap);
hash = JenkinsHashMix(hash, style);
@@ -73,6 +91,32 @@
return JenkinsHashWhiten(hash);
}
+bool PathDescription::operator==(const PathDescription& rhs) const {
+ if (type != rhs.type) return false;
+ if (join != rhs.join) return false;
+ if (cap != rhs.cap) return false;
+ if (style != rhs.style) return false;
+ if (miter != rhs.miter) return false;
+ if (strokeWidth != rhs.strokeWidth) return false;
+ if (pathEffect != rhs.pathEffect) return false;
+ switch (type) {
+ case ShapeType::None:
+ return 0;
+ case ShapeType::Rect:
+ return compareWidthHeight(shape.rect, rhs.shape.rect);
+ case ShapeType::RoundRect:
+ return compareRoundRects(shape.roundRect, rhs.shape.roundRect);
+ case ShapeType::Circle:
+ return shape.circle.mRadius == rhs.shape.circle.mRadius;
+ case ShapeType::Oval:
+ return compareWidthHeight(shape.oval, rhs.shape.oval);
+ case ShapeType::Arc:
+ return compareArcs(shape.arc, rhs.shape.arc);
+ case ShapeType::Path:
+ return shape.path.mGenerationID == rhs.shape.path.mGenerationID;
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// Utilities
///////////////////////////////////////////////////////////////////////////////
@@ -322,7 +366,7 @@
LruCache<PathDescription, PathTexture*>::Iterator iter(mCache);
while (iter.next()) {
const PathDescription& key = iter.key();
- if (key.type == kShapePath && key.shape.path.mGenerationID == generationID) {
+ if (key.type == ShapeType::Path && key.shape.path.mGenerationID == generationID) {
pathsToRemove.push(key);
}
}
@@ -336,7 +380,7 @@
}
PathTexture* PathCache::get(const SkPath* path, const SkPaint* paint) {
- PathDescription entry(kShapePath, paint);
+ PathDescription entry(ShapeType::Path, paint);
entry.shape.path.mGenerationID = path->getGenerationID();
PathTexture* texture = mCache.get(entry);
@@ -366,9 +410,8 @@
return texture;
}
-void PathCache::remove(const SkPath* path, const SkPaint* paint)
-{
- PathDescription entry(kShapePath, paint);
+void PathCache::remove(const SkPath* path, const SkPaint* paint) {
+ PathDescription entry(ShapeType::Path, paint);
entry.shape.path.mGenerationID = path->getGenerationID();
mCache.remove(entry);
}
@@ -378,7 +421,7 @@
return;
}
- PathDescription entry(kShapePath, paint);
+ PathDescription entry(ShapeType::Path, paint);
entry.shape.path.mGenerationID = path->getGenerationID();
PathTexture* texture = mCache.get(entry);
@@ -417,7 +460,7 @@
PathTexture* PathCache::getRoundRect(float width, float height,
float rx, float ry, const SkPaint* paint) {
- PathDescription entry(kShapeRoundRect, paint);
+ PathDescription entry(ShapeType::RoundRect, paint);
entry.shape.roundRect.mWidth = width;
entry.shape.roundRect.mHeight = height;
entry.shape.roundRect.mRx = rx;
@@ -442,7 +485,7 @@
///////////////////////////////////////////////////////////////////////////////
PathTexture* PathCache::getCircle(float radius, const SkPaint* paint) {
- PathDescription entry(kShapeCircle, paint);
+ PathDescription entry(ShapeType::Circle, paint);
entry.shape.circle.mRadius = radius;
PathTexture* texture = get(entry);
@@ -462,7 +505,7 @@
///////////////////////////////////////////////////////////////////////////////
PathTexture* PathCache::getOval(float width, float height, const SkPaint* paint) {
- PathDescription entry(kShapeOval, paint);
+ PathDescription entry(ShapeType::Oval, paint);
entry.shape.oval.mWidth = width;
entry.shape.oval.mHeight = height;
@@ -485,7 +528,7 @@
///////////////////////////////////////////////////////////////////////////////
PathTexture* PathCache::getRect(float width, float height, const SkPaint* paint) {
- PathDescription entry(kShapeRect, paint);
+ PathDescription entry(ShapeType::Rect, paint);
entry.shape.rect.mWidth = width;
entry.shape.rect.mHeight = height;
@@ -509,7 +552,7 @@
PathTexture* PathCache::getArc(float width, float height,
float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) {
- PathDescription entry(kShapeArc, paint);
+ PathDescription entry(ShapeType::Arc, paint);
entry.shape.arc.mWidth = width;
entry.shape.arc.mHeight = height;
entry.shape.arc.mStartAngle = startAngle;
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index d2633aa..6368ddd 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -25,6 +25,7 @@
#include "utils/Pair.h"
#include <GLES2/gl2.h>
+#include <SkPaint.h>
#include <SkPath.h>
#include <utils/LruCache.h>
#include <utils/Mutex.h>
@@ -108,18 +109,18 @@
sp<Task<SkBitmap*> > mTask;
}; // struct PathTexture
-enum ShapeType {
- kShapeNone,
- kShapeRect,
- kShapeRoundRect,
- kShapeCircle,
- kShapeOval,
- kShapeArc,
- kShapePath
+enum class ShapeType {
+ None,
+ Rect,
+ RoundRect,
+ Circle,
+ Oval,
+ Arc,
+ Path
};
struct PathDescription {
- DESCRIPTION_TYPE(PathDescription);
+ HASHABLE_TYPE(PathDescription);
ShapeType type;
SkPaint::Join join;
SkPaint::Cap cap;
@@ -159,8 +160,6 @@
PathDescription();
PathDescription(ShapeType shapeType, const SkPaint* paint);
-
- hash_t hash() const;
};
/**
diff --git a/libs/hwui/PathParser.cpp b/libs/hwui/PathParser.cpp
index 7e85333..2179f14 100644
--- a/libs/hwui/PathParser.cpp
+++ b/libs/hwui/PathParser.cpp
@@ -162,7 +162,7 @@
|| verb == 's' || verb == 't' || verb == 'v' || verb == 'z';
}
-void PathParser::getPathDataFromString(PathData* data, ParseResult* result,
+void PathParser::getPathDataFromAsciiString(PathData* data, ParseResult* result,
const char* pathStr, size_t strLen) {
if (pathStr == NULL) {
result->failureOccurred = true;
@@ -171,7 +171,16 @@
}
size_t start = 0;
- size_t end = 1;
+ // Skip leading spaces.
+ while (isspace(pathStr[start]) && start < strLen) {
+ start++;
+ }
+ if (start == strLen) {
+ result->failureOccurred = true;
+ result->failureMessage = "Path string cannot be empty.";
+ return;
+ }
+ size_t end = start + 1;
while (end < strLen) {
end = nextStart(pathStr, strLen, end);
@@ -226,9 +235,9 @@
ALOGD("points are : %s", os.str().c_str());
}
-void PathParser::parseStringForSkPath(SkPath* skPath, ParseResult* result, const char* pathStr, size_t strLen) {
+void PathParser::parseAsciiStringForSkPath(SkPath* skPath, ParseResult* result, const char* pathStr, size_t strLen) {
PathData pathData;
- getPathDataFromString(&pathData, result, pathStr, strLen);
+ getPathDataFromAsciiString(&pathData, result, pathStr, strLen);
if (result->failureOccurred) {
return;
}
diff --git a/libs/hwui/PathParser.h b/libs/hwui/PathParser.h
index 180a7a3..5578e8d 100644
--- a/libs/hwui/PathParser.h
+++ b/libs/hwui/PathParser.h
@@ -39,9 +39,9 @@
/**
* Parse the string literal and create a Skia Path. Return true on success.
*/
- ANDROID_API static void parseStringForSkPath(SkPath* outPath, ParseResult* result,
+ ANDROID_API static void parseAsciiStringForSkPath(SkPath* outPath, ParseResult* result,
const char* pathStr, size_t strLength);
- ANDROID_API static void getPathDataFromString(PathData* outData, ParseResult* result,
+ ANDROID_API static void getPathDataFromAsciiString(PathData* outData, ParseResult* result,
const char* pathStr, size_t strLength);
static void dump(const PathData& data);
static bool isVerbValid(char verb);
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
new file mode 100644
index 0000000..d7df77c
--- /dev/null
+++ b/libs/hwui/Readback.cpp
@@ -0,0 +1,159 @@
+/*
+ * 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 "Readback.h"
+
+#include "Caches.h"
+#include "Image.h"
+#include "GlopBuilder.h"
+#include "renderstate/RenderState.h"
+#include "renderthread/EglManager.h"
+#include "utils/GLUtils.h"
+
+#include <GLES2/gl2.h>
+#include <ui/Fence.h>
+#include <ui/GraphicBuffer.h>
+
+namespace android {
+namespace uirenderer {
+
+bool Readback::copySurfaceInto(renderthread::RenderThread& renderThread,
+ Surface& surface, SkBitmap* bitmap) {
+ // TODO: Clean this up and unify it with LayerRenderer::copyLayer,
+ // of which most of this is copied from.
+ renderThread.eglManager().initialize();
+
+ Caches& caches = Caches::getInstance();
+ RenderState& renderState = renderThread.renderState();
+ int destWidth = bitmap->width();
+ int destHeight = bitmap->height();
+ if (destWidth > caches.maxTextureSize
+ || destHeight > caches.maxTextureSize) {
+ ALOGW("Can't copy surface into bitmap, %dx%d exceeds max texture size %d",
+ destWidth, destHeight, caches.maxTextureSize);
+ return false;
+ }
+ GLuint fbo = renderState.createFramebuffer();
+ if (!fbo) {
+ ALOGW("Could not obtain an FBO");
+ return false;
+ }
+
+ SkAutoLockPixels alp(*bitmap);
+
+ GLuint texture;
+
+ GLenum format;
+ GLenum type;
+
+ switch (bitmap->colorType()) {
+ case kAlpha_8_SkColorType:
+ format = GL_ALPHA;
+ type = GL_UNSIGNED_BYTE;
+ break;
+ case kRGB_565_SkColorType:
+ format = GL_RGB;
+ type = GL_UNSIGNED_SHORT_5_6_5;
+ break;
+ case kARGB_4444_SkColorType:
+ format = GL_RGBA;
+ type = GL_UNSIGNED_SHORT_4_4_4_4;
+ break;
+ case kN32_SkColorType:
+ default:
+ format = GL_RGBA;
+ type = GL_UNSIGNED_BYTE;
+ break;
+ }
+
+ renderState.bindFramebuffer(fbo);
+
+ // TODO: Use layerPool or something to get this maybe? But since we
+ // need explicit format control we can't currently.
+
+ // Setup the rendertarget
+ glGenTextures(1, &texture);
+ caches.textureState().activateTexture(0);
+ caches.textureState().bindTexture(texture);
+ glPixelStorei(GL_PACK_ALIGNMENT, bitmap->bytesPerPixel());
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexImage2D(GL_TEXTURE_2D, 0, format, destWidth, destHeight,
+ 0, format, type, nullptr);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, texture, 0);
+
+ // Setup the source
+ sp<GraphicBuffer> sourceBuffer;
+ sp<Fence> sourceFence;
+ // FIXME: Waiting on an API from libgui for this
+ // surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence);
+ if (!sourceBuffer.get()) {
+ ALOGW("Surface doesn't have any previously queued frames, nothing to readback from");
+ return false;
+ }
+ int err = sourceFence->wait(500 /* ms */);
+ if (err != NO_ERROR) {
+ ALOGE("Timeout (500ms) exceeded waiting for buffer fence, abandoning readback attempt");
+ return false;
+ }
+ Image sourceImage(sourceBuffer);
+ if (!sourceImage.getTexture()) {
+ ALOGW("Failed to make an EGLImage from the GraphicBuffer");
+ return false;
+ }
+ Texture sourceTexture(caches);
+ sourceTexture.wrap(sourceImage.getTexture(),
+ sourceBuffer->getWidth(), sourceBuffer->getHeight(), 0 /* total lie */);
+
+ {
+ // Draw & readback
+ renderState.setViewport(destWidth, destHeight);
+ renderState.scissor().setEnabled(false);
+ renderState.blend().syncEnabled();
+ renderState.stencil().disable();
+
+ Rect destRect(destWidth, destHeight);
+ Glop glop;
+ GlopBuilder(renderState, caches, &glop)
+ .setRoundRectClipState(nullptr)
+ .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
+ .setFillLayer(sourceTexture, nullptr, 1.0f, SkXfermode::kSrc_Mode,
+ Blend::ModeOrderSwap::NoSwap)
+ .setTransform(Matrix4::identity(), TransformFlags::None)
+ .setModelViewMapUnitToRect(destRect)
+ .build();
+ Matrix4 ortho;
+ ortho.loadOrtho(destWidth, destHeight);
+ renderState.render(glop, ortho);
+
+ glReadPixels(0, 0, bitmap->width(), bitmap->height(), format,
+ type, bitmap->getPixels());
+ }
+
+ // Cleanup
+ caches.textureState().deleteTexture(texture);
+ renderState.deleteFramebuffer(fbo);
+
+ GL_CHECKPOINT(MODERATE);
+
+ return true;
+}
+
+} // namespace uirenderer
+} // namespace android
diff --git a/telephony/java/com/android/internal/telephony/TelephonyEvent.aidl b/libs/hwui/Readback.h
similarity index 63%
copy from telephony/java/com/android/internal/telephony/TelephonyEvent.aidl
copy to libs/hwui/Readback.h
index 1e74b31..ea03c82 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyEvent.aidl
+++ b/libs/hwui/Readback.h
@@ -14,6 +14,21 @@
* limitations under the License.
*/
-package com.android.internal.telephony;
+#pragma once
-parcelable TelephonyEvent;
+#include "renderthread/RenderThread.h"
+
+#include <SkBitmap.h>
+#include <gui/Surface.h>
+
+namespace android {
+namespace uirenderer {
+
+class Readback {
+public:
+ static bool copySurfaceInto(renderthread::RenderThread& renderThread,
+ Surface& surface, SkBitmap* bitmap);
+};
+
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index b78497d..ab733f1 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -57,6 +57,16 @@
return displayList;
}
+void RecordingCanvas::insertReorderBarrier(bool enableReorder) {
+ if (enableReorder) {
+ mDeferredBarrierType = DeferredBarrierType::OutOfOrder;
+ mDeferredBarrierClip = getRecordedClip();
+ } else {
+ mDeferredBarrierType = DeferredBarrierType::InOrder;
+ mDeferredBarrierClip = nullptr;
+ }
+}
+
SkCanvas* RecordingCanvas::asSkCanvas() {
LOG_ALWAYS_FATAL_IF(!mDisplayList,
"attempting to get an SkCanvas when we are not recording!");
@@ -610,6 +620,7 @@
newChunk.beginOpIndex = insertIndex;
newChunk.endOpIndex = insertIndex + 1;
newChunk.reorderChildren = (mDeferredBarrierType == DeferredBarrierType::OutOfOrder);
+ newChunk.reorderClip = mDeferredBarrierClip;
int nextChildIndex = mDisplayList->children.size();
newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index acb88e2..219296c 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -55,10 +55,7 @@
// ----------------------------------------------------------------------------
// MISC HWUI OPERATIONS - TODO: CATEGORIZE
// ----------------------------------------------------------------------------
- virtual void insertReorderBarrier(bool enableReorder) override {
- mDeferredBarrierType = enableReorder
- ? DeferredBarrierType::OutOfOrder : DeferredBarrierType::InOrder;
- }
+ virtual void insertReorderBarrier(bool enableReorder) override;
virtual void drawLayer(DeferredLayerUpdater* layerHandle) override;
virtual void drawRenderNode(RenderNode* renderNode) override;
@@ -312,6 +309,7 @@
std::unique_ptr<SkiaCanvasProxy> mSkiaCanvasProxy;
ResourceCache& mResourceCache;
DeferredBarrierType mDeferredBarrierType = DeferredBarrierType::None;
+ const ClipBase* mDeferredBarrierClip = nullptr;
DisplayList* mDisplayList = nullptr;
bool mHighContrastText = false;
SkAutoTUnref<SkDrawFilter> mDrawFilter;
diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
index 14c8f39..cfdc084 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -35,13 +35,14 @@
///////////////////////////////////////////////////////////////////////////////
TessellationCache::Description::Description()
- : type(kNone)
+ : type(Type::None)
, scaleX(1.0f)
, scaleY(1.0f)
, aa(false)
, cap(SkPaint::kDefault_Cap)
, style(SkPaint::kFill_Style)
, strokeWidth(1.0f) {
+ // Shape bits should be set to zeroes, because they are used for hash calculation.
memset(&shape, 0, sizeof(Shape));
}
@@ -52,11 +53,30 @@
, style(paint.getStyle())
, strokeWidth(paint.getStrokeWidth()) {
PathTessellator::extractTessellationScales(transform, &scaleX, &scaleY);
+ // Shape bits should be set to zeroes, because they are used for hash calculation.
memset(&shape, 0, sizeof(Shape));
}
+bool TessellationCache::Description::operator==(const TessellationCache::Description& rhs) const {
+ if (type != rhs.type) return false;
+ if (scaleX != rhs.scaleX) return false;
+ if (scaleY != rhs.scaleY) return false;
+ if (aa != rhs.aa) return false;
+ if (cap != rhs.cap) return false;
+ if (style != rhs.style) return false;
+ if (strokeWidth != rhs.strokeWidth) return false;
+ if (type == Type::None) return true;
+ const Shape::RoundRect& lRect = shape.roundRect;
+ const Shape::RoundRect& rRect = rhs.shape.roundRect;
+
+ if (lRect.width != rRect.width) return false;
+ if (lRect.height != rRect.height) return false;
+ if (lRect.rx != rRect.rx) return false;
+ return lRect.ry == rRect.ry;
+}
+
hash_t TessellationCache::Description::hash() const {
- uint32_t hash = JenkinsHashMix(0, type);
+ uint32_t hash = JenkinsHashMix(0, static_cast<int>(type));
hash = JenkinsHashMix(hash, aa);
hash = JenkinsHashMix(hash, cap);
hash = JenkinsHashMix(hash, style);
@@ -77,17 +97,23 @@
TessellationCache::ShadowDescription::ShadowDescription()
: nodeKey(nullptr) {
- memset(&matrixData, 0, 16 * sizeof(float));
+ memset(&matrixData, 0, sizeof(matrixData));
}
-TessellationCache::ShadowDescription::ShadowDescription(const void* nodeKey, const Matrix4* drawTransform)
+TessellationCache::ShadowDescription::ShadowDescription(const SkPath* nodeKey, const Matrix4* drawTransform)
: nodeKey(nodeKey) {
- memcpy(&matrixData, drawTransform->data, 16 * sizeof(float));
+ memcpy(&matrixData, drawTransform->data, sizeof(matrixData));
+}
+
+bool TessellationCache::ShadowDescription::operator==(
+ const TessellationCache::ShadowDescription& rhs) const {
+ return nodeKey == rhs.nodeKey
+ && memcmp(&matrixData, &rhs.matrixData, sizeof(matrixData)) == 0;
}
hash_t TessellationCache::ShadowDescription::hash() const {
uint32_t hash = JenkinsHashMixBytes(0, (uint8_t*) &nodeKey, sizeof(const void*));
- hash = JenkinsHashMixBytes(hash, (uint8_t*) &matrixData, 16 * sizeof(float));
+ hash = JenkinsHashMixBytes(hash, (uint8_t*) &matrixData, sizeof(matrixData));
return JenkinsHashWhiten(hash);
}
@@ -428,7 +454,7 @@
TessellationCache::Buffer* TessellationCache::getRoundRectBuffer(
const Matrix4& transform, const SkPaint& paint,
float width, float height, float rx, float ry) {
- Description entry(Description::kRoundRect, transform, paint);
+ Description entry(Description::Type::RoundRect, transform, paint);
entry.shape.roundRect.width = width;
entry.shape.roundRect.height = height;
entry.shape.roundRect.rx = rx;
diff --git a/libs/hwui/TessellationCache.h b/libs/hwui/TessellationCache.h
index 0bd6365..6141b4e 100644
--- a/libs/hwui/TessellationCache.h
+++ b/libs/hwui/TessellationCache.h
@@ -52,10 +52,10 @@
typedef Pair<VertexBuffer*, VertexBuffer*> vertexBuffer_pair_t;
struct Description {
- DESCRIPTION_TYPE(Description);
- enum Type {
- kNone,
- kRoundRect,
+ HASHABLE_TYPE(Description);
+ enum class Type {
+ None,
+ RoundRect,
};
Type type;
@@ -76,18 +76,16 @@
Description();
Description(Type type, const Matrix4& transform, const SkPaint& paint);
- hash_t hash() const;
void setupMatrixAndPaint(Matrix4* matrix, SkPaint* paint) const;
};
struct ShadowDescription {
- DESCRIPTION_TYPE(ShadowDescription);
- const void* nodeKey;
+ HASHABLE_TYPE(ShadowDescription);
+ const SkPath* nodeKey;
float matrixData[16];
ShadowDescription();
- ShadowDescription(const void* nodeKey, const Matrix4* drawTransform);
- hash_t hash() const;
+ ShadowDescription(const SkPath* nodeKey, const Matrix4* drawTransform);
};
class ShadowTask : public Task<vertexBuffer_pair_t> {
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index adfe45c..ac17ed2 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -96,7 +96,7 @@
Path::Path(const char* pathStr, size_t strLength) {
PathParser::ParseResult result;
Data data;
- PathParser::getPathDataFromString(&data, &result, pathStr, strLength);
+ PathParser::getPathDataFromAsciiString(&data, &result, pathStr, strLength);
mStagingProperties.setData(data);
}
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index e4c7ed7..691cfa0 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -40,11 +40,11 @@
namespace uirenderer {
namespace VectorDrawable {
-#define VD_SET_PROP_WITH_FLAG(field, value, flag) (VD_SET_PROP_AND_NOTIFY(field, value) ? (flag = true, true) : false)
-#define VD_SET_PROP(field, value) (value != field ? (field = value, true) : false)
-#define VD_SET_PROP_AND_NOTIFY(field, value) ({ bool retVal = VD_SET_PROP(field, value);\
+#define VD_SET_PRIMITIVE_FIELD_WITH_FLAG(field, value, flag) (VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(field, (value)) ? ((flag) = true, true) : false)
+#define VD_SET_PROP(field, value) ((value) != (field) ? ((field) = (value), true) : false)
+#define VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(field, value) ({ bool retVal = VD_SET_PROP((mPrimitiveFields.field), (value));\
onPropertyChanged(); retVal;})
-#define UPDATE_SKPROP(field, value) ({bool retVal = (field != value); if (field != value) SkRefCnt_SafeAssign(field, value); retVal;})
+#define UPDATE_SKPROP(field, value) ({bool retVal = ((field) != (value)); if ((field) != (value)) SkRefCnt_SafeAssign((field), (value)); retVal;})
/* A VectorDrawable is composed of a tree of nodes.
* Each node can be a group node, or a path.
@@ -248,49 +248,49 @@
return mPrimitiveFields.strokeWidth;
}
void setStrokeWidth(float strokeWidth) {
- VD_SET_PROP_AND_NOTIFY(strokeWidth, strokeWidth);
+ VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeWidth, strokeWidth);
}
SkColor getStrokeColor() const{
return mPrimitiveFields.strokeColor;
}
void setStrokeColor(SkColor strokeColor) {
- VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.strokeColor, strokeColor);
+ VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeColor, strokeColor);
}
float getStrokeAlpha() const{
return mPrimitiveFields.strokeAlpha;
}
void setStrokeAlpha(float strokeAlpha) {
- VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.strokeAlpha, strokeAlpha);
+ VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeAlpha, strokeAlpha);
}
SkColor getFillColor() const {
return mPrimitiveFields.fillColor;
}
void setFillColor(SkColor fillColor) {
- VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.fillColor, fillColor);
+ VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(fillColor, fillColor);
}
float getFillAlpha() const{
return mPrimitiveFields.fillAlpha;
}
void setFillAlpha(float fillAlpha) {
- VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.fillAlpha, fillAlpha);
+ VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(fillAlpha, fillAlpha);
}
float getTrimPathStart() const{
return mPrimitiveFields.trimPathStart;
}
void setTrimPathStart(float trimPathStart) {
- VD_SET_PROP_WITH_FLAG(mPrimitiveFields.trimPathStart, trimPathStart, mTrimDirty);
+ VD_SET_PRIMITIVE_FIELD_WITH_FLAG(trimPathStart, trimPathStart, mTrimDirty);
}
float getTrimPathEnd() const{
return mPrimitiveFields.trimPathEnd;
}
void setTrimPathEnd(float trimPathEnd) {
- VD_SET_PROP_WITH_FLAG(mPrimitiveFields.trimPathEnd, trimPathEnd, mTrimDirty);
+ VD_SET_PRIMITIVE_FIELD_WITH_FLAG(trimPathEnd, trimPathEnd, mTrimDirty);
}
float getTrimPathOffset() const{
return mPrimitiveFields.trimPathOffset;
}
void setTrimPathOffset(float trimPathOffset) {
- VD_SET_PROP_WITH_FLAG(mPrimitiveFields.trimPathOffset, trimPathOffset, mTrimDirty);
+ VD_SET_PRIMITIVE_FIELD_WITH_FLAG(trimPathOffset, trimPathOffset, mTrimDirty);
}
float getStrokeMiterLimit() const {
@@ -425,43 +425,43 @@
return mPrimitiveFields.rotate;
}
void setRotation(float rotation) {
- VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.rotate, rotation);
+ VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(rotate, rotation);
}
float getPivotX() const {
return mPrimitiveFields.pivotX;
}
void setPivotX(float pivotX) {
- VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.pivotX, pivotX);
+ VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(pivotX, pivotX);
}
float getPivotY() const {
return mPrimitiveFields.pivotY;
}
void setPivotY(float pivotY) {
- VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.pivotY, pivotY);
+ VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(pivotY, pivotY);
}
float getScaleX() const {
return mPrimitiveFields.scaleX;
}
void setScaleX(float scaleX) {
- VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.scaleX, scaleX);
+ VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(scaleX, scaleX);
}
float getScaleY() const {
return mPrimitiveFields.scaleY;
}
void setScaleY(float scaleY) {
- VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.scaleY, scaleY);
+ VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(scaleY, scaleY);
}
float getTranslateX() const {
return mPrimitiveFields.translateX;
}
void setTranslateX(float translateX) {
- VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.translateX, translateX);
+ VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(translateX, translateX);
}
float getTranslateY() const {
return mPrimitiveFields.translateY;
}
void setTranslateY(float translateY) {
- VD_SET_PROP_AND_NOTIFY(translateY, translateY);
+ VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(translateY, translateY);
}
void updateProperties(float rotate, float pivotX, float pivotY,
float scaleX, float scaleY, float translateX, float translateY) {
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index b39de26..a455f57 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -24,7 +24,8 @@
MinikinFontSkia::MinikinFontSkia(SkTypeface* typeface, const void* fontData, size_t fontSize,
int ttcIndex) :
- mTypeface(typeface), mFontData(fontData), mFontSize(fontSize), mTtcIndex(ttcIndex) {
+ MinikinFont(typeface->uniqueID()), mTypeface(typeface), mFontData(fontData),
+ mFontSize(fontSize), mTtcIndex(ttcIndex) {
}
MinikinFontSkia::~MinikinFontSkia() {
@@ -99,10 +100,6 @@
return mTtcIndex;
}
-int32_t MinikinFontSkia::GetUniqueId() const {
- return mTypeface->uniqueID();
-}
-
uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
uint32_t flags = paint->getFlags();
SkPaint::Hinting hinting = paint->getHinting();
diff --git a/libs/hwui/hwui/MinikinSkia.h b/libs/hwui/hwui/MinikinSkia.h
index dbc65f9..a7c9fb0 100644
--- a/libs/hwui/hwui/MinikinSkia.h
+++ b/libs/hwui/hwui/MinikinSkia.h
@@ -41,8 +41,6 @@
const void* GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy);
- int32_t GetUniqueId() const;
-
SkTypeface* GetSkTypeface() const;
// Access to underlying raw font bytes
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index c5a2dc7..5e37856 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -19,6 +19,7 @@
#include "DeferredLayerUpdater.h"
#include "DisplayList.h"
#include "LayerRenderer.h"
+#include "Readback.h"
#include "Rect.h"
#include "renderthread/CanvasContext.h"
#include "renderthread/RenderTask.h"
@@ -616,6 +617,20 @@
post(task);
}
+CREATE_BRIDGE3(copySurfaceInto, RenderThread* thread,
+ Surface* surface, SkBitmap* bitmap) {
+ return (void*) Readback::copySurfaceInto(*args->thread,
+ *args->surface, args->bitmap);
+}
+
+bool RenderProxy::copySurfaceInto(sp<Surface>& surface, SkBitmap* bitmap) {
+ SETUP_TASK(copySurfaceInto);
+ args->bitmap = bitmap;
+ args->surface = surface.get();
+ args->thread = &RenderThread::getInstance();
+ return (bool) staticPostAndWait(task);
+}
+
void RenderProxy::post(RenderTask* task) {
mRenderThread.queue(task);
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 32d3283..c39319d 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -127,6 +127,8 @@
ANDROID_API void removeFrameMetricsObserver(FrameMetricsObserver* observer);
ANDROID_API long getDroppedFrameReportCount();
+ ANDROID_API static bool copySurfaceInto(sp<Surface>& surface, SkBitmap* bitmap);
+
private:
RenderThread& mRenderThread;
CanvasContext* mContext;
diff --git a/libs/hwui/tests/microbench/PathParserBench.cpp b/libs/hwui/tests/microbench/PathParserBench.cpp
index 4186539..b43c4c3 100644
--- a/libs/hwui/tests/microbench/PathParserBench.cpp
+++ b/libs/hwui/tests/microbench/PathParserBench.cpp
@@ -31,7 +31,7 @@
size_t length = strlen(sPathString);
PathParser::ParseResult result;
while (state.KeepRunning()) {
- PathParser::parseStringForSkPath(&skPath, &result, sPathString, length);
+ PathParser::parseAsciiStringForSkPath(&skPath, &result, sPathString, length);
benchmark::DoNotOptimize(&result);
benchmark::DoNotOptimize(&skPath);
}
@@ -43,7 +43,7 @@
PathData outData;
PathParser::ParseResult result;
while (state.KeepRunning()) {
- PathParser::getPathDataFromString(&outData, &result, sPathString, length);
+ PathParser::getPathDataFromAsciiString(&outData, &result, sPathString, length);
benchmark::DoNotOptimize(&result);
benchmark::DoNotOptimize(&outData);
}
diff --git a/libs/hwui/tests/unit/ClipAreaTests.cpp b/libs/hwui/tests/unit/ClipAreaTests.cpp
index b864703..54ca68d 100644
--- a/libs/hwui/tests/unit/ClipAreaTests.cpp
+++ b/libs/hwui/tests/unit/ClipAreaTests.cpp
@@ -132,6 +132,7 @@
auto serializedClip = area.serializeClip(allocator);
ASSERT_NE(nullptr, serializedClip);
ASSERT_EQ(ClipMode::Rectangle, serializedClip->mode);
+ ASSERT_FALSE(serializedClip->intersectWithRoot) << "No replace, so no intersectWithRoot";
EXPECT_EQ(Rect(200, 200), serializedClip->rect);
EXPECT_EQ(serializedClip, area.serializeClip(allocator))
<< "Requery of clip on unmodified ClipArea must return same pointer.";
@@ -145,6 +146,7 @@
auto serializedClip = area.serializeClip(allocator);
ASSERT_NE(nullptr, serializedClip);
ASSERT_EQ(ClipMode::RectangleList, serializedClip->mode);
+ ASSERT_FALSE(serializedClip->intersectWithRoot) << "No replace, so no intersectWithRoot";
auto clipRectList = reinterpret_cast<const ClipRectList*>(serializedClip);
EXPECT_EQ(2, clipRectList->rectList.getTransformedRectanglesCount());
EXPECT_EQ(Rect(37, 54, 145, 163), clipRectList->rect);
@@ -160,6 +162,7 @@
auto serializedClip = area.serializeClip(allocator);
ASSERT_NE(nullptr, serializedClip);
ASSERT_EQ(ClipMode::Region, serializedClip->mode);
+ ASSERT_TRUE(serializedClip->intersectWithRoot) << "Replace op, so expect intersectWithRoot";
auto clipRegion = reinterpret_cast<const ClipRegion*>(serializedClip);
EXPECT_EQ(SkIRect::MakeWH(200, 200), clipRegion->region.getBounds())
<< "Clip region should be 200x200";
@@ -169,6 +172,18 @@
}
}
+TEST(ClipArea, serializeClip_pathIntersectWithRoot) {
+ ClipArea area(createClipArea());
+ LinearAllocator allocator;
+ SkPath circlePath;
+ circlePath.addCircle(100, 100, 100);
+ area.clipPathWithTransform(circlePath, &Matrix4::identity(), SkRegion::kIntersect_Op);
+
+ auto serializedClip = area.serializeClip(allocator);
+ ASSERT_NE(nullptr, serializedClip);
+ EXPECT_FALSE(serializedClip->intersectWithRoot) << "No replace, so no intersectWithRoot";
+}
+
TEST(ClipArea, serializeIntersectedClip) {
ClipArea area(createClipArea());
LinearAllocator allocator;
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 9877439..209a104 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -1722,6 +1722,35 @@
EXPECT_EQ(4, renderer.getIndex());
}
+RENDERTHREAD_TEST(FrameBuilder, shadowClipping) {
+ class ShadowClippingTestRenderer : public TestRendererBase {
+ public:
+ void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(0, mIndex++);
+ EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipState->rect)
+ << "Shadow must respect pre-barrier canvas clip value.";
+ }
+ void onRectOp(const RectOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(1, mIndex++);
+ }
+ };
+ auto parent = TestUtils::createNode(0, 0, 100, 100,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ // Apply a clip before the reorder barrier/shadow casting child is drawn.
+ // This clip must be applied to the shadow cast by the child.
+ canvas.clipRect(25, 25, 75, 75, SkRegion::kIntersect_Op);
+ canvas.insertReorderBarrier(true);
+ canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
+ });
+
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
+ TestUtils::createSyncedNodeList(parent),
+ (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance());
+ ShadowClippingTestRenderer renderer;
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+ EXPECT_EQ(2, renderer.getIndex());
+}
+
static void testProperty(std::function<void(RenderProperties&)> propSetupCallback,
std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) {
class PropertyTestRenderer : public TestRendererBase {
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index c49ff71..18171de 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -603,6 +603,36 @@
EXPECT_TRUE(chunks[1].reorderChildren);
}
+TEST(RecordingCanvas, insertReorderBarrier_clip) {
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
+ // first chunk: no recorded clip
+ canvas.insertReorderBarrier(true);
+ canvas.drawRect(0, 0, 400, 400, SkPaint());
+
+ // second chunk: no recorded clip, since inorder region
+ canvas.clipRect(0, 0, 200, 200, SkRegion::kIntersect_Op);
+ canvas.insertReorderBarrier(false);
+ canvas.drawRect(0, 0, 400, 400, SkPaint());
+
+ // third chunk: recorded clip
+ canvas.insertReorderBarrier(true);
+ canvas.drawRect(0, 0, 400, 400, SkPaint());
+ });
+
+ auto chunks = dl->getChunks();
+ ASSERT_EQ(3u, chunks.size());
+
+ EXPECT_TRUE(chunks[0].reorderChildren);
+ EXPECT_EQ(nullptr, chunks[0].reorderClip);
+
+ EXPECT_FALSE(chunks[1].reorderChildren);
+ EXPECT_EQ(nullptr, chunks[1].reorderClip);
+
+ EXPECT_TRUE(chunks[2].reorderChildren);
+ ASSERT_NE(nullptr, chunks[2].reorderClip);
+ EXPECT_EQ(Rect(200, 200), chunks[2].reorderClip->rect);
+}
+
TEST(RecordingCanvas, refPaint) {
SkPaint paint;
diff --git a/libs/hwui/tests/unit/VectorDrawableTests.cpp b/libs/hwui/tests/unit/VectorDrawableTests.cpp
index 796169e..83b485f 100644
--- a/libs/hwui/tests/unit/VectorDrawableTests.cpp
+++ b/libs/hwui/tests/unit/VectorDrawableTests.cpp
@@ -234,9 +234,10 @@
{"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
+ {"\n \t z", true}, // Valid path data with leading spaces
{"1-2e34567", false}, // Not starting with a verb and ill-formatted float
- {"f 4 5", false} // Invalid verb
+ {"f 4 5", false}, // Invalid verb
+ {"\r ", false} // Empty string
};
@@ -250,7 +251,7 @@
// Test generated path data against the given data.
PathData pathData;
size_t length = strlen(testData.pathString);
- PathParser::getPathDataFromString(&pathData, &result, testData.pathString, length);
+ PathParser::getPathDataFromAsciiString(&pathData, &result, testData.pathString, length);
EXPECT_EQ(testData.pathData, pathData);
}
@@ -258,7 +259,7 @@
PathParser::ParseResult result;
PathData pathData;
SkPath skPath;
- PathParser::getPathDataFromString(&pathData, &result,
+ PathParser::getPathDataFromAsciiString(&pathData, &result,
stringPath.stringPath, strlen(stringPath.stringPath));
EXPECT_EQ(stringPath.isValid, !result.failureOccurred);
}
@@ -274,13 +275,13 @@
}
}
-TEST(PathParser, parseStringForSkPath) {
+TEST(PathParser, parseAsciiStringForSkPath) {
for (TestData testData: sTestDataSet) {
PathParser::ParseResult result;
size_t length = strlen(testData.pathString);
// Check the return value as well as the SkPath generated.
SkPath actualPath;
- PathParser::parseStringForSkPath(&actualPath, &result, testData.pathString, length);
+ PathParser::parseAsciiStringForSkPath(&actualPath, &result, testData.pathString, length);
bool hasValidData = !result.failureOccurred;
EXPECT_EQ(hasValidData, testData.pathData.verbs.size() > 0);
SkPath expectedPath;
@@ -291,7 +292,7 @@
for (StringPath stringPath : sStringPaths) {
PathParser::ParseResult result;
SkPath skPath;
- PathParser::parseStringForSkPath(&skPath, &result, stringPath.stringPath,
+ PathParser::parseAsciiStringForSkPath(&skPath, &result, stringPath.stringPath,
strlen(stringPath.stringPath));
EXPECT_EQ(stringPath.isValid, !result.failureOccurred);
}
@@ -390,5 +391,40 @@
EXPECT_EQ(matrixAndScale.matrixScale, actualMatrixScale);
}
}
+
+TEST(VectorDrawable, groupProperties) {
+ //TODO: Also need to test property sync and dirty flag when properties change.
+ VectorDrawable::Group group;
+ VectorDrawable::Group::GroupProperties* properties = group.mutateProperties();
+ // Test default values, change values through setters and verify the change through getters.
+ EXPECT_EQ(0.0f, properties->getTranslateX());
+ properties->setTranslateX(1.0f);
+ EXPECT_EQ(1.0f, properties->getTranslateX());
+
+ EXPECT_EQ(0.0f, properties->getTranslateY());
+ properties->setTranslateY(1.0f);
+ EXPECT_EQ(1.0f, properties->getTranslateY());
+
+ EXPECT_EQ(0.0f, properties->getRotation());
+ properties->setRotation(1.0f);
+ EXPECT_EQ(1.0f, properties->getRotation());
+
+ EXPECT_EQ(1.0f, properties->getScaleX());
+ properties->setScaleX(0.0f);
+ EXPECT_EQ(0.0f, properties->getScaleX());
+
+ EXPECT_EQ(1.0f, properties->getScaleY());
+ properties->setScaleY(0.0f);
+ EXPECT_EQ(0.0f, properties->getScaleY());
+
+ EXPECT_EQ(0.0f, properties->getPivotX());
+ properties->setPivotX(1.0f);
+ EXPECT_EQ(1.0f, properties->getPivotX());
+
+ EXPECT_EQ(0.0f, properties->getPivotY());
+ properties->setPivotY(1.0f);
+ EXPECT_EQ(1.0f, properties->getPivotY());
+
+}
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h
index ccf2287..7212897b 100644
--- a/libs/hwui/utils/Macros.h
+++ b/libs/hwui/utils/Macros.h
@@ -23,12 +23,10 @@
Type(const Type&) = delete; \
void operator=(const Type&) = delete
-#define DESCRIPTION_TYPE(Type) \
- int compare(const Type& rhs) const { return memcmp(this, &rhs, sizeof(Type));} \
- bool operator==(const Type& other) const { return compare(other) == 0; } \
- bool operator!=(const Type& other) const { return compare(other) != 0; } \
- friend inline int strictly_order_type(const Type& lhs, const Type& rhs) { return lhs.compare(rhs) < 0; } \
- friend inline int compare_type(const Type& lhs, const Type& rhs) { return lhs.compare(rhs); } \
+#define HASHABLE_TYPE(Type) \
+ bool operator==(const Type& other) const; \
+ hash_t hash() const; \
+ bool operator!=(const Type& other) const { return !(*this == other); } \
friend inline hash_t hash_type(const Type& entry) { return entry.hash(); }
#define REQUIRE_COMPATIBLE_LAYOUT(Type) \
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index ca306cc..4504e69 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -37,6 +37,8 @@
import android.util.ArrayMap;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
/**
* The AudioRecord class manages the audio resources for Java applications
* to record audio from the audio input hardware of the platform. This is
@@ -874,22 +876,24 @@
* Calling {@link #startRecording()} following a {@link #stop()} will reset
* the frame count to 0.
*
- * @param timestamp a reference to a non-null AudioTimestamp instance.
+ * @param outTimestamp a caller provided non-null AudioTimestamp instance,
+ * which is updated with the AudioRecord frame delivery information upon success.
* @param timebase one of
* {@link AudioTimestamp#TIMEBASE_BOOTTIME AudioTimestamp.TIMEBASE_BOOTTIME} or
- * {@link AudioTimestamp#TIMEBASE_MONOTONIC AudioTimestamp.TIMEBASE_MONOTONIC}.
+ * {@link AudioTimestamp#TIMEBASE_MONOTONIC AudioTimestamp.TIMEBASE_MONOTONIC},
+ * used to select the clock for the AudioTimestamp time.
* @return {@link #SUCCESS} if a timestamp is available,
* or {@link #ERROR_INVALID_OPERATION} if a timestamp not available.
*/
- public int getTimestamp(@NonNull AudioTimestamp timestamp,
+ public int getTimestamp(@NonNull AudioTimestamp outTimestamp,
@AudioTimestamp.Timebase int timebase)
{
- if (timestamp == null ||
+ if (outTimestamp == null ||
(timebase != AudioTimestamp.TIMEBASE_BOOTTIME
&& timebase != AudioTimestamp.TIMEBASE_MONOTONIC)) {
throw new IllegalArgumentException();
}
- return native_get_timestamp(timestamp, timebase);
+ return native_get_timestamp(outTimestamp, timebase);
}
/**
@@ -1320,6 +1324,7 @@
* Note: The query is only valid if the AudioRecord is currently recording. If it is not,
* <code>getRoutedDevice()</code> will return null.
*/
+ @Override
public AudioDeviceInfo getRoutedDevice() {
int deviceId = native_getRoutedDeviceId();
if (deviceId == 0) {
@@ -1338,8 +1343,8 @@
/*
* Call BEFORE adding a routing callback handler.
*/
- private void testEnableNativeRoutingCallbacks() {
- if (mRoutingChangeListeners.size() == 0 && mNewRoutingChangeListeners.size() == 0) {
+ private void testEnableNativeRoutingCallbacksLocked() {
+ if (mRoutingChangeListeners.size() == 0) {
native_enableDeviceCallback();
}
}
@@ -1347,24 +1352,23 @@
/*
* Call AFTER removing a routing callback handler.
*/
- private void testDisableNativeRoutingCallbacks() {
- if (mRoutingChangeListeners.size() == 0 && mNewRoutingChangeListeners.size() == 0) {
+ private void testDisableNativeRoutingCallbacksLocked() {
+ if (mRoutingChangeListeners.size() == 0) {
native_disableDeviceCallback();
}
}
//--------------------------------------------------------------------------
- // >= "N" (Re)Routing Info
+ // (Re)Routing Info
//--------------------
/**
* The list of AudioRouting.OnRoutingChangedListener interfaces added (with
- * {@link AudioRecord#addOnRoutingListener(AudioRouting.OnRoutingChangedListener,
- * android.os.Handler)}
- * by an app to receive (re)routing notifications.
+ * {@link AudioRecord#addOnRoutingChangedListener} by an app to receive
+ * (re)routing notifications.
*/
- private ArrayMap<AudioRouting.OnRoutingChangedListener, NativeNewRoutingEventHandlerDelegate>
- mNewRoutingChangeListeners =
- new ArrayMap<AudioRouting.OnRoutingChangedListener, NativeNewRoutingEventHandlerDelegate>();
+ @GuardedBy("mRoutingChangeListeners")
+ private ArrayMap<AudioRouting.OnRoutingChangedListener,
+ NativeRoutingEventHandlerDelegate> mRoutingChangeListeners = new ArrayMap<>();
/**
* Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of
@@ -1375,14 +1379,15 @@
* the callback. If <code>null</code>, the {@link Handler} associated with the main
* {@link Looper} will be used.
*/
- public void addOnRoutingListener(AudioRouting.OnRoutingChangedListener listener,
+ @Override
+ public void addOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener,
android.os.Handler handler) {
- if (listener != null && !mNewRoutingChangeListeners.containsKey(listener)) {
- synchronized (mNewRoutingChangeListeners) {
- testEnableNativeRoutingCallbacks();
- mNewRoutingChangeListeners.put(
- listener, new NativeNewRoutingEventHandlerDelegate(this, listener,
- handler != null ? handler : new Handler(mInitializationLooper)));
+ synchronized (mRoutingChangeListeners) {
+ if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
+ testEnableNativeRoutingCallbacksLocked();
+ mRoutingChangeListeners.put(
+ listener, new NativeRoutingEventHandlerDelegate(this, listener,
+ handler != null ? handler : new Handler(mInitializationLooper)));
}
}
}
@@ -1393,39 +1398,42 @@
* @param listener The previously added {@link AudioRouting.OnRoutingChangedListener} interface
* to remove.
*/
- public void removeOnRoutingListener(AudioRouting.OnRoutingChangedListener listener) {
- synchronized (mNewRoutingChangeListeners) {
- if (mNewRoutingChangeListeners.containsKey(listener)) {
- mNewRoutingChangeListeners.remove(listener);
- testDisableNativeRoutingCallbacks();
+ @Override
+ public void removeOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener) {
+ synchronized (mRoutingChangeListeners) {
+ if (mRoutingChangeListeners.containsKey(listener)) {
+ mRoutingChangeListeners.remove(listener);
+ testDisableNativeRoutingCallbacksLocked();
}
}
}
//--------------------------------------------------------------------------
- // Marshmallow (Re)Routing Info
+ // (Re)Routing Info
//--------------------
/**
- * Defines the interface by which applications can receive notifications of routing
- * changes for the associated {@link AudioRecord}.
+ * Defines the interface by which applications can receive notifications of
+ * routing changes for the associated {@link AudioRecord}.
+ *
+ * @deprecated users should switch to the general purpose
+ * {@link AudioRouting.OnRoutingChangedListener} class instead.
*/
- public interface OnRoutingChangedListener {
+ @Deprecated
+ public interface OnRoutingChangedListener extends AudioRouting.OnRoutingChangedListener {
/**
- * Called when the routing of an AudioRecord changes from either and explicit or
- * policy rerouting. Use {@link #getRoutedDevice()} to retrieve the newly routed-from
- * device.
+ * Called when the routing of an AudioRecord changes from either and
+ * explicit or policy rerouting. Use {@link #getRoutedDevice()} to
+ * retrieve the newly routed-from device.
*/
public void onRoutingChanged(AudioRecord audioRecord);
- }
- /**
- * The list of AudioRecord.OnRoutingChangedListener interface added (with
- * {@link AudioRecord#addOnRoutingChangedListener(OnRoutingChangedListener,android.os.Handler)}
- * by an app to receive (re)routing notifications.
- */
- private ArrayMap<OnRoutingChangedListener, NativeRoutingEventHandlerDelegate>
- mRoutingChangeListeners =
- new ArrayMap<OnRoutingChangedListener, NativeRoutingEventHandlerDelegate>();
+ @Override
+ default public void onRoutingChanged(AudioRouting router) {
+ if (router instanceof AudioRecord) {
+ onRoutingChanged((AudioRecord) router);
+ }
+ }
+ }
/**
* Adds an {@link OnRoutingChangedListener} to receive notifications of routing changes
@@ -1435,88 +1443,28 @@
* @param handler Specifies the {@link Handler} object for the thread on which to execute
* the callback. If <code>null</code>, the {@link Handler} associated with the main
* {@link Looper} will be used.
+ * @deprecated users should switch to the general purpose
+ * {@link AudioRouting.OnRoutingChangedListener} class instead.
*/
@Deprecated
public void addOnRoutingChangedListener(OnRoutingChangedListener listener,
android.os.Handler handler) {
- if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
- synchronized (mRoutingChangeListeners) {
- testEnableNativeRoutingCallbacks();
- mRoutingChangeListeners.put(
- listener, new NativeRoutingEventHandlerDelegate(this, listener,
- handler != null ? handler : new Handler(mInitializationLooper)));
- }
- }
+ addOnRoutingChangedListener((AudioRouting.OnRoutingChangedListener) listener, handler);
}
/**
* Removes an {@link OnRoutingChangedListener} which has been previously added
* to receive rerouting notifications.
* @param listener The previously added {@link OnRoutingChangedListener} interface to remove.
+ * @deprecated users should switch to the general purpose
+ * {@link AudioRouting.OnRoutingChangedListener} class instead.
*/
@Deprecated
public void removeOnRoutingChangedListener(OnRoutingChangedListener listener) {
- synchronized (mRoutingChangeListeners) {
- if (mRoutingChangeListeners.containsKey(listener)) {
- mRoutingChangeListeners.remove(listener);
- testDisableNativeRoutingCallbacks();
- }
- }
+ removeOnRoutingChangedListener((AudioRouting.OnRoutingChangedListener) listener);
}
/**
- * >= "N" Routing
- * Helper class to handle the forwarding of native events to the appropriate listener
- * (potentially) handled in a different thread
- */
- private class NativeNewRoutingEventHandlerDelegate {
- private final Handler mHandler;
-
- NativeNewRoutingEventHandlerDelegate(final AudioRecord record,
- final AudioRouting.OnRoutingChangedListener listener,
- Handler handler) {
- // find the looper for our new event handler
- Looper looper;
- if (handler != null) {
- looper = handler.getLooper();
- } else {
- // no given handler, use the looper the AudioRecord was created in
- looper = mInitializationLooper;
- }
-
- // construct the event handler with this looper
- if (looper != null) {
- // implement the event handler delegate
- mHandler = new Handler(looper) {
- @Override
- public void handleMessage(Message msg) {
- if (record == null) {
- return;
- }
- switch(msg.what) {
- case AudioSystem.NATIVE_EVENT_ROUTING_CHANGE:
- if (listener != null) {
- listener.onRoutingChanged(record);
- }
- break;
- default:
- loge("Unknown native event type: " + msg.what);
- break;
- }
- }
- };
- } else {
- mHandler = null;
- }
- }
-
- Handler getHandler() {
- return mHandler;
- }
- }
-
- /**
- * Marshmallow Routing
* Helper class to handle the forwarding of native events to the appropriate listener
* (potentially) handled in a different thread
*/
@@ -1524,7 +1472,7 @@
private final Handler mHandler;
NativeRoutingEventHandlerDelegate(final AudioRecord record,
- final OnRoutingChangedListener listener,
+ final AudioRouting.OnRoutingChangedListener listener,
Handler handler) {
// find the looper for our new event handler
Looper looper;
@@ -1571,26 +1519,12 @@
*/
private void broadcastRoutingChange() {
AudioManager.resetAudioPortGeneration();
- // Marshmallow Routing
- Collection<NativeRoutingEventHandlerDelegate> values;
synchronized (mRoutingChangeListeners) {
- values = mRoutingChangeListeners.values();
- }
- for(NativeRoutingEventHandlerDelegate delegate : values) {
- Handler handler = delegate.getHandler();
- if (handler != null) {
- handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
- }
- }
- // >= "N" Routing
- Collection<NativeNewRoutingEventHandlerDelegate> newValues;
- synchronized (mNewRoutingChangeListeners) {
- newValues = mNewRoutingChangeListeners.values();
- }
- for(NativeNewRoutingEventHandlerDelegate delegate : newValues) {
- Handler handler = delegate.getHandler();
- if (handler != null) {
- handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
+ for (NativeRoutingEventHandlerDelegate delegate : mRoutingChangeListeners.values()) {
+ Handler handler = delegate.getHandler();
+ if (handler != null) {
+ handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
+ }
}
}
}
@@ -1623,6 +1557,7 @@
* @return true if successful, false if the specified {@link AudioDeviceInfo} is non-null and
* does not correspond to a valid audio input device.
*/
+ @Override
public boolean setPreferredDevice(AudioDeviceInfo deviceInfo) {
// Do some validation....
if (deviceInfo != null && !deviceInfo.isSource()) {
@@ -1643,6 +1578,7 @@
* Returns the selected input specified by {@link #setPreferredDevice}. Note that this
* is not guarenteed to correspond to the actual device being used for recording.
*/
+ @Override
public AudioDeviceInfo getPreferredDevice() {
synchronized (this) {
return mPreferredDevice;
@@ -1683,7 +1619,6 @@
* (potentially) handled in a different thread
*/
private class NativeEventHandler extends Handler {
-
private final AudioRecord mAudioRecord;
NativeEventHandler(AudioRecord recorder, Looper looper) {
@@ -1714,8 +1649,7 @@
break;
}
}
- };
-
+ }
//---------------------------------------------------------
// Java methods called from the native side
@@ -1793,7 +1727,7 @@
private native final void native_enableDeviceCallback();
private native final void native_disableDeviceCallback();
- private native final int native_get_timestamp(@NonNull AudioTimestamp timestamp,
+ private native final int native_get_timestamp(@NonNull AudioTimestamp outTimestamp,
@AudioTimestamp.Timebase int timebase);
//---------------------------------------------------------
diff --git a/media/java/android/media/AudioRouting.java b/media/java/android/media/AudioRouting.java
index 41f92d4..26fa631 100644
--- a/media/java/android/media/AudioRouting.java
+++ b/media/java/android/media/AudioRouting.java
@@ -57,7 +57,7 @@
* the callback. If <code>null</code>, the {@link Handler} associated with the main
* {@link Looper} will be used.
*/
- public void addOnRoutingListener(OnRoutingChangedListener listener,
+ public void addOnRoutingChangedListener(OnRoutingChangedListener listener,
Handler handler);
/**
@@ -66,7 +66,7 @@
* @param listener The previously added {@link AudioRouting.OnRoutingChangedListener} interface
* to remove.
*/
- public void removeOnRoutingListener(OnRoutingChangedListener listener);
+ public void removeOnRoutingChangedListener(OnRoutingChangedListener listener);
/**
* Defines the interface by which applications can receive notifications of routing
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 621129d..9d360db 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -40,6 +40,7 @@
import android.util.ArrayMap;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsService;
/**
@@ -1489,6 +1490,7 @@
* @deprecated Applications should use {@link #setVolume} instead, as it
* more gracefully scales down to mono, and up to multi-channel content beyond stereo.
*/
+ @Deprecated
public int setStereoVolume(float leftGain, float rightGain) {
if (isRestricted()) {
return SUCCESS;
@@ -2397,6 +2399,7 @@
* @return true if succesful, false if the specified {@link AudioDeviceInfo} is non-null and
* does not correspond to a valid audio output device.
*/
+ @Override
public boolean setPreferredDevice(AudioDeviceInfo deviceInfo) {
// Do some validation....
if (deviceInfo != null && !deviceInfo.isSink()) {
@@ -2416,6 +2419,7 @@
* Returns the selected output specified by {@link #setPreferredDevice}. Note that this
* is not guaranteed to correspond to the actual device being used for playback.
*/
+ @Override
public AudioDeviceInfo getPreferredDevice() {
synchronized (this) {
return mPreferredDevice;
@@ -2427,6 +2431,7 @@
* Note: The query is only valid if the AudioTrack is currently playing. If it is not,
* <code>getRoutedDevice()</code> will return null.
*/
+ @Override
public AudioDeviceInfo getRoutedDevice() {
int deviceId = native_getRoutedDeviceId();
if (deviceId == 0) {
@@ -2445,8 +2450,8 @@
/*
* Call BEFORE adding a routing callback handler.
*/
- private void testEnableNativeRoutingCallbacks() {
- if (mRoutingChangeListeners.size() == 0 && mNewRoutingChangeListeners.size() == 0) {
+ private void testEnableNativeRoutingCallbacksLocked() {
+ if (mRoutingChangeListeners.size() == 0) {
native_enableDeviceCallback();
}
}
@@ -2454,24 +2459,23 @@
/*
* Call AFTER removing a routing callback handler.
*/
- private void testDisableNativeRoutingCallbacks() {
- if (mRoutingChangeListeners.size() == 0 && mNewRoutingChangeListeners.size() == 0) {
+ private void testDisableNativeRoutingCallbacksLocked() {
+ if (mRoutingChangeListeners.size() == 0) {
native_disableDeviceCallback();
}
}
//--------------------------------------------------------------------------
- // >= "N" (Re)Routing Info
+ // (Re)Routing Info
//--------------------
/**
* The list of AudioRouting.OnRoutingChangedListener interfaces added (with
- * {@link AudioTrack#addOnRoutingListener(AudioRouting.OnRoutingChangedListener,
- * android.os.Handler)}
- * by an app to receive (re)routing notifications.
+ * {@link AudioRecord#addOnRoutingChangedListener} by an app to receive
+ * (re)routing notifications.
*/
- private ArrayMap<AudioRouting.OnRoutingChangedListener, NativeNewRoutingEventHandlerDelegate>
- mNewRoutingChangeListeners =
- new ArrayMap<AudioRouting.OnRoutingChangedListener, NativeNewRoutingEventHandlerDelegate>();
+ @GuardedBy("mRoutingChangeListeners")
+ private ArrayMap<AudioRouting.OnRoutingChangedListener,
+ NativeRoutingEventHandlerDelegate> mRoutingChangeListeners = new ArrayMap<>();
/**
* Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of routing
@@ -2482,14 +2486,15 @@
* the callback. If <code>null</code>, the {@link Handler} associated with the main
* {@link Looper} will be used.
*/
- public void addOnRoutingListener(AudioRouting.OnRoutingChangedListener listener,
+ @Override
+ public void addOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener,
Handler handler) {
- if (listener != null && !mNewRoutingChangeListeners.containsKey(listener)) {
- synchronized (mNewRoutingChangeListeners) {
- testEnableNativeRoutingCallbacks();
- mNewRoutingChangeListeners.put(
- listener, new NativeNewRoutingEventHandlerDelegate(this, listener,
- handler != null ? handler : new Handler(mInitializationLooper)));
+ synchronized (mRoutingChangeListeners) {
+ if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
+ testEnableNativeRoutingCallbacksLocked();
+ mRoutingChangeListeners.put(
+ listener, new NativeRoutingEventHandlerDelegate(this, listener,
+ handler != null ? handler : new Handler(mInitializationLooper)));
}
}
}
@@ -2500,39 +2505,42 @@
* @param listener The previously added {@link AudioRouting.OnRoutingChangedListener} interface
* to remove.
*/
- public void removeOnRoutingListener(AudioRouting.OnRoutingChangedListener listener) {
- if (mNewRoutingChangeListeners.containsKey(listener)) {
- mNewRoutingChangeListeners.remove(listener);
+ @Override
+ public void removeOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener) {
+ synchronized (mRoutingChangeListeners) {
+ if (mRoutingChangeListeners.containsKey(listener)) {
+ mRoutingChangeListeners.remove(listener);
+ }
+ testDisableNativeRoutingCallbacksLocked();
}
- testDisableNativeRoutingCallbacks();
}
//--------------------------------------------------------------------------
- // Marshmallow (Re)Routing Info
+ // (Re)Routing Info
//--------------------
/**
- * Defines the interface by which applications can receive notifications of routing
- * changes for the associated {@link AudioTrack}.
+ * Defines the interface by which applications can receive notifications of
+ * routing changes for the associated {@link AudioTrack}.
+ *
+ * @deprecated users should switch to the general purpose
+ * {@link AudioRouting.OnRoutingChangedListener} class instead.
*/
@Deprecated
- public interface OnRoutingChangedListener {
+ public interface OnRoutingChangedListener extends AudioRouting.OnRoutingChangedListener {
/**
- * Called when the routing of an AudioTrack changes from either and explicit or
- * policy rerouting. Use {@link #getRoutedDevice()} to retrieve the newly routed-to
- * device.
+ * Called when the routing of an AudioTrack changes from either and
+ * explicit or policy rerouting. Use {@link #getRoutedDevice()} to
+ * retrieve the newly routed-to device.
*/
- @Deprecated
public void onRoutingChanged(AudioTrack audioTrack);
- }
- /**
- * The list of AudioTrack.OnRoutingChangedListener interfaces added (with
- * {@link AudioTrack#addOnRoutingChangedListener(OnRoutingChangedListener, android.os.Handler)}
- * by an app to receive (re)routing notifications.
- */
- private ArrayMap<OnRoutingChangedListener, NativeRoutingEventHandlerDelegate>
- mRoutingChangeListeners =
- new ArrayMap<OnRoutingChangedListener, NativeRoutingEventHandlerDelegate>();
+ @Override
+ default public void onRoutingChanged(AudioRouting router) {
+ if (router instanceof AudioTrack) {
+ onRoutingChanged((AudioTrack) router);
+ }
+ }
+ }
/**
* Adds an {@link OnRoutingChangedListener} to receive notifications of routing changes
@@ -2542,33 +2550,25 @@
* @param handler Specifies the {@link Handler} object for the thread on which to execute
* the callback. If <code>null</code>, the {@link Handler} associated with the main
* {@link Looper} will be used.
+ * @deprecated users should switch to the general purpose
+ * {@link AudioRouting.OnRoutingChangedListener} class instead.
*/
@Deprecated
public void addOnRoutingChangedListener(OnRoutingChangedListener listener,
android.os.Handler handler) {
- if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
- synchronized (mRoutingChangeListeners) {
- testEnableNativeRoutingCallbacks();
- mRoutingChangeListeners.put(
- listener, new NativeRoutingEventHandlerDelegate(this, listener,
- handler != null ? handler : new Handler(mInitializationLooper)));
- }
- }
+ addOnRoutingChangedListener((AudioRouting.OnRoutingChangedListener) listener, handler);
}
/**
* Removes an {@link OnRoutingChangedListener} which has been previously added
* to receive rerouting notifications.
* @param listener The previously added {@link OnRoutingChangedListener} interface to remove.
+ * @deprecated users should switch to the general purpose
+ * {@link AudioRouting.OnRoutingChangedListener} class instead.
*/
@Deprecated
public void removeOnRoutingChangedListener(OnRoutingChangedListener listener) {
- synchronized (mRoutingChangeListeners) {
- if (mRoutingChangeListeners.containsKey(listener)) {
- mRoutingChangeListeners.remove(listener);
- }
- testDisableNativeRoutingCallbacks();
- }
+ removeOnRoutingChangedListener((AudioRouting.OnRoutingChangedListener) listener);
}
/**
@@ -2576,27 +2576,12 @@
*/
private void broadcastRoutingChange() {
AudioManager.resetAudioPortGeneration();
-
- // Marshmallow Routing
- Collection<NativeRoutingEventHandlerDelegate> values;
synchronized (mRoutingChangeListeners) {
- values = mRoutingChangeListeners.values();
- }
- for(NativeRoutingEventHandlerDelegate delegate : values) {
- Handler handler = delegate.getHandler();
- if (handler != null) {
- handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
- }
- }
- // >= "N" Routing
- Collection<NativeNewRoutingEventHandlerDelegate> newValues;
- synchronized (mNewRoutingChangeListeners) {
- newValues = mNewRoutingChangeListeners.values();
- }
- for(NativeNewRoutingEventHandlerDelegate delegate : newValues) {
- Handler handler = delegate.getHandler();
- if (handler != null) {
- handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
+ for (NativeRoutingEventHandlerDelegate delegate : mRoutingChangeListeners.values()) {
+ Handler handler = delegate.getHandler();
+ if (handler != null) {
+ handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
+ }
}
}
}
@@ -2681,7 +2666,6 @@
}
/**
- * Marshmallow Routing API.
* Helper class to handle the forwarding of native events to the appropriate listener
* (potentially) handled in a different thread
*/
@@ -2689,57 +2673,6 @@
private final Handler mHandler;
NativeRoutingEventHandlerDelegate(final AudioTrack track,
- final OnRoutingChangedListener listener,
- Handler handler) {
- // find the looper for our new event handler
- Looper looper;
- if (handler != null) {
- looper = handler.getLooper();
- } else {
- // no given handler, use the looper the AudioTrack was created in
- looper = mInitializationLooper;
- }
-
- // construct the event handler with this looper
- if (looper != null) {
- // implement the event handler delegate
- mHandler = new Handler(looper) {
- @Override
- public void handleMessage(Message msg) {
- if (track == null) {
- return;
- }
- switch(msg.what) {
- case AudioSystem.NATIVE_EVENT_ROUTING_CHANGE:
- if (listener != null) {
- listener.onRoutingChanged(track);
- }
- break;
- default:
- loge("Unknown native event type: " + msg.what);
- break;
- }
- }
- };
- } else {
- mHandler = null;
- }
- }
-
- Handler getHandler() {
- return mHandler;
- }
- }
-
- /**
- * Marshmallow Routing API.
- * Helper class to handle the forwarding of native events to the appropriate listener
- * (potentially) handled in a different thread
- */
- private class NativeNewRoutingEventHandlerDelegate {
- private final Handler mHandler;
-
- NativeNewRoutingEventHandlerDelegate(final AudioTrack track,
final AudioRouting.OnRoutingChangedListener listener,
Handler handler) {
// find the looper for our new event handler
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 2bd9781..7af9c24 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -2611,10 +2611,13 @@
public static final int VP8ProfileMain = 0x01;
// from OMX_VIDEO_VP9PROFILETYPE
- public static final int VP9Profile0 = 0x00;
- public static final int VP9Profile1 = 0x01;
- public static final int VP9Profile2 = 0x02;
- public static final int VP9Profile3 = 0x03;
+ public static final int VP9Profile0 = 0x01;
+ public static final int VP9Profile1 = 0x02;
+ public static final int VP9Profile2 = 0x04;
+ public static final int VP9Profile3 = 0x08;
+ // HDR profiles also support passing HDR metadata
+ public static final int VP9Profile2HDR = 0x1000;
+ public static final int VP9Profile3HDR = 0x2000;
// from OMX_VIDEO_VP9LEVELTYPE
public static final int VP9Level1 = 0x0;
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index b78869e..55d5f42 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1107,6 +1107,9 @@
* as this call returns.
*
* @param afd the AssetFileDescriptor for the file you want to play
+ * @throws IllegalStateException if it is called in an invalid state
+ * @throws IllegalArgumentException if afd is not a valid AssetFileDescriptor
+ * @throws IOException if afd can not be read
*/
public void setDataSource(@NonNull AssetFileDescriptor afd)
throws IOException, IllegalArgumentException, IllegalStateException {
@@ -1127,6 +1130,8 @@
*
* @param fd the FileDescriptor for the file you want to play
* @throws IllegalStateException if it is called in an invalid state
+ * @throws IllegalArgumentException if fd is not a valid FileDescriptor
+ * @throws IOException if fd can not be read
*/
public void setDataSource(FileDescriptor fd)
throws IOException, IllegalArgumentException, IllegalStateException {
@@ -1143,6 +1148,8 @@
* @param offset the offset into the file where the data to be played starts, in bytes
* @param length the length in bytes of the data to be played
* @throws IllegalStateException if it is called in an invalid state
+ * @throws IllegalArgumentException if fd is not a valid FileDescriptor
+ * @throws IOException if fd can not be read
*/
public void setDataSource(FileDescriptor fd, long offset, long length)
throws IOException, IllegalArgumentException, IllegalStateException {
@@ -1157,6 +1164,7 @@
*
* @param dataSource the MediaDataSource for the media you want to play
* @throws IllegalStateException if it is called in an invalid state
+ * @throws IllegalArgumentException if dataSource is not a valid MediaDataSource
*/
public void setDataSource(MediaDataSource dataSource)
throws IllegalArgumentException, IllegalStateException {
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index e8c50e3..db7b43a 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -1217,6 +1217,18 @@
public static final String COLUMN_SEARCHABLE = "searchable";
/**
+ * The flag indicating whether recording of this program is prohibited.
+ *
+ * <p>A value of 1 indicates that recording of this program is prohibited and application
+ * will not schedule any recording for this program. A value of 0 indicates that the
+ * recording is not prohibited. If not specified, this value is set to 0 (not prohibited) by
+ * default.
+ *
+ * <p>Type: INTEGER (boolean)
+ */
+ public static final String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
+
+ /**
* Internal data used by individual TV input services.
*
* <p>This is internal to the provider that inserted it, and should not be decoded by other
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 03dc699..a33b219 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -16,7 +16,9 @@
package android.media.tv;
+import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.StringRes;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
@@ -48,6 +50,8 @@
import java.io.IOException;
import java.io.InputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
@@ -62,6 +66,12 @@
private static final boolean DEBUG = false;
private static final String TAG = "TvInputInfo";
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({TYPE_TUNER, TYPE_OTHER, TYPE_COMPOSITE, TYPE_SVIDEO, TYPE_SCART, TYPE_COMPONENT,
+ TYPE_VGA, TYPE_DVI, TYPE_HDMI, TYPE_DISPLAY_PORT})
+ public @interface Type {}
+
// Should be in sync with frameworks/base/core/res/res/values/attrs.xml
/**
* TV input type: the TV input service is a tuner which provides channels.
@@ -343,6 +353,7 @@
/**
* Returns the type of this TV input.
*/
+ @Type
public int getType() {
return mType;
}
@@ -369,8 +380,7 @@
}
/**
- * Returns the extras associated with this TV input.
- * @hide
+ * Returns domain-specific extras associated with this TV input.
*/
public Bundle getExtras() {
return mExtras;
@@ -769,7 +779,7 @@
* @hide
*/
@SystemApi
- public Builder setLabel(int resId) {
+ public Builder setLabel(@StringRes int resId) {
if (mLabel != null) {
throw new IllegalStateException("Label text is already set.");
}
@@ -847,11 +857,12 @@
}
/**
- * Sets the extras associated with this TV input.
+ * Sets domain-specific extras associated with this TV input.
*
- * @param extras The extras associated with this TV input.
+ * @param extras Domain-specific extras associated with this TV input. Keys <em>must</em> be
+ * a scoped name, i.e. prefixed with a package name you own, so that different
+ * developers will not create conflicting keys.
* @return This Builder object to allow for chaining of calls to builder methods.
- * @hide
*/
public Builder setExtras(Bundle extras) {
this.mExtras = extras;
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index b4536b1..bfd938e 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -99,6 +99,13 @@
*/
public static final int DVB_DEVICE_FRONTEND = DVB_DEVICE_END;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({VIDEO_UNAVAILABLE_REASON_UNKNOWN, VIDEO_UNAVAILABLE_REASON_TUNING,
+ VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL, VIDEO_UNAVAILABLE_REASON_BUFFERING,
+ VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY})
+ public @interface VideoUnavailableReason {}
+
static final int VIDEO_UNAVAILABLE_REASON_START = 0;
static final int VIDEO_UNAVAILABLE_REASON_END = 4;
@@ -135,10 +142,9 @@
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef({VIDEO_UNAVAILABLE_REASON_UNKNOWN, VIDEO_UNAVAILABLE_REASON_TUNING,
- VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL, VIDEO_UNAVAILABLE_REASON_BUFFERING,
- VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY})
- public @interface VideoUnavailableReason {}
+ @IntDef({TIME_SHIFT_STATUS_UNKNOWN, TIME_SHIFT_STATUS_UNSUPPORTED,
+ TIME_SHIFT_STATUS_UNAVAILABLE, TIME_SHIFT_STATUS_AVAILABLE})
+ public @interface TimeShiftStatus {}
/**
* Status for {@link TvInputService.Session#notifyTimeShiftStatusChanged(int)} and
@@ -169,12 +175,6 @@
*/
public static final int TIME_SHIFT_STATUS_AVAILABLE = 3;
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({TIME_SHIFT_STATUS_UNKNOWN, TIME_SHIFT_STATUS_UNSUPPORTED,
- TIME_SHIFT_STATUS_UNAVAILABLE, TIME_SHIFT_STATUS_AVAILABLE})
- public @interface TimeShiftStatus {}
-
/**
* Value returned by {@link TvInputService.Session#onTimeShiftGetCurrentPosition()} and
* {@link TvInputService.Session#onTimeShiftGetStartPosition()} when time shifting has not
@@ -182,6 +182,12 @@
*/
public static final long TIME_SHIFT_INVALID_TIME = Long.MIN_VALUE;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({RECORDING_ERROR_UNKNOWN, RECORDING_ERROR_INSUFFICIENT_SPACE,
+ RECORDING_ERROR_RESOURCE_BUSY})
+ public @interface RecordingError {}
+
/**
* Error for {@link TvInputService.RecordingSession#notifyError(int)} and
* {@link TvRecordingClient.RecordingCallback#onError(int)}: The requested operation cannot be
@@ -205,9 +211,8 @@
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef({RECORDING_ERROR_UNKNOWN, RECORDING_ERROR_INSUFFICIENT_SPACE,
- RECORDING_ERROR_RESOURCE_BUSY})
- public @interface RecordingError {}
+ @IntDef({INPUT_STATE_CONNECTED, INPUT_STATE_CONNECTED_STANDBY, INPUT_STATE_DISCONNECTED})
+ public @interface InputState {}
/**
* State for {@link #getInputState(String)} and
@@ -240,11 +245,6 @@
*/
public static final int INPUT_STATE_DISCONNECTED = 2;
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({INPUT_STATE_CONNECTED, INPUT_STATE_CONNECTED_STANDBY, INPUT_STATE_DISCONNECTED})
- public @interface InputState {}
-
/**
* Broadcast intent action when the user blocked content ratings change. For use with the
* {@link #isRatingBlocked}.
@@ -483,26 +483,19 @@
}
/**
- * This is called when the start playback position is changed.
- *
- * <p>The start playback position of the time shifted program should be adjusted when the TV
- * input cannot retain the whole recorded program due to some reason (e.g. limitation on
- * storage space). This is necessary to prevent the application from allowing the user to
- * seek to a time position that is not reachable.
+ * This is called when the start position for time shifting has changed.
*
* @param session A {@link TvInputManager.Session} associated with this callback.
- * @param timeMs The start playback position of the time shifted program, in milliseconds
- * since the epoch.
+ * @param timeMs The start position for time shifting, in milliseconds since the epoch.
*/
public void onTimeShiftStartPositionChanged(Session session, long timeMs) {
}
/**
- * This is called when the current playback position is changed.
+ * This is called when the current position for time shifting is changed.
*
* @param session A {@link TvInputManager.Session} associated with this callback.
- * @param timeMs The current playback position of the time shifted program, in milliseconds
- * since the epoch.
+ * @param timeMs The current position for time shifting, in milliseconds since the epoch.
*/
public void onTimeShiftCurrentPositionChanged(Session session, long timeMs) {
}
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 97ef6d8..e134635 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -16,6 +16,7 @@
package android.media.tv;
+import android.annotation.FloatRange;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -823,7 +824,7 @@
*
* @param volume A volume value between {@code 0.0f} to {@code 1.0f}.
*/
- public abstract void onSetStreamVolume(float volume);
+ public abstract void onSetStreamVolume(@FloatRange(from = 0.0, to = 1.0) float volume);
/**
* Tunes to a given channel.
@@ -995,15 +996,18 @@
}
/**
- * Returns the start playback position for time shifting, in milliseconds since the epoch.
+ * Returns the start position for time shifting, in milliseconds since the epoch.
* Returns {@link TvInputManager#TIME_SHIFT_INVALID_TIME} if the position is unknown at the
* moment.
*
- * <p>The start playback position of the time shifted program should be adjusted when the
- * implementation cannot retain the whole recorded program due to some reason (e.g.
- * limitation on storage space). It is the earliest possible time position that the user can
- * seek to, thus failure to notifying its change immediately might result in bad experience
- * where the application allows the user to seek to an invalid time position.
+ * <p>The start position for time shifting indicates the earliest possible time the user can
+ * seek to. Initially this is equivalent to the time when the implementation starts
+ * recording. Later it may be adjusted because there is insufficient space or the duration
+ * of recording is limited by the implementation. The application does not allow the user to
+ * seek to a position earlier than the start position.
+ *
+ * <p>For playback of a recorded program initiated by {@link #onTimeShiftPlay(Uri)}, the
+ * start position is the time when playback starts. It does not change.
*
* @see #onTimeShiftPlay(Uri)
* @see #onTimeShiftResume()
@@ -1017,13 +1021,13 @@
}
/**
- * Returns the current playback position for time shifting, in milliseconds since the epoch.
+ * Returns the current position for time shifting, in milliseconds since the epoch.
* Returns {@link TvInputManager#TIME_SHIFT_INVALID_TIME} if the position is unknown at the
* moment.
*
- * <p>Note that the current playback position should be equal to or greater than the start
- * playback position reported by {@link #onTimeShiftGetStartPosition}. Failure to notifying
- * the correct current position might lead to bad user experience.
+ * <p>The current position for time shifting is the same as the current position of
+ * playback. It should be equal to or greater than the start position reported by
+ * {@link #onTimeShiftGetStartPosition()}.
*
* @see #onTimeShiftPlay(Uri)
* @see #onTimeShiftResume()
diff --git a/media/java/android/media/tv/TvTrackInfo.java b/media/java/android/media/tv/TvTrackInfo.java
index e623353..c9c881c 100644
--- a/media/java/android/media/tv/TvTrackInfo.java
+++ b/media/java/android/media/tv/TvTrackInfo.java
@@ -16,17 +16,29 @@
package android.media.tv;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import com.android.internal.util.Preconditions;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
/**
* Encapsulates the format of tracks played in {@link TvInputService}.
*/
public final class TvTrackInfo implements Parcelable {
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({TYPE_AUDIO, TYPE_VIDEO, TYPE_SUBTITLE})
+ public @interface Type {}
+
/**
* The type value for audio tracks.
*/
@@ -93,6 +105,7 @@
* Returns the type of the track. The type should be one of the followings:
* {@link #TYPE_AUDIO}, {@link #TYPE_VIDEO} and {@link #TYPE_SUBTITLE}.
*/
+ @Type
public final int getType() {
return mType;
}
@@ -245,6 +258,37 @@
dest.writeBundle(mExtra);
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof TvTrackInfo)) {
+ return false;
+ }
+
+ TvTrackInfo obj = (TvTrackInfo) o;
+ return TextUtils.equals(mId, obj.mId)
+ && mType == obj.mType
+ && TextUtils.equals(mLanguage, obj.mLanguage)
+ && TextUtils.equals(mDescription, obj.mDescription)
+ && Objects.equals(mExtra, obj.mExtra)
+ && (mType == TYPE_AUDIO
+ ? mAudioChannelCount == obj.mAudioChannelCount
+ && mAudioSampleRate == obj.mAudioSampleRate
+ : (mType == TYPE_VIDEO
+ ? mVideoWidth == obj.mVideoWidth
+ && mVideoHeight == obj.mVideoHeight
+ && mVideoFrameRate == obj.mVideoFrameRate
+ && mVideoPixelAspectRatio == obj.mVideoPixelAspectRatio : true));
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(mId);
+ }
+
public static final Parcelable.Creator<TvTrackInfo> CREATOR =
new Parcelable.Creator<TvTrackInfo>() {
@Override
@@ -285,7 +329,7 @@
* @throws IllegalArgumentException if the type is not any of {@link #TYPE_AUDIO},
* {@link #TYPE_VIDEO} and {@link #TYPE_SUBTITLE}
*/
- public Builder(int type, @NonNull String id) {
+ public Builder(@Type int type, @NonNull String id) {
if (type != TYPE_AUDIO
&& type != TYPE_VIDEO
&& type != TYPE_SUBTITLE) {
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 02ee0cc..10cec1f 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -16,6 +16,7 @@
package android.media.tv;
+import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -271,7 +272,7 @@
*
* @param volume A volume value between {@code 0.0f} to {@code 1.0f}.
*/
- public void setStreamVolume(float volume) {
+ public void setStreamVolume(@FloatRange(from = 0.0, to = 1.0) float volume) {
if (DEBUG) Log.d(TAG, "setStreamVolume(" + volume + ")");
mStreamVolume = volume;
if (mSession == null) {
@@ -847,32 +848,34 @@
public abstract static class TimeShiftPositionCallback {
/**
- * This is called when the start playback position is changed.
+ * This is called when the start position for time shifting has changed.
*
- * <p>The start playback position of the time shifted program can be adjusted by the TV
- * input when it cannot retain the whole recorded program due to some reason (e.g.
- * limitation on storage space). The application should not allow the user to seek to a
- * position earlier than the start position.
+ * <p>The start position for time shifting indicates the earliest possible time the user can
+ * seek to. Initially this is equivalent to the time when the underlying TV input starts
+ * recording. Later it may be adjusted because there is insufficient space or the duration
+ * of recording is limited. The application must not allow the user to seek to a position
+ * earlier than the start position.
*
- * <p>Note that {@code timeMs} is not relative time in the program but wall-clock time,
- * which is intended to avoid calling this method unnecessarily around program boundaries.
+ * <p>For playback of a recorded program initiated by {@link #timeShiftPlay(String, Uri)},
+ * the start position is the time when playback starts. It does not change.
*
* @param inputId The ID of the TV input bound to this view.
- * @param timeMs The start playback position of the time shifted program, in milliseconds
- * since the epoch.
+ * @param timeMs The start position for time shifting, in milliseconds since the epoch.
*/
public void onTimeShiftStartPositionChanged(String inputId, long timeMs) {
}
/**
- * This is called when the current playback position is changed.
+ * This is called when the current position for time shifting has changed.
*
- * <p>Note that {@code timeMs} is not relative time in the program but wall-clock time,
- * which is intended to avoid calling this method unnecessarily around program boundaries.
+ * <p>The current position for time shifting is the same as the current position of
+ * playback. During playback, the current position changes continuously. When paused, it
+ * does not change.
+ *
+ * <p>Note that {@code timeMs} is wall-clock time.
*
* @param inputId The ID of the TV input bound to this view.
- * @param timeMs The current playback position of the time shifted program, in milliseconds
- * since the epoch.
+ * @param timeMs The current position for time shifting, in milliseconds since the epoch.
*/
public void onTimeShiftCurrentPositionChanged(String inputId, long timeMs) {
}
diff --git a/media/jni/soundpool/SoundPoolThread.h b/media/jni/soundpool/SoundPoolThread.h
index d388388..9096aeb 100644
--- a/media/jni/soundpool/SoundPoolThread.h
+++ b/media/jni/soundpool/SoundPoolThread.h
@@ -47,7 +47,7 @@
void write(SoundPoolMsg msg);
private:
- static const size_t maxMessages = 5;
+ static const size_t maxMessages = 128;
static int beginThread(void* arg);
int run();
diff --git a/packages/DocumentsUI/Android.mk b/packages/DocumentsUI/Android.mk
index 3197abd..568e200 100644
--- a/packages/DocumentsUI/Android.mk
+++ b/packages/DocumentsUI/Android.mk
@@ -2,6 +2,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
+LOCAL_PRIVILEGED_MODULE := true
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/packages/DocumentsUI/res/color/item_root_icon.xml b/packages/DocumentsUI/res/color/item_root_icon.xml
index 0aa2c13..e1d7e61 100644
--- a/packages/DocumentsUI/res/color/item_root_icon.xml
+++ b/packages/DocumentsUI/res/color/item_root_icon.xml
@@ -15,5 +15,10 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@*android:color/secondary_text_material_light" />
+ <item
+ android:state_activated="false"
+ android:color="@*android:color/secondary_text_material_light" />
+ <item
+ android:state_activated="true"
+ android:color="@color/root_activated_color" />
</selector>
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..4be7dc8 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..77cc59d 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/src/com/android/documentsui/DocumentClipper.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
index 15bfc3b..059b5e0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
@@ -32,6 +32,7 @@
import libcore.io.IoUtils;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -76,7 +77,8 @@
* This should be run from inside an AsyncTask.
*/
public List<DocumentInfo> getClippedDocuments() {
- return getDocumentsFromClipData(mClipboard.getPrimaryClip());
+ ClipData data = mClipboard.getPrimaryClip();
+ return data == null ? Collections.EMPTY_LIST : getDocumentsFromClipData(data);
}
/**
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 40b54d3..7a7d3a1 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -232,12 +232,13 @@
final MenuItem list = menu.findItem(R.id.menu_list);
final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
- boolean recents = cwd == null;
- createDir.setVisible(picking && !recents && cwd.isCreateSupported());
+ createDir.setVisible(picking);
+ createDir.setEnabled(canCreateDirectory());
// No display options in recent directories
- if (picking && recents) {
+ boolean inRecents = cwd == null;
+ if (picking && inRecents) {
grid.setVisible(false);
list.setVisible(false);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index b34af0b..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);
@@ -276,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:
@@ -297,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);
@@ -311,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();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java b/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
index f6fe47b..3373c23 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
@@ -147,17 +147,13 @@
}
}
- // Hamburger if drawer is present, else root icon, or sad nullness.
+ // Hamburger if drawer is present, else sad nullness.
private @Nullable Drawable getActionBarIcon() {
if (mDrawer.isPresent()) {
return mToolbar.getContext().getDrawable(R.drawable.ic_hamburger);
} else {
- RootInfo root = mEnv.getCurrentRoot();
- if (root != null) {
- return root.loadToolbarIcon(mToolbar.getContext());
- }
+ return null;
}
- return null;
}
void revealRootsDrawer(boolean open) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
index 8fcd9d1..babde99 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
@@ -17,7 +17,6 @@
package com.android.documentsui;
import static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.Shared.TAG;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
import android.content.ClipData;
@@ -45,6 +44,8 @@
* Provides support for gather a list of quick-viewable files into a quick view intent.
*/
final class QuickViewIntentBuilder {
+
+ private static final String TAG = "QuickViewIntentBuilder";
private static final int MAX_CLIP_ITEMS = 1000;
private final DocumentInfo mDocument;
@@ -127,8 +128,18 @@
for (int i = 0; i < siblingIds.length; i++) {
cursor = mModel.getItem(siblingIds[i]);
+ if (cursor == null) {
+ if (DEBUG) Log.d(TAG,
+ "Unable to obtain cursor for sibling document, modelId: "
+ + siblingIds[i]);
+ continue;
+ }
+
mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
if (Document.MIME_TYPE_DIR.equals(mimeType)) {
+ if (DEBUG) Log.d(TAG,
+ "Skipping directory, not supported by quick view. modelId: "
+ + siblingIds[i]);
continue;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
index 0e27622..2be93b8 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
@@ -17,6 +17,7 @@
package com.android.documentsui;
import static com.android.documentsui.Shared.TAG;
+import static com.android.documentsui.State.ACTION_CREATE;
import android.app.Fragment;
import android.app.FragmentManager;
@@ -107,8 +108,9 @@
mAdapter.update(data);
// When launched into empty recents, show drawer
- if (mAdapter.isEmpty() && !state.hasLocationChanged() &&
- context instanceof DocumentsActivity) {
+ if (mAdapter.isEmpty() && !state.hasLocationChanged()
+ && state.action != ACTION_CREATE
+ && context instanceof DocumentsActivity) {
((DocumentsActivity) context).setRootsDrawerOpen(true);
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
index f3b750a..d830c61 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
@@ -84,6 +84,13 @@
new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
+ // Only handle key-down events. This is simpler, consistent with most other
+ // UIs, and enables the handling of repeated key events from holding down a
+ // key.
+ if (event.getAction() != KeyEvent.ACTION_DOWN) {
+ return false;
+ }
+
if (keyCode == KeyEvent.KEYCODE_ENTER && mSave.isEnabled()) {
performSave();
return true;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index bc2133e..ccb2886 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -351,7 +351,10 @@
private boolean handleViewItem(String id) {
final Cursor cursor = mModel.getItem(id);
- assert(cursor != null);
+ if (cursor == null) {
+ Log.w(TAG, "Can't view item. Can't obtain cursor for modeId" + id);
+ return false;
+ }
final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
@@ -465,11 +468,14 @@
public boolean onBeforeItemStateChange(String modelId, boolean selected) {
if (selected) {
final Cursor cursor = mModel.getItem(modelId);
-
- assert(cursor != null);
+ if (cursor == null) {
+ Log.w(TAG, "Can't obtain cursor for modelId: " + modelId);
+ return false;
+ }
final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
+
return mTuner.canSelectType(docMimeType, docFlags);
}
return true;
@@ -479,7 +485,7 @@
public void onItemStateChanged(String modelId, boolean selected) {
final Cursor cursor = mModel.getItem(modelId);
if (cursor == null) {
- Log.e(TAG, "Model returned null cursor for document: " + modelId
+ Log.w(TAG, "Model returned null cursor for document: " + modelId
+ ". Ignoring state changed event.");
return;
}
@@ -518,6 +524,7 @@
}
if (mActionMode != null) {
+ assert(!mSelected.isEmpty());
final String title = Shared.getQuantityString(getActivity(),
R.plurals.elements_selected, mSelected.size());
mActionMode.setTitle(title);
@@ -803,6 +810,8 @@
// the user cancels the delete.
if (mActionMode != null) {
mActionMode.finish();
+ } else {
+ Log.w(TAG, "Action mode is null before deleting documents.");
}
// Hide the files in the UI...since the operation
// might be queued up on FileOperationService.
@@ -833,6 +842,15 @@
getActivity(),
DocumentsActivity.class);
+
+ // Relay any config overrides bits present in the original intent.
+ Intent original = getActivity().getIntent();
+ if (original != null && original.hasExtra(Shared.EXTRA_PRODUCTIVITY_MODE)) {
+ intent.putExtra(
+ Shared.EXTRA_PRODUCTIVITY_MODE,
+ original.getBooleanExtra(Shared.EXTRA_PRODUCTIVITY_MODE, false));
+ }
+
// Set an appropriate title on the drawer when it is shown in the picker.
// Coupled with the fact that we auto-open the drawer for copy/move operations
// it should basically be the thing people see first.
@@ -1095,6 +1113,10 @@
List<String> enabled = new ArrayList<String>();
for (String id : mAdapter.getModelIds()) {
Cursor cursor = getModel().getItem(id);
+ if (cursor == null) {
+ Log.w(TAG, "Skipping selection. Can't obtain cursor for modeId: " + id);
+ continue;
+ }
String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
if (isDocumentEnabled(docMimeType, docFlags)) {
@@ -1157,14 +1179,23 @@
case DragEvent.ACTION_DROP:
// After a drop event, always stop highlighting the target.
setDropTargetHighlight(v, false);
+
+ ClipData clipData = event.getClipData();
+ if (clipData == null) {
+ Log.w(TAG, "Received invalid drop event with null clipdata. Ignoring.");
+ return false;
+ }
+
// Don't copy from the cwd into the cwd. Note: this currently doesn't work for
// multi-window drag, because localState isn't carried over from one process to
// another.
Object src = event.getLocalState();
DocumentInfo dst = getDestination(v);
if (Objects.equals(src, dst)) {
+ if (DEBUG) Log.d(TAG, "Drop target same as source. Ignoring.");
return false;
}
+
// 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.
@@ -1173,7 +1204,8 @@
Metrics.logUserAction(getContext(),
src == null ? Metrics.USER_ACTION_DRAG_N_DROP_MULTI_WINDOW
: Metrics.USER_ACTION_DRAG_N_DROP);
- copyFromClipData(event.getClipData(), dst);
+
+ copyFromClipData(clipData, dst);
return true;
}
return false;
@@ -1183,7 +1215,10 @@
String id = getModelId(v);
if (id != null) {
Cursor dstCursor = mModel.getItem(id);
- assert(dstCursor != null);
+ if (dstCursor == null) {
+ Log.w(TAG, "Invalid destination. Can't obtain cursor for modelId: " + id);
+ return null;
+ }
return DocumentInfo.fromDirectoryCursor(dstCursor);
}
@@ -1256,8 +1291,10 @@
}
final Cursor cursor = mModel.getItem(modelId);
-
- assert(cursor != null);
+ if (cursor == null) {
+ Log.w(TAG, "Undraggable document. Can't obtain cursor for modelId " + modelId);
+ return Collections.EMPTY_LIST;
+ }
return Lists.newArrayList(
DocumentInfo.fromDirectoryCursor(cursor));
@@ -1386,7 +1423,7 @@
// Handle range selection adjustments. Extending the selection will adjust the
// bounds of the in-progress range selection. Each time an unshifted navigation
// event is received, the range selection is restarted.
- if (shouldExtendSelection(event)) {
+ if (shouldExtendSelection(doc, event)) {
if (!mSelectionManager.isRangeSelectionActive()) {
// Start a range selection if one isn't active
mSelectionManager.startRangeSelection(doc.getAdapterPosition());
@@ -1412,7 +1449,8 @@
// 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()) {
- deleteDocuments(mSelectionManager.getSelection());
+ Selection selection = mSelectionManager.getSelection(new Selection());
+ deleteDocuments(selection);
}
// Always handle the key, even if there was nothing to delete. This is a
// precaution to prevent other handlers from potentially picking up the event
@@ -1423,9 +1461,22 @@
return false;
}
- private boolean shouldExtendSelection(KeyEvent event) {
- return Events.isNavigationKeyCode(event.getKeyCode()) &&
- event.isShiftPressed();
+ private boolean shouldExtendSelection(DocumentHolder doc, KeyEvent event) {
+ if (!Events.isNavigationKeyCode(event.getKeyCode()) || !event.isShiftPressed()) {
+ return false;
+ }
+
+ // TODO: Combine this method with onBeforeItemStateChange, as both of them are almost
+ // the same, and responsible for the same thing (whether to select or not).
+ final Cursor cursor = mModel.getItem(doc.modelId);
+ if (cursor == null) {
+ Log.w(TAG, "Couldn't obtain cursor for modelId: " + doc.modelId);
+ return false;
+ }
+
+ final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
+ final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
+ return mTuner.canSelectType(docMimeType, docFlags);
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
index 450341f..2288fe74 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
@@ -139,11 +139,13 @@
}
// Do everything in global coordinates - it makes things simpler.
- Rect rect = new Rect();
- mSelectionHotspot.getGlobalVisibleRect(rect);
+ int[] coords = new int[2];
+ mSelectionHotspot.getLocationOnScreen(coords);
+ Rect rect = new Rect(coords[0], coords[1], coords[0] + mSelectionHotspot.getWidth(),
+ coords[1] + mSelectionHotspot.getHeight());
// If the tap occurred within the icon rect, consider it a selection.
- if (rect.contains((int)event.getRawX(), (int)event.getRawY())) {
+ if (rect.contains((int) event.getRawX(), (int) event.getRawY())) {
return mEventListener.onSelect(this);
} else {
return mEventListener.onActivate(this);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java
index ac05c05..f274df3 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FocusManager.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.content.Context;
+import android.database.Cursor;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
@@ -476,9 +477,9 @@
List<String> index = new ArrayList<>(itemCount);
for (int i = 0; i < itemCount; i++) {
String modelId = mAdapter.getModelId(i);
- if (modelId != null) {
- String title =
- getCursorString(mModel.getItem(modelId), Document.COLUMN_DISPLAY_NAME);
+ Cursor cursor = mModel.getItem(modelId);
+ if (modelId != null && cursor != null) {
+ String title = getCursorString(cursor, Document.COLUMN_DISPLAY_NAME);
// Perform case-insensitive search.
index.add(title.toLowerCase());
} else {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
index 016cc9e..e3eae33 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
@@ -90,6 +90,10 @@
*/
private static final class DocumentsTuner extends FragmentTuner {
+ // We use this to keep track of whether a model has been previously loaded or not so we can
+ // open the drawer on empty directories on first launch
+ private boolean mModelPreviousLoaded;
+
public DocumentsTuner(Context context, State state) {
super(context, state);
}
@@ -178,10 +182,12 @@
showDrawer = true;
}
- if (showDrawer && !mState.hasInitialLocationChanged() && !isSearch) {
+ if (showDrawer && !mState.hasInitialLocationChanged() && !isSearch
+ && !mModelPreviousLoaded) {
// This noops on layouts without drawer, so no need to guard.
((BaseActivity) mContext).setRootsDrawerOpen(true);
}
+ mModelPreviousLoaded = true;
}
@Override
@@ -195,6 +201,10 @@
*/
private static final class FilesTuner extends FragmentTuner {
+ // We use this to keep track of whether a model has been previously loaded or not so we can
+ // open the drawer on empty directories on first launch
+ private boolean mModelPreviousLoaded;
+
public FilesTuner(Context context, State state) {
super(context, state);
}
@@ -230,10 +240,12 @@
@Override
void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch) {
// When launched into empty root, open drawer.
- if (model.isEmpty() && !mState.hasInitialLocationChanged() && !isSearch) {
+ if (model.isEmpty() && !mState.hasInitialLocationChanged() && !isSearch
+ && !mModelPreviousLoaded) {
// This noops on layouts without drawer, so no need to guard.
((BaseActivity) mContext).setRootsDrawerOpen(true);
}
+ mModelPreviousLoaded = true;
}
@Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
index 3642b01..e2a28ad9a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
@@ -37,6 +37,7 @@
import com.android.documentsui.model.DocumentInfo;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -403,11 +404,18 @@
public @Nullable Cursor getItem(String modelId) {
Integer pos = mPositions.get(modelId);
- if (pos != null) {
- mCursor.moveToPosition(pos);
- return mCursor;
+ if (pos == null) {
+ if (DEBUG) Log.d(TAG, "Unabled to find cursor position for modelId: " + modelId);
+ return null;
}
- return null;
+
+ if (!mCursor.moveToPosition(pos)) {
+ if (DEBUG) Log.d(TAG,
+ "Unabled to move cursor to position " + pos + " for modelId: " + modelId);
+ return null;
+ }
+
+ return mCursor;
}
boolean isEmpty() {
@@ -424,8 +432,11 @@
final List<DocumentInfo> docs = new ArrayList<>(size);
for (String modelId: items.getAll()) {
final Cursor cursor = getItem(modelId);
- assert(cursor != null);
-
+ if (cursor == null) {
+ Log.w(TAG,
+ "Skipping document. Unabled to obtain cursor for modelId: " + modelId);
+ continue;
+ }
docs.add(DocumentInfo.fromDirectoryCursor(cursor));
}
return docs;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
index 1285b34..35d8988 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
@@ -378,8 +378,8 @@
* @param pos The anchor position for the selection range.
*/
void startRangeSelection(int pos) {
- attemptSelect(mAdapter.getModelId(pos));
- setSelectionRangeBegin(pos);
+ attemptSelect(mAdapter.getModelId(pos));
+ setSelectionRangeBegin(pos);
}
/**
@@ -1268,6 +1268,11 @@
notifySelectionChanged();
}
+ @Override
+ public boolean onBeforeItemStateChange(String id, boolean nextState) {
+ return notifyBeforeItemStateChange(id, nextState);
+ }
+
private class ViewScroller implements Runnable {
/**
* The number of milliseconds of scrolling at which scroll speed continues to increase.
@@ -1655,7 +1660,9 @@
if (id != null) {
// The adapter inserts items for UI layout purposes that aren't associated
// with files. Those will have a null model ID. Don't select them.
- mSelection.add(id);
+ if (canSelect(id)) {
+ mSelection.add(id);
+ }
}
if (isPossiblePositionNearestOrigin(column, columnStartIndex, columnEndIndex,
row, rowStartIndex, rowEndIndex)) {
@@ -1669,6 +1676,21 @@
}
/**
+ * @return True if the item is selectable.
+ */
+ private boolean canSelect(String id) {
+ // TODO: Simplify the logic, so the check whether we can select is done in one place.
+ // Consider injecting FragmentTuner, or move the checks from MultiSelectManager to
+ // Selection.
+ for (OnSelectionChangedListener listener : mOnSelectionChangedListeners) {
+ if (!listener.onBeforeItemStateChange(id, true)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
* @return Returns true if the position is the nearest to the origin, or, in the case of the
* lower-right corner, whether it is possible that the position is the nearest to the
* origin. See comment below for reasoning for this special case.
@@ -1700,6 +1722,7 @@
*/
static interface OnSelectionChangedListener {
public void onSelectionChanged(Set<String> updatedSelection);
+ public boolean onBeforeItemStateChange(String id, boolean nextState);
}
void addOnSelectionChangedListener(OnSelectionChangedListener listener) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
index 31ce837..3a86a51 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
@@ -139,11 +139,13 @@
};
public static DocumentInfo fromDirectoryCursor(Cursor cursor) {
+ assert(cursor != null);
final String authority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY);
return fromCursor(cursor, authority);
}
public static DocumentInfo fromCursor(Cursor cursor, String authority) {
+ assert(cursor != null);
final DocumentInfo info = new DocumentInfo();
info.updateFromCursor(cursor, authority);
return info;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index 0709652..d54bdfd 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -334,15 +334,6 @@
}
}
- public Drawable loadToolbarIcon(Context context) {
- if (derivedIcon != 0) {
- return IconUtils.applyTintAttr(context, derivedIcon,
- android.R.attr.colorControlNormal);
- } else {
- return IconUtils.loadPackageIcon(context, authority, icon);
- }
- }
-
@Override
public boolean equals(Object o) {
if (o == null) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java b/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java
index 580fa38..871e135 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java
@@ -229,31 +229,32 @@
@OpType int operationType, String id, List<DocumentInfo> srcs, DocumentInfo srcParent,
DocumentStack stack) {
+ if (srcs.isEmpty()) {
+ Log.w(TAG, "Ignoring job request with empty srcs list. Id: " + id);
+ return null;
+ }
+
if (mRunning.containsKey(id)) {
Log.w(TAG, "Duplicate job id: " + id
+ ". Ignoring job request for srcs: " + srcs + ", stack: " + stack + ".");
return null;
}
- Job job = null;
switch (operationType) {
case OPERATION_COPY:
- job = jobFactory.createCopy(this, getApplicationContext(), this, id, stack, srcs);
- break;
+ return jobFactory.createCopy(
+ this, getApplicationContext(), this, id, stack, srcs);
case OPERATION_MOVE:
- job = jobFactory.createMove(this, getApplicationContext(), this, id, stack, srcs,
+ return jobFactory.createMove(
+ this, getApplicationContext(), this, id, stack, srcs,
srcParent);
- break;
case OPERATION_DELETE:
- job = jobFactory.createDelete(this, getApplicationContext(), this, id, stack, srcs,
+ return jobFactory.createDelete(
+ this, getApplicationContext(), this, id, stack, srcs,
srcParent);
- break;
default:
throw new UnsupportedOperationException();
}
-
- assert(job != null);
- return job;
}
@GuardedBy("mRunning")
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/Job.java b/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
index c723ac6..b4f1299 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
@@ -291,18 +291,24 @@
Job createCopy(Context service, Context appContext, Listener listener,
String id, DocumentStack stack, List<DocumentInfo> srcs) {
+ assert(!srcs.isEmpty());
+ assert(stack.peek().isCreateSupported());
return new CopyJob(service, appContext, listener, id, stack, srcs);
}
Job createMove(Context service, Context appContext, Listener listener,
String id, DocumentStack stack, List<DocumentInfo> srcs,
DocumentInfo srcParent) {
+ assert(!srcs.isEmpty());
+ assert(stack.peek().isCreateSupported());
return new MoveJob(service, appContext, listener, id, stack, srcs, srcParent);
}
Job createDelete(Context service, Context appContext, Listener listener,
String id, DocumentStack stack, List<DocumentInfo> srcs,
DocumentInfo srcParent) {
+ assert(!srcs.isEmpty());
+ assert(stack.peek().isDirectory()); // we can't currently delete from archives.
return new DeleteJob(service, appContext, listener, id, stack, srcs, srcParent);
}
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
index 0c0e0b7..cc119fe 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
@@ -76,6 +76,11 @@
public void onSelectionChanged(Set<String> updatedSelection) {
lastSelection = updatedSelection;
}
+
+ @Override
+ public boolean onBeforeItemStateChange(String id, boolean nextState) {
+ return true;
+ }
});
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/services/FileOperationServiceTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/services/FileOperationServiceTest.java
index 4d5392e..96d963f 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/services/FileOperationServiceTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/services/FileOperationServiceTest.java
@@ -79,6 +79,16 @@
mJobFactory.assertAllJobsStarted();
}
+ public void testRunsJobs_AfterExceptionInJobCreation() throws Exception {
+ startService(createCopyIntent(new ArrayList<DocumentInfo>(), BETA_DOC));
+ startService(createCopyIntent(newArrayList(GAMMA_DOC), DELTA_DOC));
+
+ mJobFactory.assertJobsCreated(1);
+
+ mExecutor.runAll();
+ mJobFactory.assertAllJobsStarted();
+ }
+
public void testRunsJobs_AfterFailure() throws Exception {
startService(createCopyIntent(newArrayList(ALPHA_DOC), BETA_DOC));
startService(createCopyIntent(newArrayList(GAMMA_DOC), DELTA_DOC));
@@ -182,9 +192,18 @@
}
}
+ void assertJobsCreated(int expected) {
+ assertEquals(expected, jobs.size());
+ }
+
@Override
Job createCopy(Context service, Context appContext, Listener listener, String id,
DocumentStack stack, List<DocumentInfo> srcs) {
+
+ if (srcs.isEmpty()) {
+ throw new RuntimeException("Empty srcs not supported!");
+ }
+
TestJob job = new TestJob(service, appContext, listener, OPERATION_COPY, id, stack);
jobs.add(job);
return job;
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/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml
index 61966b2..09fec81 100644
--- a/packages/Keyguard/res/values/strings.xml
+++ b/packages/Keyguard/res/values/strings.xml
@@ -334,6 +334,14 @@
<!-- An explanation text that the password needs to be entered since profiles have just been switched. [CHAR LIMIT=80] -->
<string name="kg_prompt_reason_switch_profiles_password">Password required when you switch profiles</string>
+ <!-- An explanation text that the credential needs to be entered because a device admin has
+ locked the device. [CHAR LIMIT=80] -->
+ <string name="kg_prompt_reason_device_admin">Device administrator locked device</string>
+
+ <!-- An explanation text that the credential needs to be entered because the user has clicked
+ the force lock button. [CHAR LIMIT=80] -->
+ <string name="kg_prompt_reason_user_request">Device was locked manually</string>
+
<!-- An explanation text that the pattern needs to be solved since it hasn't been solved in a while. [CHAR LIMIT=80]-->
<plurals name="kg_prompt_reason_time_pattern">
<item quantity="one">Device hasn\'t been unlocked for <xliff:g id="number">%d</xliff:g> hour. Confirm pattern.</item>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
index 63dec8b..189f5b7 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
@@ -117,6 +117,10 @@
return R.string.kg_prompt_reason_restart_password;
case PROMPT_REASON_TIMEOUT:
return R.string.kg_prompt_reason_timeout_password;
+ case PROMPT_REASON_DEVICE_ADMIN:
+ return R.string.kg_prompt_reason_device_admin;
+ case PROMPT_REASON_USER_REQUEST:
+ return R.string.kg_prompt_reason_user_request;
case PROMPT_REASON_NONE:
return 0;
default:
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index be2701d..e070492 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -339,6 +339,14 @@
mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_timeout_pattern,
true /* important */);
break;
+ case PROMPT_REASON_DEVICE_ADMIN:
+ mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_device_admin,
+ true /* important */);
+ break;
+ case PROMPT_REASON_USER_REQUEST:
+ mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_user_request,
+ true /* important */);
+ break;
case PROMPT_REASON_NONE:
break;
default:
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
index fe98cb8..f14290a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -108,6 +108,10 @@
return R.string.kg_prompt_reason_restart_pin;
case PROMPT_REASON_TIMEOUT:
return R.string.kg_prompt_reason_timeout_pin;
+ case PROMPT_REASON_DEVICE_ADMIN:
+ return R.string.kg_prompt_reason_device_admin;
+ case PROMPT_REASON_USER_REQUEST:
+ return R.string.kg_prompt_reason_user_request;
case PROMPT_REASON_NONE:
return 0;
default:
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
index 246b95de..6ed4ea1 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);
+ }
}
/**
@@ -183,9 +196,10 @@
}
task.loadObjectInfoList(NUM_LOADING_ENTRIES);
final boolean shouldNotify =
- task.mLastNotified.getTime() <
- new Date().getTime() - NOTIFY_PERIOD_MS ||
- task.getState() != LoaderTask.STATE_LOADING;
+ task.getState() != LoaderTask.STATE_CANCELLED &&
+ (task.mLastNotified.getTime() <
+ new Date().getTime() - NOTIFY_PERIOD_MS ||
+ task.getState() != LoaderTask.STATE_LOADING);
if (shouldNotify) {
task.notify(mResolver);
}
@@ -205,14 +219,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 +229,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 +240,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 +268,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 +300,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 +369,10 @@
}
}
synchronized (this) {
+ // Check if the task is cancelled or not.
+ if (mState != STATE_LOADING) {
+ return;
+ }
try {
mDatabase.getMapper().putChildDocuments(
mIdentifier.mDeviceId,
@@ -403,6 +402,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/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index 00d31a7..90dd440 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -16,6 +16,7 @@
package com.android.mtp;
+import android.annotation.Nullable;
import android.content.Context;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
@@ -27,6 +28,7 @@
import android.mtp.MtpDeviceInfo;
import android.mtp.MtpEvent;
import android.mtp.MtpObjectInfo;
+import android.mtp.MtpStorageInfo;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
import android.util.Log;
@@ -80,9 +82,7 @@
}
}
- if (rawDevice == null) {
- throw new IOException("Not found USB device: " + deviceId);
- }
+ ensureNotNull(rawDevice, "Not found USB device: " + deviceId);
if (!mManager.hasPermission(rawDevice)) {
mManager.grantPermission(rawDevice);
@@ -93,10 +93,9 @@
final MtpDevice device = new MtpDevice(rawDevice);
- final UsbDeviceConnection connection = mManager.openDevice(rawDevice);
- if (connection == null) {
- throw new IOException("Failed to open a USB connection.");
- }
+ final UsbDeviceConnection connection = ensureNotNull(
+ mManager.openDevice(rawDevice),
+ "Failed to open a USB connection.");
if (!device.open(connection)) {
// We cannot open connection when another application use the device.
@@ -104,13 +103,11 @@
}
// Handle devices that fail to obtain storages just after opening a MTP session.
- final int[] storageIds = device.getStorageIds();
- if (storageIds == null) {
- throw new IOException("Not found MTP storages in the device.");
- }
+ final int[] storageIds = ensureNotNull(
+ device.getStorageIds(),
+ "Not found MTP storages in the device.");
mDevices.put(deviceId, device);
-
return createDeviceRecord(rawDevice);
}
@@ -133,11 +130,9 @@
MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
final MtpDevice device = getDevice(deviceId);
synchronized (device) {
- final MtpObjectInfo info = device.getObjectInfo(objectHandle);
- if (info == null) {
- throw new IOException("Failed to get object info: " + objectHandle);
- }
- return info;
+ return ensureNotNull(
+ device.getObjectInfo(objectHandle),
+ "Failed to get object info: " + objectHandle);
}
}
@@ -145,12 +140,9 @@
throws IOException {
final MtpDevice device = getDevice(deviceId);
synchronized (device) {
- final int[] handles =
- device.getObjectHandles(storageId, 0 /* all format */, parentObjectHandle);
- if (handles == null) {
- throw new IOException("Failed to fetch object handles.");
- }
- return handles;
+ return ensureNotNull(
+ device.getObjectHandles(storageId, 0 /* all format */, parentObjectHandle),
+ "Failed to fetch object handles.");
}
}
@@ -158,7 +150,9 @@
throws IOException {
final MtpDevice device = getDevice(deviceId);
synchronized (device) {
- return device.getObject(objectHandle, expectedSize);
+ return ensureNotNull(
+ device.getObject(objectHandle, expectedSize),
+ "Failed to fetch object bytes");
}
}
@@ -181,7 +175,9 @@
byte[] getThumbnail(int deviceId, int objectHandle) throws IOException {
final MtpDevice device = getDevice(deviceId);
synchronized (device) {
- return device.getThumbnail(objectHandle);
+ return ensureNotNull(
+ device.getThumbnail(objectHandle),
+ "Failed to obtain thumbnail bytes");
}
}
@@ -216,7 +212,7 @@
final MtpDevice device = getDevice(deviceId);
synchronized (device) {
final int result = (int) device.getParent(objectHandle);
- if (result < 0) {
+ if (result == 0xffffffff) {
throw new FileNotFoundException("Not found parent object");
}
return result;
@@ -227,7 +223,9 @@
throws IOException {
final MtpDevice device = getDevice(deviceId);
synchronized (device) {
- device.importFile(objectHandle, target);
+ if (!device.importFile(objectHandle, target)) {
+ throw new IOException("Failed to import file to FD");
+ }
}
}
@@ -243,26 +241,25 @@
}
private synchronized MtpDevice getDevice(int deviceId) throws IOException {
- final MtpDevice device = mDevices.get(deviceId);
- if (device == null) {
- throw new IOException("USB device " + deviceId + " is not opened.");
- }
- return device;
+ return ensureNotNull(
+ mDevices.get(deviceId),
+ "USB device " + deviceId + " is not opened.");
}
private MtpRoot[] getRoots(int deviceId) throws IOException {
final MtpDevice device = getDevice(deviceId);
synchronized (device) {
- final int[] storageIds = device.getStorageIds();
- if (storageIds == null) {
- throw new IOException("Failed to obtain storage IDs.");
- }
- final MtpRoot[] results = new MtpRoot[storageIds.length];
+ final int[] storageIds =
+ ensureNotNull(device.getStorageIds(), "Failed to obtain storage IDs.");
+ final ArrayList<MtpRoot> roots = new ArrayList<>();
for (int i = 0; i < storageIds.length; i++) {
- results[i] = new MtpRoot(
- device.getDeviceId(), device.getStorageInfo(storageIds[i]));
+ final MtpStorageInfo info = device.getStorageInfo(storageIds[i]);
+ if (info == null) {
+ continue;
+ }
+ roots.add(new MtpRoot(device.getDeviceId(), info));
}
- return results;
+ return roots.toArray(new MtpRoot[roots.size()]);
}
}
@@ -313,4 +310,12 @@
}
return false;
}
+
+ private static <T> T ensureNotNull(@Nullable T t, String errorMessage) throws IOException {
+ if (t != null) {
+ return t;
+ } else {
+ throw new IOException(errorMessage);
+ }
+ }
}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
index 45f89e4..a3c6bd7 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,38 @@
}
}
+ public void testCancelTask() throws IOException, InterruptedException, TimeoutException {
+ setUpDocument(mManager,
+ DocumentLoader.NUM_INITIAL_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));
+ }
+
+ final Uri uri = DocumentsContract.buildChildDocumentsUri(
+ MtpDocumentsProvider.AUTHORITY, mParentIdentifier.mDocumentId);
+ assertEquals(0, mResolver.getChangeCount(uri));
+
+ // Clear task while the first iteration is being blocked.
+ mLoader.cancelTask(mParentIdentifier);
+ mManager.unblockDocument(
+ 0, DocumentLoader.NUM_INITIAL_ENTRIES + 1);
+ Thread.sleep(DocumentLoader.NOTIFY_PERIOD_MS);
+ assertEquals(0, mResolver.getChangeCount(uri));
+
+ // Check if it's OK to query invalidated task.
+ try (final Cursor cursor = mLoader.queryChildDocuments(
+ MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier)) {
+ assertTrue(cursor.getExtras().getBoolean(DocumentsContract.EXTRA_LOADING));
+ }
+ mResolver.waitForNotification(uri, 1);
+ }
+
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/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index e7aebdd..c411186 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -320,6 +320,8 @@
mFileProvider, new RemotePrintDocument.RemoteAdapterDeathObserver() {
@Override
public void onDied() {
+ Log.w(LOG_TAG, "Printing app died unexpectedly");
+
// If we are finishing or we are in a state that we do not need any
// data from the printing app, then no need to finish.
if (isFinishing() || (isFinalState(mState) && !mPrintedDocument.isUpdating())) {
diff --git a/packages/SettingsLib/res/layout/restricted_switch_preference.xml b/packages/SettingsLib/res/layout/restricted_switch_preference.xml
new file mode 100644
index 0000000..89dc10b
--- /dev/null
+++ b/packages/SettingsLib/res/layout/restricted_switch_preference.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:gravity="center_vertical"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:background="?android:attr/activatedBackgroundIndicator"
+ android:clipToPadding="false">
+
+ <LinearLayout
+ android:id="@+id/icon_frame"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minWidth="60dp"
+ android:gravity="start|center_vertical"
+ android:orientation="horizontal"
+ android:paddingEnd="12dp"
+ android:paddingTop="4dp"
+ android:paddingBottom="4dp">
+ <com.android.internal.widget.PreferenceImageView
+ android:id="@android:id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:maxWidth="48dp"
+ android:maxHeight="48dp" />
+ </LinearLayout>
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp">
+
+ <TextView android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceListItem"
+ android:ellipsize="marquee" />
+
+ <TextView android:id="@android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/title"
+ android:layout_alignStart="@android:id/title"
+ android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+ android:textColor="?android:attr/textColorSecondary"
+ android:maxLines="10" />
+
+ <TextView android:id="@+id/additional_summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/summary"
+ android:layout_alignStart="@android:id/summary"
+ android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+ android:textColor="?android:attr/textColorSecondary"
+ android:maxLines="10"
+ android:visibility="gone" />
+ </RelativeLayout>
+
+ <!-- Preference should place its actual preference widget here. -->
+ <LinearLayout android:id="@android:id/widget_frame"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="end|center_vertical"
+ android:paddingStart="16dp"
+ android:orientation="vertical" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 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..8526112 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 16e0f44..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..4ae1fb0 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/attrs.xml b/packages/SettingsLib/res/values/attrs.xml
index 4484613..4cdc177 100644
--- a/packages/SettingsLib/res/values/attrs.xml
+++ b/packages/SettingsLib/res/values/attrs.xml
@@ -15,10 +15,18 @@
-->
<resources>
+
<declare-styleable name="RestrictedPreference">
+ <!-- The user restriction on which the preference disabled by admin state will be based on. -->
<attr name="userRestriction" format="string" />
+ <!-- If true then we can use enabled/disabled by admin strings for summary (android.R.id.summary). -->
<attr name="useAdminDisabledSummary" format="boolean" />
+ <!-- If true, an additional summary will be added in addition to the existing summary and
+ this will be used for enabled/disabled by admin strings leaving android.R.id.summary untouched.
+ As such when this is true, useAdminDisabledSummary will be overwritten to false. -->
+ <attr name="useAdditionalSummary" format="boolean" />
</declare-styleable>
+
<declare-styleable name="WifiEncryptionState">
<attr name="state_encrypted" format="boolean" />
</declare-styleable>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 084acac..985fe3c 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -804,7 +804,7 @@
<string name="disabled_by_admin">Disabled by administrator</string>
<!-- Option in navigation drawer that leads to Settings main screen [CHAR LIMIT=30] -->
- <string name="home">Home</string>
+ <string name="home">Settings Home</string>
<string-array name="battery_labels" translatable="false">
<item>0%</item>
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
index f381286..dabbc61 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
@@ -17,12 +17,14 @@
package com.android.settingslib;
import android.content.Context;
+import android.content.res.TypedArray;
import android.os.UserHandle;
import android.support.v4.content.res.TypedArrayUtils;
import android.support.v7.preference.PreferenceManager;
import android.support.v7.preference.PreferenceViewHolder;
import android.support.v14.preference.SwitchPreference;
import android.util.AttributeSet;
+import android.util.TypedValue;
import android.view.View;
import android.widget.TextView;
@@ -34,12 +36,28 @@
*/
public class RestrictedSwitchPreference extends SwitchPreference {
RestrictedPreferenceHelper mHelper;
+ boolean mUseAdditionalSummary = false;
public RestrictedSwitchPreference(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setWidgetLayoutResource(R.layout.restricted_switch_widget);
mHelper = new RestrictedPreferenceHelper(context, this, attrs);
+ if (attrs != null) {
+ final TypedArray attributes = context.obtainStyledAttributes(attrs,
+ R.styleable.RestrictedPreference);
+ final TypedValue useAdditionalSummary =
+ attributes.peekValue(R.styleable.RestrictedPreference_useAdditionalSummary);
+ if (useAdditionalSummary != null) {
+ mUseAdditionalSummary =
+ (useAdditionalSummary.type == TypedValue.TYPE_INT_BOOLEAN
+ && useAdditionalSummary.data != 0);
+ }
+ }
+ if (mUseAdditionalSummary) {
+ setLayoutResource(R.layout.restricted_switch_preference);
+ useAdminDisabledSummary(false);
+ }
}
public RestrictedSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
@@ -67,11 +85,29 @@
if (switchWidget != null) {
switchWidget.setVisibility(isDisabledByAdmin() ? View.GONE : View.VISIBLE);
}
- final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
- if (summaryView != null && isDisabledByAdmin()) {
- summaryView.setText(
- isChecked() ? R.string.enabled_by_admin : R.string.disabled_by_admin);
- summaryView.setVisibility(View.VISIBLE);
+ if (mUseAdditionalSummary) {
+ final TextView additionalSummaryView = (TextView) holder.findViewById(
+ R.id.additional_summary);
+ if (additionalSummaryView != null) {
+ if (isDisabledByAdmin()) {
+ additionalSummaryView.setText(
+ isChecked() ? R.string.enabled_by_admin : R.string.disabled_by_admin);
+ additionalSummaryView.setVisibility(View.VISIBLE);
+ }
+ } else {
+ additionalSummaryView.setVisibility(View.GONE);
+ }
+ } else {
+ final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
+ if (summaryView != null) {
+ if (isDisabledByAdmin()) {
+ summaryView.setText(
+ isChecked() ? R.string.enabled_by_admin : R.string.disabled_by_admin);
+ summaryView.setVisibility(View.VISIBLE);
+ }
+ }
+ // No need to change the visibility to GONE in the else case here since Preference class
+ // would have already changed it if there is no summary to display.
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index d353f31..8c2af45 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -534,6 +534,7 @@
Comparator<AppEntry> mRebuildComparator;
ArrayList<AppEntry> mRebuildResult;
ArrayList<AppEntry> mLastAppList;
+ boolean mRebuildForeground;
Session(Callbacks callbacks) {
mCallbacks = callbacks;
@@ -572,6 +573,11 @@
// Creates a new list of app entries with the given filter and comparator.
public ArrayList<AppEntry> rebuild(AppFilter filter, Comparator<AppEntry> comparator) {
+ return rebuild(filter, comparator, true);
+ }
+
+ public ArrayList<AppEntry> rebuild(AppFilter filter, Comparator<AppEntry> comparator,
+ boolean foreground) {
synchronized (mRebuildSync) {
synchronized (mEntriesMap) {
mRebuildingSessions.add(this);
@@ -579,6 +585,7 @@
mRebuildAsync = false;
mRebuildFilter = filter;
mRebuildComparator = comparator;
+ mRebuildForeground = foreground;
mRebuildResult = null;
if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_REBUILD_LIST)) {
Message msg = mBackgroundHandler.obtainMessage(
@@ -620,10 +627,12 @@
mRebuildRequested = false;
mRebuildFilter = null;
mRebuildComparator = null;
+ if (mRebuildForeground) {
+ Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
+ mRebuildForeground = false;
+ }
}
- Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
-
if (filter != null) {
filter.init();
}
@@ -640,7 +649,10 @@
if (filter == null || filter.filterApp(entry)) {
synchronized (mEntriesMap) {
if (DEBUG_LOCKING) Log.v(TAG, "rebuild acquired lock");
- entry.ensureLabel(mContext);
+ if (comparator != null) {
+ // Only need the label if we are going to be sorting.
+ entry.ensureLabel(mContext);
+ }
if (DEBUG) Log.i(TAG, "Using " + entry.info.packageName + ": " + entry);
filteredApps.add(entry);
if (DEBUG_LOCKING) Log.v(TAG, "rebuild releasing lock");
@@ -648,7 +660,9 @@
}
}
- Collections.sort(filteredApps, comparator);
+ if (comparator != null) {
+ Collections.sort(filteredApps, comparator);
+ }
synchronized (mRebuildSync) {
if (!mRebuildRequested) {
@@ -825,8 +839,18 @@
for (int i = 0; i < mEntriesMap.size(); i++) {
int userId = mEntriesMap.keyAt(i);
- List<ResolveInfo> intents = mPm.queryIntentActivitiesAsUser(launchIntent,
- PackageManager.GET_DISABLED_COMPONENTS, userId);
+ // If we do not specify MATCH_DIRECT_BOOT_AWARE or
+ // MATCH_DIRECT_BOOT_UNAWARE, system will derive and update the flags
+ // according to the user's lock state. When the user is locked, components
+ // with ComponentInfo#directBootAware == false will be filtered. We should
+ // explicitly include both direct boot aware and unaware components here.
+ List<ResolveInfo> intents = mPm.queryIntentActivitiesAsUser(
+ launchIntent,
+ PackageManager.GET_DISABLED_COMPONENTS
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+ userId
+ );
synchronized (mEntriesMap) {
if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_LAUNCHER acquired lock");
HashMap<String, AppEntry> userEntries = mEntriesMap.valueAt(i);
@@ -1102,6 +1126,10 @@
public boolean mounted;
+ /**
+ * Setting this to {@code true} prevents the entry to be filtered by
+ * {@link #FILTER_DOWNLOADED_AND_LAUNCHER}.
+ */
public boolean hasLauncherEntry;
public String getNormalizedLabel() {
@@ -1272,6 +1300,9 @@
}
};
+ /**
+ * Displays a combined list with "downloaded" and "visible in launcher" apps only.
+ */
public static final AppFilter FILTER_DOWNLOADED_AND_LAUNCHER = new AppFilter() {
public void init() {
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index ff70190..bcbc6ac 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -216,6 +216,8 @@
if (sDashboardCategories == null) {
sTileCache = new HashMap<>();
sConfigTracker = new InterestingConfigChanges();
+ // Apply initial current config.
+ sConfigTracker.applyNewConfig(getResources());
sDashboardCategories = TileUtils.getCategories(this, sTileCache);
}
return sDashboardCategories;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 5621642..8dc247a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1324,6 +1324,9 @@
}
private static void appendSettingToCursor(MatrixCursor cursor, Setting setting) {
+ if (setting == null) {
+ return;
+ }
final int columnCount = cursor.getColumnCount();
String[] values = new String[columnCount];
@@ -1831,14 +1834,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();
}
}
}
diff --git a/packages/Shell/res/layout/confirm_repeat.xml b/packages/Shell/res/layout/confirm_repeat.xml
index d12f467..ad90af1 100644
--- a/packages/Shell/res/layout/confirm_repeat.xml
+++ b/packages/Shell/res/layout/confirm_repeat.xml
@@ -38,5 +38,5 @@
android:id="@android:id/checkbox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/bugreport_confirm_repeat" />
+ android:text="@string/bugreport_confirm_dont_repeat" />
</LinearLayout>
diff --git a/packages/Shell/res/values/strings.xml b/packages/Shell/res/values/strings.xml
index 5d90189..95e36fd 100644
--- a/packages/Shell/res/values/strings.xml
+++ b/packages/Shell/res/values/strings.xml
@@ -20,8 +20,6 @@
<string name="bugreport_in_progress_title">Bug report <xliff:g id="id">#%d</xliff:g> is being generated</string>
<!-- Title of notification indicating a bugreport has been successfully captured. [CHAR LIMIT=50] -->
<string name="bugreport_finished_title">Bug report <xliff:g id="id">#%d</xliff:g> captured</string>
- <!-- Title of notification indicating a bugreport has been successfully captured, but screenshot is not finished yet. [CHAR LIMIT=50] -->
- <string name="bugreport_finished_pending_screenshot_title">Bug report <xliff:g id="id">#%d</xliff:g> captured but screenshot pending</string>
<!-- Title of notification indicating a bugreport is being updated before it can be shared. [CHAR LIMIT=50] -->
<string name="bugreport_updating_title">Adding details to the bug report</string>
<!-- Content notification indicating a bugreport is being updated before it can be shared, asking the user to wait [CHAR LIMIT=50] -->
@@ -37,9 +35,9 @@
<string name="bugreport_finished_pending_screenshot_text" product="default">Tap to share your bug report without a screenshot or wait for the screenshot to finish</string>
<!-- Body of dialog informing user about contents of a bugreport. [CHAR LIMIT=NONE] -->
- <string name="bugreport_confirm">Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people you trust.</string>
- <!-- Checkbox that indicates this dialog should be shown again when the next bugreport is taken. [CHAR LIMIT=50] -->
- <string name="bugreport_confirm_repeat">Show this message next time</string>
+ <string name="bugreport_confirm">Bug reports contain data from the system\'s various log files, which may include data you consider sensitive (such as app-usage and location data). Only share bug reports with people and apps you trust.</string>
+ <!-- Checkbox that indicates this dialog should not be shown again when the next bugreport is taken. [CHAR LIMIT=50] -->
+ <string name="bugreport_confirm_dont_repeat">Don\'t show again</string>
<!-- Title for documents backend that offers bugreports. -->
<string name="bugreport_storage_title">Bug reports</string>
diff --git a/packages/Shell/src/com/android/shell/BugreportPrefs.java b/packages/Shell/src/com/android/shell/BugreportPrefs.java
index 3748e89..93690d4 100644
--- a/packages/Shell/src/com/android/shell/BugreportPrefs.java
+++ b/packages/Shell/src/com/android/shell/BugreportPrefs.java
@@ -22,22 +22,24 @@
/**
* Preferences related to bug reports.
*/
-public class BugreportPrefs {
- private static final String PREFS_BUGREPORT = "bugreports";
+final class BugreportPrefs {
+ static final String PREFS_BUGREPORT = "bugreports";
private static final String KEY_WARNING_STATE = "warning-state";
- public static final int STATE_UNKNOWN = 0;
- public static final int STATE_SHOW = 1;
- public static final int STATE_HIDE = 2;
+ static final int STATE_UNKNOWN = 0;
+ // Shows the warning dialog.
+ static final int STATE_SHOW = 1;
+ // Skips the warning dialog.
+ static final int STATE_HIDE = 2;
- public static int getWarningState(Context context, int def) {
+ static int getWarningState(Context context, int def) {
final SharedPreferences prefs = context.getSharedPreferences(
PREFS_BUGREPORT, Context.MODE_PRIVATE);
return prefs.getInt(KEY_WARNING_STATE, def);
}
- public static void setWarningState(Context context, int value) {
+ static void setWarningState(Context context, int value) {
final SharedPreferences prefs = context.getSharedPreferences(
PREFS_BUGREPORT, Context.MODE_PRIVATE);
prefs.edit().putInt(KEY_WARNING_STATE, value).apply();
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 7ca7614..502eed1 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -17,7 +17,8 @@
package com.android.shell;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
-import static com.android.shell.BugreportPrefs.STATE_SHOW;
+import static com.android.shell.BugreportPrefs.STATE_HIDE;
+import static com.android.shell.BugreportPrefs.STATE_UNKNOWN;
import static com.android.shell.BugreportPrefs.getWarningState;
import java.io.BufferedOutputStream;
@@ -220,6 +221,7 @@
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
+ Log.v(TAG, "onStartCommand(): " + dumpIntent(intent));
if (intent != null) {
// Handle it in a separate thread.
final Message msg = mMainHandler.obtainMessage();
@@ -297,6 +299,7 @@
return;
}
final Parcelable parcel = ((Intent) msg.obj).getParcelableExtra(EXTRA_ORIGINAL_INTENT);
+ Log.v(TAG, "handleMessage(): " + dumpIntent((Intent) parcel));
final Intent intent;
if (parcel instanceof Intent) {
// The real intent was passed to BugreportReceiver, which delegated to the service.
@@ -707,7 +710,8 @@
for (int i = 0; i < mProcesses.size(); i++) {
final BugreportInfo info = mProcesses.valueAt(i);
if (info.finished) {
- Log.d(TAG, "Not updating progress because share notification was already sent");
+ Log.d(TAG, "Not updating progress for " + info.id + " while taking screenshot"
+ + " because share notification was already sent");
continue;
}
updateProgress(info);
@@ -846,7 +850,15 @@
private static Intent buildSendIntent(Context context, BugreportInfo info) {
// Files are kept on private storage, so turn into Uris that we can
// grant temporary permissions for.
- final Uri bugreportUri = getUri(context, info.bugreportFile);
+ final Uri bugreportUri;
+ try {
+ bugreportUri = getUri(context, info.bugreportFile);
+ } catch (IllegalArgumentException e) {
+ // Should not happen on production, but happens when a Shell is sideloaded and
+ // FileProvider cannot find a configured root for it.
+ Log.wtf(TAG, "Could not get URI for " + info.bugreportFile, e);
+ return null;
+ }
final Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
final String mimeType = "application/vnd.android.bugreport";
@@ -907,10 +919,16 @@
addDetailsToZipFile(mContext, info);
final Intent sendIntent = buildSendIntent(mContext, info);
+ if (sendIntent == null) {
+ Log.w(TAG, "Stopping progres on ID " + id + " because share intent could not be built");
+ stopProgress(id);
+ return;
+ }
+
final Intent notifIntent;
// Send through warning dialog by default
- if (getWarningState(mContext, STATE_SHOW) == STATE_SHOW) {
+ if (getWarningState(mContext, STATE_UNKNOWN) != STATE_HIDE) {
notifIntent = buildWarningIntent(mContext, sendIntent);
} else {
notifIntent = sendIntent;
@@ -939,15 +957,10 @@
shareIntent.putExtra(EXTRA_ID, info.id);
shareIntent.putExtra(EXTRA_INFO, info);
- final String title, content;
- if (takingScreenshot) {
- title = context.getString(R.string.bugreport_finished_pending_screenshot_title,
- info.id);
- content = context.getString(R.string.bugreport_finished_pending_screenshot_text);
- } else {
- title = context.getString(R.string.bugreport_finished_title, info.id);
- content = context.getString(R.string.bugreport_finished_text);
- }
+ final String title = context.getString(R.string.bugreport_finished_title, info.id);
+ final String content = takingScreenshot ?
+ context.getString(R.string.bugreport_finished_pending_screenshot_text)
+ : context.getString(R.string.bugreport_finished_text);
final Notification.Builder builder = newBaseNotification(context)
.setContentTitle(title)
.setTicker(title)
@@ -1165,6 +1178,52 @@
}
}
+ /**
+ * Dumps an intent, extracting the relevant extras.
+ */
+ static String dumpIntent(Intent intent) {
+ if (intent == null) {
+ return "NO INTENT";
+ }
+ String action = intent.getAction();
+ if (action == null) {
+ // Happens when BugreportReceiver calls startService...
+ action = "no action";
+ }
+ final StringBuilder buffer = new StringBuilder(action).append(" extras: ");
+ addExtra(buffer, intent, EXTRA_ID);
+ addExtra(buffer, intent, EXTRA_PID);
+ addExtra(buffer, intent, EXTRA_MAX);
+ addExtra(buffer, intent, EXTRA_NAME);
+ addExtra(buffer, intent, EXTRA_DESCRIPTION);
+ addExtra(buffer, intent, EXTRA_BUGREPORT);
+ addExtra(buffer, intent, EXTRA_SCREENSHOT);
+ addExtra(buffer, intent, EXTRA_INFO);
+
+ if (intent.hasExtra(EXTRA_ORIGINAL_INTENT)) {
+ buffer.append(SHORT_EXTRA_ORIGINAL_INTENT).append(": ");
+ final Intent originalIntent = intent.getParcelableExtra(EXTRA_ORIGINAL_INTENT);
+ buffer.append(dumpIntent(originalIntent));
+ } else {
+ buffer.append("no ").append(SHORT_EXTRA_ORIGINAL_INTENT);
+ }
+
+ return buffer.toString();
+ }
+
+ private static final String SHORT_EXTRA_ORIGINAL_INTENT =
+ EXTRA_ORIGINAL_INTENT.substring(EXTRA_ORIGINAL_INTENT.lastIndexOf('.') + 1);
+
+ private static void addExtra(StringBuilder buffer, Intent intent, String name) {
+ final String shortName = name.substring(name.lastIndexOf('.') + 1);
+ if (intent.hasExtra(name)) {
+ buffer.append(shortName).append('=').append(intent.getExtra(name));
+ } else {
+ buffer.append("no ").append(shortName);
+ }
+ buffer.append(", ");
+ }
+
private static boolean setSystemProperty(String key, String value) {
try {
if (DEBUG) Log.v(TAG, "Setting system property " + key + " to " + value);
diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java
index cbd17bf..f6e558f 100644
--- a/packages/Shell/src/com/android/shell/BugreportReceiver.java
+++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java
@@ -20,6 +20,7 @@
import static com.android.shell.BugreportProgressService.EXTRA_ORIGINAL_INTENT;
import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
import static com.android.shell.BugreportProgressService.getFileExtra;
+import static com.android.shell.BugreportProgressService.dumpIntent;
import java.io.File;
@@ -51,7 +52,7 @@
@Override
public void onReceive(Context context, Intent intent) {
- Log.d(TAG, "onReceive: " + intent);
+ Log.d(TAG, "onReceive(): " + dumpIntent(intent));
// Clean up older bugreports in background
cleanupOldFiles(this, intent, INTENT_BUGREPORT_FINISHED, MIN_KEEP_COUNT, MIN_KEEP_AGE);
diff --git a/packages/Shell/src/com/android/shell/BugreportWarningActivity.java b/packages/Shell/src/com/android/shell/BugreportWarningActivity.java
index a1d879a..da33a65 100644
--- a/packages/Shell/src/com/android/shell/BugreportWarningActivity.java
+++ b/packages/Shell/src/com/android/shell/BugreportWarningActivity.java
@@ -59,7 +59,7 @@
ap.mNegativeButtonListener = this;
mConfirmRepeat = (CheckBox) ap.mView.findViewById(android.R.id.checkbox);
- mConfirmRepeat.setChecked(getWarningState(this, STATE_UNKNOWN) == STATE_SHOW);
+ mConfirmRepeat.setChecked(getWarningState(this, STATE_UNKNOWN) != STATE_SHOW);
setupAlert();
}
@@ -68,7 +68,7 @@
public void onClick(DialogInterface dialog, int which) {
if (which == AlertDialog.BUTTON_POSITIVE) {
// Remember confirm state, and launch target
- setWarningState(this, mConfirmRepeat.isChecked() ? STATE_SHOW : STATE_HIDE);
+ setWarningState(this, mConfirmRepeat.isChecked() ? STATE_HIDE : STATE_SHOW);
startActivity(mSendIntent);
}
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index e1e0c3b..537e4c5 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -17,7 +17,14 @@
package com.android.shell;
import static android.test.MoreAsserts.assertContainsRegex;
+
import static com.android.shell.ActionSendMultipleConsumerActivity.UI_NAME;
+import static com.android.shell.BugreportPrefs.PREFS_BUGREPORT;
+import static com.android.shell.BugreportPrefs.STATE_HIDE;
+import static com.android.shell.BugreportPrefs.STATE_SHOW;
+import static com.android.shell.BugreportPrefs.STATE_UNKNOWN;
+import static com.android.shell.BugreportPrefs.getWarningState;
+import static com.android.shell.BugreportPrefs.setWarningState;
import static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT;
import static com.android.shell.BugreportProgressService.EXTRA_ID;
import static com.android.shell.BugreportProgressService.EXTRA_MAX;
@@ -48,12 +55,12 @@
import java.util.zip.ZipOutputStream;
import libcore.io.Streams;
+
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.Instrumentation;
import android.app.NotificationManager;
import android.content.Context;
-import android.content.ContextWrapper;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@@ -62,7 +69,6 @@
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.UiSelector;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.text.TextUtils;
@@ -70,7 +76,6 @@
import android.util.Log;
import com.android.shell.ActionSendMultipleConsumerActivity.CustomActionSendMultipleListener;
-import com.android.shell.BugreportProgressService;
/**
* Integration tests for {@link BugreportReceiver}.
@@ -131,9 +136,6 @@
private static final boolean RENAMED_SCREENSHOTS = true;
private static final boolean DIDNT_RENAME_SCREENSHOTS = false;
- private static final boolean PENDING_SCREENSHOT = true;
- private static final boolean NOT_PENDING_SCREENSHOT = false;
-
private String mDescription;
private String mPlainTextPath;
@@ -171,7 +173,7 @@
}
mDescription = sb.toString();
- BugreportPrefs.setWarningState(mContext, BugreportPrefs.STATE_HIDE);
+ setWarningState(mContext, STATE_HIDE);
}
public void testProgress() throws Exception {
@@ -179,42 +181,37 @@
sendBugreportStarted(1000);
waitForScreenshotButtonEnabled(true);
- final NumberFormat nf = NumberFormat.getPercentInstance();
- nf.setMinimumFractionDigits(2);
- nf.setMaximumFractionDigits(2);
-
- assertProgressNotification(NAME, nf.format(0));
+ assertProgressNotification(NAME, 0f);
SystemProperties.set(PROGRESS_PROPERTY, "108");
- assertProgressNotification(NAME, nf.format(0.108));
+ assertProgressNotification(NAME, 10.80f);
- SystemProperties.set(PROGRESS_PROPERTY, "500");
- assertProgressNotification(NAME, nf.format(0.50));
+ assertProgressNotification(NAME, 50.00f);
SystemProperties.set(PROGRESS_PROPERTY, "950");
- assertProgressNotification(NAME, nf.format(0.95));
+ assertProgressNotification(NAME, 95.00f);
// Make sure progress never goes back...
SystemProperties.set(MAX_PROPERTY, "2000");
Thread.sleep(POLLING_FREQUENCY + DateUtils.SECOND_IN_MILLIS);
- assertProgressNotification(NAME, nf.format(0.95));
+ assertProgressNotification(NAME, 95.00f);
SystemProperties.set(PROGRESS_PROPERTY, "1000");
- assertProgressNotification(NAME, nf.format(0.95));
+ assertProgressNotification(NAME, 95.00f);
// ...only forward...
SystemProperties.set(PROGRESS_PROPERTY, "1902");
- assertProgressNotification(NAME, nf.format(0.9510));
+ assertProgressNotification(NAME, 95.10f);
SystemProperties.set(PROGRESS_PROPERTY, "1960");
- assertProgressNotification(NAME, nf.format(0.98));
+ assertProgressNotification(NAME, 98.00f);
// ...but never more than the capped value.
SystemProperties.set(PROGRESS_PROPERTY, "2000");
- assertProgressNotification(NAME, nf.format(0.99));
+ assertProgressNotification(NAME, 99.00f);
SystemProperties.set(PROGRESS_PROPERTY, "3000");
- assertProgressNotification(NAME, nf.format(0.99));
+ assertProgressNotification(NAME, 99.00f);
Bundle extras =
sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath, mScreenshotPath);
@@ -233,7 +230,7 @@
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
- assertProgressNotification(NAME, nf.format(0));
+ assertProgressNotification(NAME, 00.00f);
openProgressNotification(ID);
UiObject cancelButton = mUiBot.getVisibleObject(mContext.getString(
@@ -338,7 +335,7 @@
detailsUi.clickOk();
assertPropertyValue(NAME_PROPERTY, NEW_NAME);
- assertProgressNotification(NEW_NAME, "0.00%");
+ assertProgressNotification(NEW_NAME, 00.00f);
Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath,
mScreenshotPath);
@@ -375,7 +372,7 @@
detailsUi.clickOk();
assertPropertyValue(NAME_PROPERTY, NEW_NAME);
- assertProgressNotification(NEW_NAME, "0.00%");
+ assertProgressNotification(NEW_NAME, 00.00f);
Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID,
plainText? mPlainTextPath : mZipPath, mScreenshotPath);
@@ -437,7 +434,7 @@
sendBugreportStarted(ID2, PID2, NAME2, 1000);
sendBugreportFinished(ID, mZipPath, mScreenshotPath);
- Bundle extras = acceptBugreportAndGetSharedIntent(ID, PENDING_SCREENSHOT);
+ Bundle extras = acceptBugreportAndGetSharedIntent(ID);
detailsUi = new DetailsUi(mUiBot, ID2);
detailsUi.assertName(NAME2);
@@ -508,9 +505,29 @@
assertServiceNotRunning();
}
- public void testBugreportFinished_withWarning() throws Exception {
- // Explicitly shows the warning.
- BugreportPrefs.setWarningState(mContext, BugreportPrefs.STATE_SHOW);
+ public void testBugreportFinished_withWarningFirstTime() throws Exception {
+ bugreportFinishedWithWarningTest(null);
+ }
+
+ public void testBugreportFinished_withWarningUnknownState() throws Exception {
+ bugreportFinishedWithWarningTest(STATE_UNKNOWN);
+ }
+
+ public void testBugreportFinished_withWarningShowAgain() throws Exception {
+ bugreportFinishedWithWarningTest(STATE_SHOW);
+ }
+
+ private void bugreportFinishedWithWarningTest(Integer propertyState) throws Exception {
+ if (propertyState == null) {
+ // Clear properties
+ mContext.getSharedPreferences(PREFS_BUGREPORT, Context.MODE_PRIVATE)
+ .edit().clear().commit();
+ // Sanity check...
+ assertEquals("Did not reset properties", STATE_UNKNOWN,
+ getWarningState(mContext, STATE_UNKNOWN));
+ } else {
+ setWarningState(mContext, propertyState);
+ }
// Send notification and click on share.
sendBugreportFinished(NO_ID, mPlainTextPath, null);
@@ -518,10 +535,16 @@
// Handle the warning
mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm));
- // TODO: get ok and showMessageAgain from the dialog reference above
- UiObject showMessageAgain =
- mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm_repeat));
- mUiBot.click(showMessageAgain, "show-message-again");
+ // TODO: get ok and dontShowAgain from the dialog reference above
+ UiObject dontShowAgain =
+ mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm_dont_repeat));
+ final boolean firstTime = propertyState == null || propertyState == STATE_UNKNOWN;
+ if (firstTime) {
+ assertTrue("Checkbox should be checked by default", dontShowAgain.isChecked());
+ } else {
+ assertFalse("Checkbox should not be checked", dontShowAgain.isChecked());
+ mUiBot.click(dontShowAgain, "dont-show-again");
+ }
UiObject ok = mUiBot.getVisibleObject(mContext.getString(com.android.internal.R.string.ok));
mUiBot.click(ok, "ok");
@@ -531,8 +554,8 @@
assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT);
// Make sure it's hidden now.
- int newState = BugreportPrefs.getWarningState(mContext, BugreportPrefs.STATE_UNKNOWN);
- assertEquals("Didn't change state", BugreportPrefs.STATE_HIDE, newState);
+ int newState = getWarningState(mContext, STATE_UNKNOWN);
+ assertEquals("Didn't change state", STATE_HIDE, newState);
}
public void testShareBugreportAfterServiceDies() throws Exception {
@@ -571,13 +594,13 @@
}
}
- private void assertProgressNotification(String name, String percent) {
+ private void assertProgressNotification(String name, float percent) {
// TODO: it currently looks for 3 distinct objects, without taking advantage of their
// relationship.
openProgressNotification(ID);
Log.v(TAG, "Looking for progress notification details: '" + name + "-" + percent + "'");
mUiBot.getObject(name);
- mUiBot.getObject(percent);
+ // TODO: need a way to get the ProgresBar from the "android:id/progress" UIObject...
}
private UiObject openProgressNotification(int id) {
@@ -628,7 +651,7 @@
private Bundle sendBugreportFinishedAndGetSharedIntent(int id, String bugreportPath,
String screenshotPath) {
sendBugreportFinished(id, bugreportPath, screenshotPath);
- return acceptBugreportAndGetSharedIntent(id, NOT_PENDING_SCREENSHOT);
+ return acceptBugreportAndGetSharedIntent(id);
}
/**
@@ -637,11 +660,7 @@
* @return extras sent in the shared intent.
*/
private Bundle acceptBugreportAndGetSharedIntent(int id) {
- return acceptBugreportAndGetSharedIntent(id, NOT_PENDING_SCREENSHOT);
- }
-
- private Bundle acceptBugreportAndGetSharedIntent(int id, boolean pendingScreenshot) {
- acceptBugreport(id, pendingScreenshot);
+ acceptBugreport(id);
mUiBot.chooseActivity(UI_NAME);
return mListener.getExtras();
}
@@ -657,13 +676,7 @@
* Accepts the notification to share the finished bugreport.
*/
private void acceptBugreport(int id) {
- acceptBugreport(id, NOT_PENDING_SCREENSHOT);
- }
-
- private void acceptBugreport(int id, boolean pendingScreenshot) {
- final int res = pendingScreenshot ? R.string.bugreport_finished_pending_screenshot_title
- : R.string.bugreport_finished_title;
- mUiBot.clickOnNotification(mContext.getString(res, id));
+ mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title, id));
}
/**
@@ -894,8 +907,8 @@
}
private String getPath(String file) {
- File rootDir = new ContextWrapper(mContext).getFilesDir();
- File dir = new File(rootDir, BUGREPORTS_DIR);
+ final File rootDir = mContext.getFilesDir();
+ final File dir = new File(rootDir, BUGREPORTS_DIR);
if (!dir.exists()) {
Log.i(TAG, "Creating directory " + dir);
assertTrue("Could not create directory " + dir, dir.mkdir());
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 9e2442c..c248adf 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -159,6 +159,9 @@
<!-- DND access -->
<uses-permission android:name="android.permission.MANAGE_NOTIFICATIONS" />
+ <!-- It's like, reality, but, you know, virtual -->
+ <uses-permission android:name="android.permission.ACCESS_VR_MANAGER" />
+
<application
android:name=".SystemUIApplication"
android:persistent="true"
@@ -235,6 +238,19 @@
android:value="com.android.settings.category.system" />
</activity>
+ <activity-alias android:name=".DemoMode"
+ android:targetActivity=".tuner.TunerActivity"
+ android:icon="@drawable/tuner"
+ android:theme="@style/TunerSettings"
+ android:label="@string/demo_mode"
+ android:process=":tuner"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="com.android.settings.action.DEMO_MODE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity-alias>
+
<!-- Service used by secondary users to register themselves with the system user. -->
<service android:name=".recents.RecentsSystemUserService"
android:exported="false"
@@ -488,5 +504,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/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_text_focus_gain_animation.xml
similarity index 92%
copy from packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
copy to packages/SystemUI/res/anim/tv_pip_controls_text_focus_gain_animation.xml
index 681ff91..257bf35 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
+++ b/packages/SystemUI/res/anim/tv_pip_controls_text_focus_gain_animation.xml
@@ -18,4 +18,4 @@
android:propertyName="alpha"
android:valueTo="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="@integer/recents_tv_pip_focus_anim_duration" />
+ android:duration="100" />
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml b/packages/SystemUI/res/anim/tv_pip_controls_text_focus_lose_animation.xml
similarity index 92%
copy from packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml
copy to packages/SystemUI/res/anim/tv_pip_controls_text_focus_lose_animation.xml
index e6deb0f..e032008 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml
+++ b/packages/SystemUI/res/anim/tv_pip_controls_text_focus_lose_animation.xml
@@ -18,4 +18,4 @@
android:propertyName="alpha"
android:valueTo="0"
android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="@integer/recents_tv_pip_focus_anim_duration" />
+ android:duration="100" />
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml b/packages/SystemUI/res/anim/tv_pip_menu_fade_in_animation.xml
similarity index 92%
copy from packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
copy to packages/SystemUI/res/anim/tv_pip_menu_fade_in_animation.xml
index 681ff91..257bf35 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
+++ b/packages/SystemUI/res/anim/tv_pip_menu_fade_in_animation.xml
@@ -18,4 +18,4 @@
android:propertyName="alpha"
android:valueTo="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="@integer/recents_tv_pip_focus_anim_duration" />
+ android:duration="100" />
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml b/packages/SystemUI/res/anim/tv_pip_menu_fade_out_animation.xml
similarity index 92%
copy from packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml
copy to packages/SystemUI/res/anim/tv_pip_menu_fade_out_animation.xml
index e6deb0f..e032008 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml
+++ b/packages/SystemUI/res/anim/tv_pip_menu_fade_out_animation.xml
@@ -18,4 +18,4 @@
android:propertyName="alpha"
android:valueTo="0"
android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="@integer/recents_tv_pip_focus_anim_duration" />
+ android:duration="100" />
diff --git a/packages/SystemUI/res/anim/tv_pip_onboarding_button_enter_animation.xml b/packages/SystemUI/res/anim/tv_pip_onboarding_button_enter_animation.xml
new file mode 100644
index 0000000..01c263b
--- /dev/null
+++ b/packages/SystemUI/res/anim/tv_pip_onboarding_button_enter_animation.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <objectAnimator
+ android:propertyName="translationY"
+ android:valueFrom="114dp"
+ android:valueTo="0dp"
+ android:interpolator="@android:interpolator/fast_out_slow_in"
+ android:duration="@integer/tv_pip_onboarding_anim_duration" />
+ <objectAnimator
+ android:propertyName="alpha"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear"
+ android:duration="@integer/tv_pip_onboarding_anim_duration" />
+</set>
diff --git a/packages/SystemUI/res/anim/tv_pip_onboarding_description_enter_animation.xml b/packages/SystemUI/res/anim/tv_pip_onboarding_description_enter_animation.xml
new file mode 100644
index 0000000..a12b3b6
--- /dev/null
+++ b/packages/SystemUI/res/anim/tv_pip_onboarding_description_enter_animation.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <objectAnimator
+ android:propertyName="translationY"
+ android:valueFrom="84dp"
+ android:valueTo="0dp"
+ android:interpolator="@android:interpolator/fast_out_slow_in"
+ android:duration="@integer/tv_pip_onboarding_anim_duration" />
+ <objectAnimator
+ android:propertyName="alpha"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/linear"
+ android:duration="@integer/tv_pip_onboarding_anim_duration" />
+</set>
diff --git a/packages/SystemUI/res/anim/tv_pip_onboarding_image_enter_animation.xml b/packages/SystemUI/res/anim/tv_pip_onboarding_image_enter_animation.xml
new file mode 100644
index 0000000..ae9677e
--- /dev/null
+++ b/packages/SystemUI/res/anim/tv_pip_onboarding_image_enter_animation.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <objectAnimator
+ android:propertyName="translationY"
+ android:valueFrom="114dp"
+ android:valueTo="0dp"
+ android:interpolator="@android:interpolator/fast_out_slow_in"
+ android:duration="@integer/tv_pip_onboarding_anim_duration" />
+ <objectAnimator
+ android:propertyName="alpha"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/fast_out_slow_in"
+ android:duration="@integer/tv_pip_onboarding_anim_duration" />
+</set>
diff --git a/packages/SystemUI/res/anim/tv_pip_onboarding_title_enter_animation.xml b/packages/SystemUI/res/anim/tv_pip_onboarding_title_enter_animation.xml
new file mode 100644
index 0000000..4bde070
--- /dev/null
+++ b/packages/SystemUI/res/anim/tv_pip_onboarding_title_enter_animation.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <objectAnimator
+ android:propertyName="translationY"
+ android:valueFrom="84dp"
+ android:valueTo="0dp"
+ android:interpolator="@android:interpolator/fast_out_slow_in"
+ android:duration="@integer/tv_pip_onboarding_anim_duration" />
+ <objectAnimator
+ android:propertyName="alpha"
+ android:valueTo="1"
+ android:interpolator="@android:interpolator/fast_out_slow_in"
+ android:duration="@integer/tv_pip_onboarding_anim_duration" />
+</set>
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml b/packages/SystemUI/res/anim/tv_pip_overlay_fade_in_animation.xml
similarity index 92%
rename from packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
rename to packages/SystemUI/res/anim/tv_pip_overlay_fade_in_animation.xml
index 681ff91..33bceaa 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
+++ b/packages/SystemUI/res/anim/tv_pip_overlay_fade_in_animation.xml
@@ -18,4 +18,4 @@
android:propertyName="alpha"
android:valueTo="1"
android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="@integer/recents_tv_pip_focus_anim_duration" />
+ android:duration="350" />
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml b/packages/SystemUI/res/anim/tv_pip_overlay_fade_out_animation.xml
similarity index 92%
rename from packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml
rename to packages/SystemUI/res/anim/tv_pip_overlay_fade_out_animation.xml
index e6deb0f..a12ddff 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_lose_animation.xml
+++ b/packages/SystemUI/res/anim/tv_pip_overlay_fade_out_animation.xml
@@ -18,4 +18,4 @@
android:propertyName="alpha"
android:valueTo="0"
android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="@integer/recents_tv_pip_focus_anim_duration" />
+ android:duration="500" />
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote.png b/packages/SystemUI/res/drawable-xhdpi/remote.png
new file mode 100644
index 0000000..c0ccfe6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_0.png b/packages/SystemUI/res/drawable-xhdpi/remote_0.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_1.png b/packages/SystemUI/res/drawable-xhdpi/remote_1.png
new file mode 100644
index 0000000..252ff5e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_10.png b/packages/SystemUI/res/drawable-xhdpi/remote_10.png
new file mode 100644
index 0000000..5e52b37
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_10.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_100.png b/packages/SystemUI/res/drawable-xhdpi/remote_100.png
new file mode 100644
index 0000000..f604808
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_100.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_101.png b/packages/SystemUI/res/drawable-xhdpi/remote_101.png
new file mode 100644
index 0000000..0272e45
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_101.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_102.png b/packages/SystemUI/res/drawable-xhdpi/remote_102.png
new file mode 100644
index 0000000..aaa35c0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_102.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_103.png b/packages/SystemUI/res/drawable-xhdpi/remote_103.png
new file mode 100644
index 0000000..20f95a5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_103.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_104.png b/packages/SystemUI/res/drawable-xhdpi/remote_104.png
new file mode 100644
index 0000000..052f23e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_104.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_105.png b/packages/SystemUI/res/drawable-xhdpi/remote_105.png
new file mode 100644
index 0000000..c5c8256
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_105.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_106.png b/packages/SystemUI/res/drawable-xhdpi/remote_106.png
new file mode 100644
index 0000000..4e804fe
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_106.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_107.png b/packages/SystemUI/res/drawable-xhdpi/remote_107.png
new file mode 100644
index 0000000..76669cc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_107.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_108.png b/packages/SystemUI/res/drawable-xhdpi/remote_108.png
new file mode 100644
index 0000000..c1b2f3b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_108.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_109.png b/packages/SystemUI/res/drawable-xhdpi/remote_109.png
new file mode 100644
index 0000000..79e1d7b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_109.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_11.png b/packages/SystemUI/res/drawable-xhdpi/remote_11.png
new file mode 100644
index 0000000..cfec6cb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_11.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_110.png b/packages/SystemUI/res/drawable-xhdpi/remote_110.png
new file mode 100644
index 0000000..d902297
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_110.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_111.png b/packages/SystemUI/res/drawable-xhdpi/remote_111.png
new file mode 100644
index 0000000..e48ed0b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_111.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_112.png b/packages/SystemUI/res/drawable-xhdpi/remote_112.png
new file mode 100644
index 0000000..90dd1a2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_112.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_113.png b/packages/SystemUI/res/drawable-xhdpi/remote_113.png
new file mode 100644
index 0000000..8fb4ad2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_113.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_114.png b/packages/SystemUI/res/drawable-xhdpi/remote_114.png
new file mode 100644
index 0000000..76873fb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_114.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_115.png b/packages/SystemUI/res/drawable-xhdpi/remote_115.png
new file mode 100644
index 0000000..e923d4c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_115.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_116.png b/packages/SystemUI/res/drawable-xhdpi/remote_116.png
new file mode 100644
index 0000000..41d5124
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_116.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_117.png b/packages/SystemUI/res/drawable-xhdpi/remote_117.png
new file mode 100644
index 0000000..eacde64
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_117.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_118.png b/packages/SystemUI/res/drawable-xhdpi/remote_118.png
new file mode 100644
index 0000000..5dc1fb0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_118.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_119.png b/packages/SystemUI/res/drawable-xhdpi/remote_119.png
new file mode 100644
index 0000000..a16f037
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_119.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_12.png b/packages/SystemUI/res/drawable-xhdpi/remote_12.png
new file mode 100644
index 0000000..28bb387
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_12.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_120.png b/packages/SystemUI/res/drawable-xhdpi/remote_120.png
new file mode 100644
index 0000000..fe3ef41
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_120.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_121.png b/packages/SystemUI/res/drawable-xhdpi/remote_121.png
new file mode 100644
index 0000000..ef2b892
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_121.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_122.png b/packages/SystemUI/res/drawable-xhdpi/remote_122.png
new file mode 100644
index 0000000..5342976
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_122.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_123.png b/packages/SystemUI/res/drawable-xhdpi/remote_123.png
new file mode 100644
index 0000000..bb8a53a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_123.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_124.png b/packages/SystemUI/res/drawable-xhdpi/remote_124.png
new file mode 100644
index 0000000..b68337e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_124.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_125.png b/packages/SystemUI/res/drawable-xhdpi/remote_125.png
new file mode 100644
index 0000000..81fa3a7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_125.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_126.png b/packages/SystemUI/res/drawable-xhdpi/remote_126.png
new file mode 100644
index 0000000..2339d74
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_126.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_127.png b/packages/SystemUI/res/drawable-xhdpi/remote_127.png
new file mode 100644
index 0000000..90d1e0b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_127.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_128.png b/packages/SystemUI/res/drawable-xhdpi/remote_128.png
new file mode 100644
index 0000000..6de4eb8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_128.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_129.png b/packages/SystemUI/res/drawable-xhdpi/remote_129.png
new file mode 100644
index 0000000..9086074
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_129.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_13.png b/packages/SystemUI/res/drawable-xhdpi/remote_13.png
new file mode 100644
index 0000000..a1e212d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_13.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_130.png b/packages/SystemUI/res/drawable-xhdpi/remote_130.png
new file mode 100644
index 0000000..2bc9698
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_130.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_131.png b/packages/SystemUI/res/drawable-xhdpi/remote_131.png
new file mode 100644
index 0000000..d18d2c6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_131.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_132.png b/packages/SystemUI/res/drawable-xhdpi/remote_132.png
new file mode 100644
index 0000000..10a00cd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_132.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_133.png b/packages/SystemUI/res/drawable-xhdpi/remote_133.png
new file mode 100644
index 0000000..6f495b4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_133.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_134.png b/packages/SystemUI/res/drawable-xhdpi/remote_134.png
new file mode 100644
index 0000000..703f2c6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_134.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_135.png b/packages/SystemUI/res/drawable-xhdpi/remote_135.png
new file mode 100644
index 0000000..f4105b0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_135.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_136.png b/packages/SystemUI/res/drawable-xhdpi/remote_136.png
new file mode 100644
index 0000000..0c3a5bc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_136.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_137.png b/packages/SystemUI/res/drawable-xhdpi/remote_137.png
new file mode 100644
index 0000000..cbebc05
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_137.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_138.png b/packages/SystemUI/res/drawable-xhdpi/remote_138.png
new file mode 100644
index 0000000..6dfefb0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_138.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_139.png b/packages/SystemUI/res/drawable-xhdpi/remote_139.png
new file mode 100644
index 0000000..1acfdd6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_139.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_14.png b/packages/SystemUI/res/drawable-xhdpi/remote_14.png
new file mode 100644
index 0000000..a503cdf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_14.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_140.png b/packages/SystemUI/res/drawable-xhdpi/remote_140.png
new file mode 100644
index 0000000..70d27c1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_140.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_141.png b/packages/SystemUI/res/drawable-xhdpi/remote_141.png
new file mode 100644
index 0000000..d523a0c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_141.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_142.png b/packages/SystemUI/res/drawable-xhdpi/remote_142.png
new file mode 100644
index 0000000..ed6a65d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_142.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_143.png b/packages/SystemUI/res/drawable-xhdpi/remote_143.png
new file mode 100644
index 0000000..9b048e6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_143.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_144.png b/packages/SystemUI/res/drawable-xhdpi/remote_144.png
new file mode 100644
index 0000000..9e2337d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_144.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_145.png b/packages/SystemUI/res/drawable-xhdpi/remote_145.png
new file mode 100644
index 0000000..3f30629
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_145.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_146.png b/packages/SystemUI/res/drawable-xhdpi/remote_146.png
new file mode 100644
index 0000000..1288039
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_146.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_147.png b/packages/SystemUI/res/drawable-xhdpi/remote_147.png
new file mode 100644
index 0000000..d060539
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_147.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_148.png b/packages/SystemUI/res/drawable-xhdpi/remote_148.png
new file mode 100644
index 0000000..5be839d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_148.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_149.png b/packages/SystemUI/res/drawable-xhdpi/remote_149.png
new file mode 100644
index 0000000..39d31ba
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_149.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_15.png b/packages/SystemUI/res/drawable-xhdpi/remote_15.png
new file mode 100644
index 0000000..5695595
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_150.png b/packages/SystemUI/res/drawable-xhdpi/remote_150.png
new file mode 100644
index 0000000..ec2667c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_150.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_151.png b/packages/SystemUI/res/drawable-xhdpi/remote_151.png
new file mode 100644
index 0000000..ec2667c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_151.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_152.png b/packages/SystemUI/res/drawable-xhdpi/remote_152.png
new file mode 100644
index 0000000..a5d58c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_152.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_153.png b/packages/SystemUI/res/drawable-xhdpi/remote_153.png
new file mode 100644
index 0000000..a5d58c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_153.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_154.png b/packages/SystemUI/res/drawable-xhdpi/remote_154.png
new file mode 100644
index 0000000..a5d58c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_154.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_155.png b/packages/SystemUI/res/drawable-xhdpi/remote_155.png
new file mode 100644
index 0000000..793d411
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_155.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_156.png b/packages/SystemUI/res/drawable-xhdpi/remote_156.png
new file mode 100644
index 0000000..793d411
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_156.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_157.png b/packages/SystemUI/res/drawable-xhdpi/remote_157.png
new file mode 100644
index 0000000..f9d6cdc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_157.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_158.png b/packages/SystemUI/res/drawable-xhdpi/remote_158.png
new file mode 100644
index 0000000..da8d5d7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_158.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_159.png b/packages/SystemUI/res/drawable-xhdpi/remote_159.png
new file mode 100644
index 0000000..1e0b097
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_159.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_16.png b/packages/SystemUI/res/drawable-xhdpi/remote_16.png
new file mode 100644
index 0000000..4ae106c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_16.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_160.png b/packages/SystemUI/res/drawable-xhdpi/remote_160.png
new file mode 100644
index 0000000..8aa68ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_160.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_161.png b/packages/SystemUI/res/drawable-xhdpi/remote_161.png
new file mode 100644
index 0000000..e49fdd9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_161.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_162.png b/packages/SystemUI/res/drawable-xhdpi/remote_162.png
new file mode 100644
index 0000000..69257a0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_162.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_163.png b/packages/SystemUI/res/drawable-xhdpi/remote_163.png
new file mode 100644
index 0000000..8f0c3d5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_163.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_164.png b/packages/SystemUI/res/drawable-xhdpi/remote_164.png
new file mode 100644
index 0000000..a4c3229
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_164.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_165.png b/packages/SystemUI/res/drawable-xhdpi/remote_165.png
new file mode 100644
index 0000000..46fae23
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_165.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_166.png b/packages/SystemUI/res/drawable-xhdpi/remote_166.png
new file mode 100644
index 0000000..40d5a9b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_166.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_167.png b/packages/SystemUI/res/drawable-xhdpi/remote_167.png
new file mode 100644
index 0000000..6bd0380
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_167.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_168.png b/packages/SystemUI/res/drawable-xhdpi/remote_168.png
new file mode 100644
index 0000000..03904bf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_168.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_169.png b/packages/SystemUI/res/drawable-xhdpi/remote_169.png
new file mode 100644
index 0000000..564a161
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_169.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_17.png b/packages/SystemUI/res/drawable-xhdpi/remote_17.png
new file mode 100644
index 0000000..0703e1a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_17.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_170.png b/packages/SystemUI/res/drawable-xhdpi/remote_170.png
new file mode 100644
index 0000000..0411f94
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_170.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_171.png b/packages/SystemUI/res/drawable-xhdpi/remote_171.png
new file mode 100644
index 0000000..ec141e9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_171.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_172.png b/packages/SystemUI/res/drawable-xhdpi/remote_172.png
new file mode 100644
index 0000000..cb9ecaf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_172.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_173.png b/packages/SystemUI/res/drawable-xhdpi/remote_173.png
new file mode 100644
index 0000000..484ee51
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_173.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_174.png b/packages/SystemUI/res/drawable-xhdpi/remote_174.png
new file mode 100644
index 0000000..85a3135
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_174.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_175.png b/packages/SystemUI/res/drawable-xhdpi/remote_175.png
new file mode 100644
index 0000000..edd6507
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_175.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_176.png b/packages/SystemUI/res/drawable-xhdpi/remote_176.png
new file mode 100644
index 0000000..d95a68b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_176.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_177.png b/packages/SystemUI/res/drawable-xhdpi/remote_177.png
new file mode 100644
index 0000000..305641f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_177.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_178.png b/packages/SystemUI/res/drawable-xhdpi/remote_178.png
new file mode 100644
index 0000000..59de0e5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_178.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_179.png b/packages/SystemUI/res/drawable-xhdpi/remote_179.png
new file mode 100644
index 0000000..414e548
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_179.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_18.png b/packages/SystemUI/res/drawable-xhdpi/remote_18.png
new file mode 100644
index 0000000..74df1e4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_18.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_180.png b/packages/SystemUI/res/drawable-xhdpi/remote_180.png
new file mode 100644
index 0000000..b5d925c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_180.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_181.png b/packages/SystemUI/res/drawable-xhdpi/remote_181.png
new file mode 100644
index 0000000..e8a7127
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_181.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_182.png b/packages/SystemUI/res/drawable-xhdpi/remote_182.png
new file mode 100644
index 0000000..29c7037
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_182.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_183.png b/packages/SystemUI/res/drawable-xhdpi/remote_183.png
new file mode 100644
index 0000000..9491d94
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_183.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_184.png b/packages/SystemUI/res/drawable-xhdpi/remote_184.png
new file mode 100644
index 0000000..4aa0e32
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_184.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_185.png b/packages/SystemUI/res/drawable-xhdpi/remote_185.png
new file mode 100644
index 0000000..2a0dde8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_185.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_186.png b/packages/SystemUI/res/drawable-xhdpi/remote_186.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_186.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_187.png b/packages/SystemUI/res/drawable-xhdpi/remote_187.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_187.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_188.png b/packages/SystemUI/res/drawable-xhdpi/remote_188.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_188.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_189.png b/packages/SystemUI/res/drawable-xhdpi/remote_189.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_189.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_19.png b/packages/SystemUI/res/drawable-xhdpi/remote_19.png
new file mode 100644
index 0000000..222ea31
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_19.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_190.png b/packages/SystemUI/res/drawable-xhdpi/remote_190.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_190.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_191.png b/packages/SystemUI/res/drawable-xhdpi/remote_191.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_191.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_192.png b/packages/SystemUI/res/drawable-xhdpi/remote_192.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_192.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_193.png b/packages/SystemUI/res/drawable-xhdpi/remote_193.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_193.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_194.png b/packages/SystemUI/res/drawable-xhdpi/remote_194.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_194.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_195.png b/packages/SystemUI/res/drawable-xhdpi/remote_195.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_195.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_196.png b/packages/SystemUI/res/drawable-xhdpi/remote_196.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_196.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_197.png b/packages/SystemUI/res/drawable-xhdpi/remote_197.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_197.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_198.png b/packages/SystemUI/res/drawable-xhdpi/remote_198.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_198.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_199.png b/packages/SystemUI/res/drawable-xhdpi/remote_199.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_199.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_2.png b/packages/SystemUI/res/drawable-xhdpi/remote_2.png
new file mode 100644
index 0000000..fb3f7ef
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_20.png b/packages/SystemUI/res/drawable-xhdpi/remote_20.png
new file mode 100644
index 0000000..646587c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_20.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_200.png b/packages/SystemUI/res/drawable-xhdpi/remote_200.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_200.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_201.png b/packages/SystemUI/res/drawable-xhdpi/remote_201.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_201.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_202.png b/packages/SystemUI/res/drawable-xhdpi/remote_202.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_202.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_203.png b/packages/SystemUI/res/drawable-xhdpi/remote_203.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_203.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_204.png b/packages/SystemUI/res/drawable-xhdpi/remote_204.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_204.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_205.png b/packages/SystemUI/res/drawable-xhdpi/remote_205.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_205.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_206.png b/packages/SystemUI/res/drawable-xhdpi/remote_206.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_206.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_207.png b/packages/SystemUI/res/drawable-xhdpi/remote_207.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_207.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_208.png b/packages/SystemUI/res/drawable-xhdpi/remote_208.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_208.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_209.png b/packages/SystemUI/res/drawable-xhdpi/remote_209.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_209.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_21.png b/packages/SystemUI/res/drawable-xhdpi/remote_21.png
new file mode 100644
index 0000000..5858ba92
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_21.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_210.png b/packages/SystemUI/res/drawable-xhdpi/remote_210.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_210.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_211.png b/packages/SystemUI/res/drawable-xhdpi/remote_211.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_211.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_212.png b/packages/SystemUI/res/drawable-xhdpi/remote_212.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_212.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_213.png b/packages/SystemUI/res/drawable-xhdpi/remote_213.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_213.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_214.png b/packages/SystemUI/res/drawable-xhdpi/remote_214.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_214.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_215.png b/packages/SystemUI/res/drawable-xhdpi/remote_215.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_215.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_216.png b/packages/SystemUI/res/drawable-xhdpi/remote_216.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_216.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_217.png b/packages/SystemUI/res/drawable-xhdpi/remote_217.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_217.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_218.png b/packages/SystemUI/res/drawable-xhdpi/remote_218.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_218.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_219.png b/packages/SystemUI/res/drawable-xhdpi/remote_219.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_219.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_22.png b/packages/SystemUI/res/drawable-xhdpi/remote_22.png
new file mode 100644
index 0000000..1974802
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_22.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_220.png b/packages/SystemUI/res/drawable-xhdpi/remote_220.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_220.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_221.png b/packages/SystemUI/res/drawable-xhdpi/remote_221.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_221.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_222.png b/packages/SystemUI/res/drawable-xhdpi/remote_222.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_222.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_223.png b/packages/SystemUI/res/drawable-xhdpi/remote_223.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_223.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_224.png b/packages/SystemUI/res/drawable-xhdpi/remote_224.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_224.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_225.png b/packages/SystemUI/res/drawable-xhdpi/remote_225.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_225.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_226.png b/packages/SystemUI/res/drawable-xhdpi/remote_226.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_226.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_227.png b/packages/SystemUI/res/drawable-xhdpi/remote_227.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_227.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_228.png b/packages/SystemUI/res/drawable-xhdpi/remote_228.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_228.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_229.png b/packages/SystemUI/res/drawable-xhdpi/remote_229.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_229.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_23.png b/packages/SystemUI/res/drawable-xhdpi/remote_23.png
new file mode 100644
index 0000000..96b7c35
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_23.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_230.png b/packages/SystemUI/res/drawable-xhdpi/remote_230.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_230.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_231.png b/packages/SystemUI/res/drawable-xhdpi/remote_231.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_231.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_232.png b/packages/SystemUI/res/drawable-xhdpi/remote_232.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_232.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_233.png b/packages/SystemUI/res/drawable-xhdpi/remote_233.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_233.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_234.png b/packages/SystemUI/res/drawable-xhdpi/remote_234.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_234.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_235.png b/packages/SystemUI/res/drawable-xhdpi/remote_235.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_235.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_236.png b/packages/SystemUI/res/drawable-xhdpi/remote_236.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_236.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_237.png b/packages/SystemUI/res/drawable-xhdpi/remote_237.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_237.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_238.png b/packages/SystemUI/res/drawable-xhdpi/remote_238.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_238.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_239.png b/packages/SystemUI/res/drawable-xhdpi/remote_239.png
new file mode 100644
index 0000000..5bda52e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_239.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_24.png b/packages/SystemUI/res/drawable-xhdpi/remote_24.png
new file mode 100644
index 0000000..0437200
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_24.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_25.png b/packages/SystemUI/res/drawable-xhdpi/remote_25.png
new file mode 100644
index 0000000..60b0f15
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_25.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_26.png b/packages/SystemUI/res/drawable-xhdpi/remote_26.png
new file mode 100644
index 0000000..c34ed97
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_26.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_27.png b/packages/SystemUI/res/drawable-xhdpi/remote_27.png
new file mode 100644
index 0000000..1a83664
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_27.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_28.png b/packages/SystemUI/res/drawable-xhdpi/remote_28.png
new file mode 100644
index 0000000..a3685ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_28.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_29.png b/packages/SystemUI/res/drawable-xhdpi/remote_29.png
new file mode 100644
index 0000000..f7135eb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_29.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_3.png b/packages/SystemUI/res/drawable-xhdpi/remote_3.png
new file mode 100644
index 0000000..937da65
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_30.png b/packages/SystemUI/res/drawable-xhdpi/remote_30.png
new file mode 100644
index 0000000..718cf52
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_30.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_31.png b/packages/SystemUI/res/drawable-xhdpi/remote_31.png
new file mode 100644
index 0000000..c0b55df
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_31.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_32.png b/packages/SystemUI/res/drawable-xhdpi/remote_32.png
new file mode 100644
index 0000000..7a1ce9f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_32.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_33.png b/packages/SystemUI/res/drawable-xhdpi/remote_33.png
new file mode 100644
index 0000000..5428bcf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_33.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_34.png b/packages/SystemUI/res/drawable-xhdpi/remote_34.png
new file mode 100644
index 0000000..264efe8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_34.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_35.png b/packages/SystemUI/res/drawable-xhdpi/remote_35.png
new file mode 100644
index 0000000..a5c450f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_35.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_36.png b/packages/SystemUI/res/drawable-xhdpi/remote_36.png
new file mode 100644
index 0000000..3e469e4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_36.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_37.png b/packages/SystemUI/res/drawable-xhdpi/remote_37.png
new file mode 100644
index 0000000..124ebe4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_37.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_38.png b/packages/SystemUI/res/drawable-xhdpi/remote_38.png
new file mode 100644
index 0000000..b2b4844
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_38.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_39.png b/packages/SystemUI/res/drawable-xhdpi/remote_39.png
new file mode 100644
index 0000000..a6d1733
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_39.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_4.png b/packages/SystemUI/res/drawable-xhdpi/remote_4.png
new file mode 100644
index 0000000..c282f40
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_40.png b/packages/SystemUI/res/drawable-xhdpi/remote_40.png
new file mode 100644
index 0000000..4cd615c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_40.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_41.png b/packages/SystemUI/res/drawable-xhdpi/remote_41.png
new file mode 100644
index 0000000..c746ae0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_41.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_42.png b/packages/SystemUI/res/drawable-xhdpi/remote_42.png
new file mode 100644
index 0000000..a93f198
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_42.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_43.png b/packages/SystemUI/res/drawable-xhdpi/remote_43.png
new file mode 100644
index 0000000..966e563
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_43.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_44.png b/packages/SystemUI/res/drawable-xhdpi/remote_44.png
new file mode 100644
index 0000000..beb7031
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_44.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_45.png b/packages/SystemUI/res/drawable-xhdpi/remote_45.png
new file mode 100644
index 0000000..718e167
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_45.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_46.png b/packages/SystemUI/res/drawable-xhdpi/remote_46.png
new file mode 100644
index 0000000..aa54ddb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_46.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_47.png b/packages/SystemUI/res/drawable-xhdpi/remote_47.png
new file mode 100644
index 0000000..1d11270
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_47.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_48.png b/packages/SystemUI/res/drawable-xhdpi/remote_48.png
new file mode 100644
index 0000000..ab31163
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_48.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_49.png b/packages/SystemUI/res/drawable-xhdpi/remote_49.png
new file mode 100644
index 0000000..219b7f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_49.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_5.png b/packages/SystemUI/res/drawable-xhdpi/remote_5.png
new file mode 100644
index 0000000..15f69e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_5.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_50.png b/packages/SystemUI/res/drawable-xhdpi/remote_50.png
new file mode 100644
index 0000000..8a9725f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_50.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_51.png b/packages/SystemUI/res/drawable-xhdpi/remote_51.png
new file mode 100644
index 0000000..bc839cf
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_51.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_52.png b/packages/SystemUI/res/drawable-xhdpi/remote_52.png
new file mode 100644
index 0000000..7bab6e5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_52.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_53.png b/packages/SystemUI/res/drawable-xhdpi/remote_53.png
new file mode 100644
index 0000000..34ab855
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_53.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_54.png b/packages/SystemUI/res/drawable-xhdpi/remote_54.png
new file mode 100644
index 0000000..5bd9f59
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_54.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_55.png b/packages/SystemUI/res/drawable-xhdpi/remote_55.png
new file mode 100644
index 0000000..1ff17f4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_55.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_56.png b/packages/SystemUI/res/drawable-xhdpi/remote_56.png
new file mode 100644
index 0000000..d57e067
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_56.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_57.png b/packages/SystemUI/res/drawable-xhdpi/remote_57.png
new file mode 100644
index 0000000..a1bdae1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_57.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_58.png b/packages/SystemUI/res/drawable-xhdpi/remote_58.png
new file mode 100644
index 0000000..c8bc6a4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_58.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_59.png b/packages/SystemUI/res/drawable-xhdpi/remote_59.png
new file mode 100644
index 0000000..526a24e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_59.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_6.png b/packages/SystemUI/res/drawable-xhdpi/remote_6.png
new file mode 100644
index 0000000..2b6732f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_6.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_60.png b/packages/SystemUI/res/drawable-xhdpi/remote_60.png
new file mode 100644
index 0000000..080619e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_60.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_61.png b/packages/SystemUI/res/drawable-xhdpi/remote_61.png
new file mode 100644
index 0000000..5932a8c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_61.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_62.png b/packages/SystemUI/res/drawable-xhdpi/remote_62.png
new file mode 100644
index 0000000..d1233dd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_62.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_63.png b/packages/SystemUI/res/drawable-xhdpi/remote_63.png
new file mode 100644
index 0000000..4f230c7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_63.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_64.png b/packages/SystemUI/res/drawable-xhdpi/remote_64.png
new file mode 100644
index 0000000..6b89fcb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_64.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_65.png b/packages/SystemUI/res/drawable-xhdpi/remote_65.png
new file mode 100644
index 0000000..87597b1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_65.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_66.png b/packages/SystemUI/res/drawable-xhdpi/remote_66.png
new file mode 100644
index 0000000..0ee8c1e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_66.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_67.png b/packages/SystemUI/res/drawable-xhdpi/remote_67.png
new file mode 100644
index 0000000..9aca8fd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_67.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_68.png b/packages/SystemUI/res/drawable-xhdpi/remote_68.png
new file mode 100644
index 0000000..5f263ae
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_68.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_69.png b/packages/SystemUI/res/drawable-xhdpi/remote_69.png
new file mode 100644
index 0000000..1a22b61
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_69.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_7.png b/packages/SystemUI/res/drawable-xhdpi/remote_7.png
new file mode 100644
index 0000000..9d9d699
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_7.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_70.png b/packages/SystemUI/res/drawable-xhdpi/remote_70.png
new file mode 100644
index 0000000..0372c50
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_70.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_71.png b/packages/SystemUI/res/drawable-xhdpi/remote_71.png
new file mode 100644
index 0000000..854e3e2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_71.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_72.png b/packages/SystemUI/res/drawable-xhdpi/remote_72.png
new file mode 100644
index 0000000..6919624
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_72.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_73.png b/packages/SystemUI/res/drawable-xhdpi/remote_73.png
new file mode 100644
index 0000000..d8e9ae1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_73.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_74.png b/packages/SystemUI/res/drawable-xhdpi/remote_74.png
new file mode 100644
index 0000000..24e5b6a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_74.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_75.png b/packages/SystemUI/res/drawable-xhdpi/remote_75.png
new file mode 100644
index 0000000..369a3a9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_75.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_76.png b/packages/SystemUI/res/drawable-xhdpi/remote_76.png
new file mode 100644
index 0000000..96824c6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_76.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_77.png b/packages/SystemUI/res/drawable-xhdpi/remote_77.png
new file mode 100644
index 0000000..dd60cca
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_77.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_78.png b/packages/SystemUI/res/drawable-xhdpi/remote_78.png
new file mode 100644
index 0000000..aa3460b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_78.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_79.png b/packages/SystemUI/res/drawable-xhdpi/remote_79.png
new file mode 100644
index 0000000..9a60e3c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_79.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_8.png b/packages/SystemUI/res/drawable-xhdpi/remote_8.png
new file mode 100644
index 0000000..b73c7ef
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_8.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_80.png b/packages/SystemUI/res/drawable-xhdpi/remote_80.png
new file mode 100644
index 0000000..cbf883c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_80.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_81.png b/packages/SystemUI/res/drawable-xhdpi/remote_81.png
new file mode 100644
index 0000000..11a6add
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_81.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_82.png b/packages/SystemUI/res/drawable-xhdpi/remote_82.png
new file mode 100644
index 0000000..e05105d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_82.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_83.png b/packages/SystemUI/res/drawable-xhdpi/remote_83.png
new file mode 100644
index 0000000..57813aa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_83.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_84.png b/packages/SystemUI/res/drawable-xhdpi/remote_84.png
new file mode 100644
index 0000000..0f6f0fe
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_84.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_85.png b/packages/SystemUI/res/drawable-xhdpi/remote_85.png
new file mode 100644
index 0000000..ada83ec
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_85.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_86.png b/packages/SystemUI/res/drawable-xhdpi/remote_86.png
new file mode 100644
index 0000000..442dd51
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_86.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_87.png b/packages/SystemUI/res/drawable-xhdpi/remote_87.png
new file mode 100644
index 0000000..bdb4962
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_87.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_88.png b/packages/SystemUI/res/drawable-xhdpi/remote_88.png
new file mode 100644
index 0000000..b318002
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_88.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_89.png b/packages/SystemUI/res/drawable-xhdpi/remote_89.png
new file mode 100644
index 0000000..c4ed874
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_89.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_9.png b/packages/SystemUI/res/drawable-xhdpi/remote_9.png
new file mode 100644
index 0000000..ce5041f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_90.png b/packages/SystemUI/res/drawable-xhdpi/remote_90.png
new file mode 100644
index 0000000..6a662f9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_90.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_91.png b/packages/SystemUI/res/drawable-xhdpi/remote_91.png
new file mode 100644
index 0000000..21be887
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_91.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_92.png b/packages/SystemUI/res/drawable-xhdpi/remote_92.png
new file mode 100644
index 0000000..1bc5361
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_92.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_93.png b/packages/SystemUI/res/drawable-xhdpi/remote_93.png
new file mode 100644
index 0000000..76495ac
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_93.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_94.png b/packages/SystemUI/res/drawable-xhdpi/remote_94.png
new file mode 100644
index 0000000..081c84b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_94.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_95.png b/packages/SystemUI/res/drawable-xhdpi/remote_95.png
new file mode 100644
index 0000000..e9c27a8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_95.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_96.png b/packages/SystemUI/res/drawable-xhdpi/remote_96.png
new file mode 100644
index 0000000..1369603
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_96.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_97.png b/packages/SystemUI/res/drawable-xhdpi/remote_97.png
new file mode 100644
index 0000000..fbd1458
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_97.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_98.png b/packages/SystemUI/res/drawable-xhdpi/remote_98.png
new file mode 100644
index 0000000..ccdd7a7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_98.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_99.png b/packages/SystemUI/res/drawable-xhdpi/remote_99.png
new file mode 100644
index 0000000..f3cb4db
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/remote_99.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ksh_key_item_background.xml b/packages/SystemUI/res/drawable/ksh_key_item_background.xml
new file mode 100644
index 0000000..75ff30d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ksh_key_item_background.xml
@@ -0,0 +1,21 @@
+<?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
+ -->
+<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/drawable/recents_info_dark.xml b/packages/SystemUI/res/drawable/recents_info_dark.xml
index b1a2242..555a69a 100644
--- a/packages/SystemUI/res/drawable/recents_info_dark.xml
+++ b/packages/SystemUI/res/drawable/recents_info_dark.xml
@@ -14,8 +14,8 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48.0dp"
- android:height="48.0dp"
+ android:width="24.0dp"
+ android:height="24.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
diff --git a/packages/SystemUI/res/drawable/recents_info_light.xml b/packages/SystemUI/res/drawable/recents_info_light.xml
index bc58c3b..65e7bf5 100644
--- a/packages/SystemUI/res/drawable/recents_info_light.xml
+++ b/packages/SystemUI/res/drawable/recents_info_light.xml
@@ -14,8 +14,8 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48.0dp"
- android:height="48.0dp"
+ android:width="24.0dp"
+ android:height="24.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
diff --git a/packages/SystemUI/res/drawable/recents_tv_background_gradient.xml b/packages/SystemUI/res/drawable/recents_tv_background_gradient.xml
index e98d43f..1e52a91 100644
--- a/packages/SystemUI/res/drawable/recents_tv_background_gradient.xml
+++ b/packages/SystemUI/res/drawable/recents_tv_background_gradient.xml
@@ -16,7 +16,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
- android:startColor="#99000000"
- android:endColor="#E6000000"
+ android:startColor="#4C000000"
+ android:endColor="#72000000"
android:angle="90"/>
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/tv_pip_button_focused.xml b/packages/SystemUI/res/drawable/tv_pip_button_focused.xml
index 405ea0c..0db1a57 100644
--- a/packages/SystemUI/res/drawable/tv_pip_button_focused.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_button_focused.xml
@@ -14,11 +14,5 @@
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <size
- android:width="34dp"
- android:height="34dp" />
- <solid
- android:color="#4DFFFFFF" />
-</shape>
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="#9AFFFFFF" android:radius="17dp" />
diff --git a/packages/SystemUI/res/drawable/tv_pip_close_button.xml b/packages/SystemUI/res/drawable/tv_pip_close_button.xml
deleted file mode 100644
index 186a4ba..0000000
--- a/packages/SystemUI/res/drawable/tv_pip_close_button.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- android:constantSize="true">
- <item android:state_focused="true">
- <layer-list>
- <item android:drawable="@drawable/tv_pip_button_focused" />
- <item android:drawable="@drawable/ic_close_white"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
- <item>
- <layer-list>
- <item android:drawable="@drawable/ic_close_white"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
-</selector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_full_button.xml b/packages/SystemUI/res/drawable/tv_pip_full_button.xml
deleted file mode 100644
index c48dc828..0000000
--- a/packages/SystemUI/res/drawable/tv_pip_full_button.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- android:constantSize="true">
- <item android:state_focused="true">
- <layer-list>
- <item android:drawable="@drawable/tv_pip_button_focused" />
- <item android:drawable="@drawable/ic_fullscreen_white_24dp"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
- <item>
- <layer-list>
- <item android:drawable="@drawable/ic_fullscreen_white_24dp"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
-</selector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_onboarding_remote.xml b/packages/SystemUI/res/drawable/tv_pip_onboarding_remote.xml
new file mode 100644
index 0000000..d46108a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/tv_pip_onboarding_remote.xml
@@ -0,0 +1,259 @@
+<?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.
+-->
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+ android:oneshot="false">
+
+ <item android:drawable="@drawable/remote_0" android:duration="13" />
+ <item android:drawable="@drawable/remote_1" android:duration="13" />
+ <item android:drawable="@drawable/remote_2" android:duration="13" />
+ <item android:drawable="@drawable/remote_3" android:duration="13" />
+ <item android:drawable="@drawable/remote_4" android:duration="13" />
+ <item android:drawable="@drawable/remote_5" android:duration="13" />
+ <item android:drawable="@drawable/remote_6" android:duration="13" />
+ <item android:drawable="@drawable/remote_7" android:duration="13" />
+ <item android:drawable="@drawable/remote_8" android:duration="13" />
+ <item android:drawable="@drawable/remote_9" android:duration="13" />
+ <item android:drawable="@drawable/remote_10" android:duration="13" />
+ <item android:drawable="@drawable/remote_11" android:duration="13" />
+ <item android:drawable="@drawable/remote_12" android:duration="13" />
+ <item android:drawable="@drawable/remote_13" android:duration="13" />
+ <item android:drawable="@drawable/remote_14" android:duration="13" />
+ <item android:drawable="@drawable/remote_15" android:duration="13" />
+ <item android:drawable="@drawable/remote_16" android:duration="13" />
+ <item android:drawable="@drawable/remote_17" android:duration="13" />
+ <item android:drawable="@drawable/remote_18" android:duration="13" />
+ <item android:drawable="@drawable/remote_19" android:duration="13" />
+ <item android:drawable="@drawable/remote_20" android:duration="13" />
+ <item android:drawable="@drawable/remote_21" android:duration="13" />
+ <item android:drawable="@drawable/remote_22" android:duration="13" />
+ <item android:drawable="@drawable/remote_23" android:duration="13" />
+ <item android:drawable="@drawable/remote_24" android:duration="13" />
+ <item android:drawable="@drawable/remote_25" android:duration="13" />
+ <item android:drawable="@drawable/remote_26" android:duration="13" />
+ <item android:drawable="@drawable/remote_27" android:duration="13" />
+ <item android:drawable="@drawable/remote_28" android:duration="13" />
+ <item android:drawable="@drawable/remote_29" android:duration="13" />
+ <item android:drawable="@drawable/remote_30" android:duration="13" />
+ <item android:drawable="@drawable/remote_31" android:duration="13" />
+ <item android:drawable="@drawable/remote_32" android:duration="13" />
+ <item android:drawable="@drawable/remote_33" android:duration="13" />
+ <item android:drawable="@drawable/remote_34" android:duration="13" />
+ <item android:drawable="@drawable/remote_35" android:duration="13" />
+ <item android:drawable="@drawable/remote_36" android:duration="13" />
+ <item android:drawable="@drawable/remote_37" android:duration="13" />
+ <item android:drawable="@drawable/remote_38" android:duration="13" />
+ <item android:drawable="@drawable/remote_39" android:duration="13" />
+ <item android:drawable="@drawable/remote_40" android:duration="13" />
+ <item android:drawable="@drawable/remote_41" android:duration="13" />
+ <item android:drawable="@drawable/remote_42" android:duration="13" />
+ <item android:drawable="@drawable/remote_43" android:duration="13" />
+ <item android:drawable="@drawable/remote_44" android:duration="13" />
+ <item android:drawable="@drawable/remote_45" android:duration="13" />
+ <item android:drawable="@drawable/remote_46" android:duration="13" />
+ <item android:drawable="@drawable/remote_47" android:duration="13" />
+ <item android:drawable="@drawable/remote_48" android:duration="13" />
+ <item android:drawable="@drawable/remote_49" android:duration="13" />
+ <item android:drawable="@drawable/remote_50" android:duration="13" />
+ <item android:drawable="@drawable/remote_51" android:duration="13" />
+ <item android:drawable="@drawable/remote_52" android:duration="13" />
+ <item android:drawable="@drawable/remote_53" android:duration="13" />
+ <item android:drawable="@drawable/remote_54" android:duration="13" />
+ <item android:drawable="@drawable/remote_55" android:duration="13" />
+ <item android:drawable="@drawable/remote_56" android:duration="13" />
+ <item android:drawable="@drawable/remote_57" android:duration="13" />
+ <item android:drawable="@drawable/remote_58" android:duration="13" />
+ <item android:drawable="@drawable/remote_59" android:duration="13" />
+ <item android:drawable="@drawable/remote_60" android:duration="13" />
+ <item android:drawable="@drawable/remote_61" android:duration="13" />
+ <item android:drawable="@drawable/remote_62" android:duration="13" />
+ <item android:drawable="@drawable/remote_63" android:duration="13" />
+ <item android:drawable="@drawable/remote_64" android:duration="13" />
+ <item android:drawable="@drawable/remote_65" android:duration="13" />
+ <item android:drawable="@drawable/remote_66" android:duration="13" />
+ <item android:drawable="@drawable/remote_67" android:duration="13" />
+ <item android:drawable="@drawable/remote_68" android:duration="13" />
+ <item android:drawable="@drawable/remote_69" android:duration="13" />
+ <item android:drawable="@drawable/remote_70" android:duration="13" />
+ <item android:drawable="@drawable/remote_71" android:duration="13" />
+ <item android:drawable="@drawable/remote_72" android:duration="13" />
+ <item android:drawable="@drawable/remote_73" android:duration="13" />
+ <item android:drawable="@drawable/remote_74" android:duration="13" />
+ <item android:drawable="@drawable/remote_75" android:duration="13" />
+ <item android:drawable="@drawable/remote_76" android:duration="13" />
+ <item android:drawable="@drawable/remote_77" android:duration="13" />
+ <item android:drawable="@drawable/remote_78" android:duration="13" />
+ <item android:drawable="@drawable/remote_79" android:duration="13" />
+ <item android:drawable="@drawable/remote_80" android:duration="13" />
+ <item android:drawable="@drawable/remote_81" android:duration="13" />
+ <item android:drawable="@drawable/remote_82" android:duration="13" />
+ <item android:drawable="@drawable/remote_83" android:duration="13" />
+ <item android:drawable="@drawable/remote_84" android:duration="13" />
+ <item android:drawable="@drawable/remote_85" android:duration="13" />
+ <item android:drawable="@drawable/remote_86" android:duration="13" />
+ <item android:drawable="@drawable/remote_87" android:duration="13" />
+ <item android:drawable="@drawable/remote_88" android:duration="13" />
+ <item android:drawable="@drawable/remote_89" android:duration="13" />
+ <item android:drawable="@drawable/remote_90" android:duration="13" />
+ <item android:drawable="@drawable/remote_91" android:duration="13" />
+ <item android:drawable="@drawable/remote_92" android:duration="13" />
+ <item android:drawable="@drawable/remote_93" android:duration="13" />
+ <item android:drawable="@drawable/remote_94" android:duration="13" />
+ <item android:drawable="@drawable/remote_95" android:duration="13" />
+ <item android:drawable="@drawable/remote_96" android:duration="13" />
+ <item android:drawable="@drawable/remote_97" android:duration="13" />
+ <item android:drawable="@drawable/remote_98" android:duration="13" />
+ <item android:drawable="@drawable/remote_99" android:duration="13" />
+ <item android:drawable="@drawable/remote_100" android:duration="13" />
+ <item android:drawable="@drawable/remote_101" android:duration="13" />
+ <item android:drawable="@drawable/remote_102" android:duration="13" />
+ <item android:drawable="@drawable/remote_103" android:duration="13" />
+ <item android:drawable="@drawable/remote_104" android:duration="13" />
+ <item android:drawable="@drawable/remote_105" android:duration="13" />
+ <item android:drawable="@drawable/remote_106" android:duration="13" />
+ <item android:drawable="@drawable/remote_107" android:duration="13" />
+ <item android:drawable="@drawable/remote_108" android:duration="13" />
+ <item android:drawable="@drawable/remote_109" android:duration="13" />
+ <item android:drawable="@drawable/remote_110" android:duration="13" />
+ <item android:drawable="@drawable/remote_111" android:duration="13" />
+ <item android:drawable="@drawable/remote_112" android:duration="13" />
+ <item android:drawable="@drawable/remote_113" android:duration="13" />
+ <item android:drawable="@drawable/remote_114" android:duration="13" />
+ <item android:drawable="@drawable/remote_115" android:duration="13" />
+ <item android:drawable="@drawable/remote_116" android:duration="13" />
+ <item android:drawable="@drawable/remote_117" android:duration="13" />
+ <item android:drawable="@drawable/remote_118" android:duration="13" />
+ <item android:drawable="@drawable/remote_119" android:duration="13" />
+ <item android:drawable="@drawable/remote_120" android:duration="13" />
+ <item android:drawable="@drawable/remote_121" android:duration="13" />
+ <item android:drawable="@drawable/remote_122" android:duration="13" />
+ <item android:drawable="@drawable/remote_123" android:duration="13" />
+ <item android:drawable="@drawable/remote_124" android:duration="13" />
+ <item android:drawable="@drawable/remote_125" android:duration="13" />
+ <item android:drawable="@drawable/remote_126" android:duration="13" />
+ <item android:drawable="@drawable/remote_127" android:duration="13" />
+ <item android:drawable="@drawable/remote_128" android:duration="13" />
+ <item android:drawable="@drawable/remote_129" android:duration="13" />
+ <item android:drawable="@drawable/remote_130" android:duration="13" />
+ <item android:drawable="@drawable/remote_131" android:duration="13" />
+ <item android:drawable="@drawable/remote_132" android:duration="13" />
+ <item android:drawable="@drawable/remote_133" android:duration="13" />
+ <item android:drawable="@drawable/remote_134" android:duration="13" />
+ <item android:drawable="@drawable/remote_135" android:duration="13" />
+ <item android:drawable="@drawable/remote_136" android:duration="13" />
+ <item android:drawable="@drawable/remote_137" android:duration="13" />
+ <item android:drawable="@drawable/remote_138" android:duration="13" />
+ <item android:drawable="@drawable/remote_139" android:duration="13" />
+ <item android:drawable="@drawable/remote_140" android:duration="13" />
+ <item android:drawable="@drawable/remote_141" android:duration="13" />
+ <item android:drawable="@drawable/remote_142" android:duration="13" />
+ <item android:drawable="@drawable/remote_143" android:duration="13" />
+ <item android:drawable="@drawable/remote_144" android:duration="13" />
+ <item android:drawable="@drawable/remote_145" android:duration="13" />
+ <item android:drawable="@drawable/remote_146" android:duration="13" />
+ <item android:drawable="@drawable/remote_147" android:duration="13" />
+ <item android:drawable="@drawable/remote_148" android:duration="13" />
+ <item android:drawable="@drawable/remote_149" android:duration="13" />
+ <item android:drawable="@drawable/remote_150" android:duration="13" />
+ <item android:drawable="@drawable/remote_151" android:duration="13" />
+ <item android:drawable="@drawable/remote_152" android:duration="13" />
+ <item android:drawable="@drawable/remote_153" android:duration="13" />
+ <item android:drawable="@drawable/remote_154" android:duration="13" />
+ <item android:drawable="@drawable/remote_155" android:duration="13" />
+ <item android:drawable="@drawable/remote_156" android:duration="13" />
+ <item android:drawable="@drawable/remote_157" android:duration="13" />
+ <item android:drawable="@drawable/remote_158" android:duration="13" />
+ <item android:drawable="@drawable/remote_159" android:duration="13" />
+ <item android:drawable="@drawable/remote_160" android:duration="13" />
+ <item android:drawable="@drawable/remote_161" android:duration="13" />
+ <item android:drawable="@drawable/remote_162" android:duration="13" />
+ <item android:drawable="@drawable/remote_163" android:duration="13" />
+ <item android:drawable="@drawable/remote_164" android:duration="13" />
+ <item android:drawable="@drawable/remote_165" android:duration="13" />
+ <item android:drawable="@drawable/remote_166" android:duration="13" />
+ <item android:drawable="@drawable/remote_167" android:duration="13" />
+ <item android:drawable="@drawable/remote_168" android:duration="13" />
+ <item android:drawable="@drawable/remote_169" android:duration="13" />
+ <item android:drawable="@drawable/remote_170" android:duration="13" />
+ <item android:drawable="@drawable/remote_171" android:duration="13" />
+ <item android:drawable="@drawable/remote_172" android:duration="13" />
+ <item android:drawable="@drawable/remote_173" android:duration="13" />
+ <item android:drawable="@drawable/remote_174" android:duration="13" />
+ <item android:drawable="@drawable/remote_175" android:duration="13" />
+ <item android:drawable="@drawable/remote_176" android:duration="13" />
+ <item android:drawable="@drawable/remote_177" android:duration="13" />
+ <item android:drawable="@drawable/remote_178" android:duration="13" />
+ <item android:drawable="@drawable/remote_179" android:duration="13" />
+ <item android:drawable="@drawable/remote_180" android:duration="13" />
+ <item android:drawable="@drawable/remote_181" android:duration="13" />
+ <item android:drawable="@drawable/remote_182" android:duration="13" />
+ <item android:drawable="@drawable/remote_183" android:duration="13" />
+ <item android:drawable="@drawable/remote_184" android:duration="13" />
+ <item android:drawable="@drawable/remote_185" android:duration="13" />
+ <item android:drawable="@drawable/remote_186" android:duration="13" />
+ <item android:drawable="@drawable/remote_187" android:duration="13" />
+ <item android:drawable="@drawable/remote_188" android:duration="13" />
+ <item android:drawable="@drawable/remote_189" android:duration="13" />
+ <item android:drawable="@drawable/remote_190" android:duration="13" />
+ <item android:drawable="@drawable/remote_191" android:duration="13" />
+ <item android:drawable="@drawable/remote_192" android:duration="13" />
+ <item android:drawable="@drawable/remote_193" android:duration="13" />
+ <item android:drawable="@drawable/remote_194" android:duration="13" />
+ <item android:drawable="@drawable/remote_195" android:duration="13" />
+ <item android:drawable="@drawable/remote_196" android:duration="13" />
+ <item android:drawable="@drawable/remote_197" android:duration="13" />
+ <item android:drawable="@drawable/remote_198" android:duration="13" />
+ <item android:drawable="@drawable/remote_199" android:duration="13" />
+ <item android:drawable="@drawable/remote_200" android:duration="13" />
+ <item android:drawable="@drawable/remote_201" android:duration="13" />
+ <item android:drawable="@drawable/remote_202" android:duration="13" />
+ <item android:drawable="@drawable/remote_203" android:duration="13" />
+ <item android:drawable="@drawable/remote_204" android:duration="13" />
+ <item android:drawable="@drawable/remote_205" android:duration="13" />
+ <item android:drawable="@drawable/remote_206" android:duration="13" />
+ <item android:drawable="@drawable/remote_207" android:duration="13" />
+ <item android:drawable="@drawable/remote_208" android:duration="13" />
+ <item android:drawable="@drawable/remote_209" android:duration="13" />
+ <item android:drawable="@drawable/remote_210" android:duration="13" />
+ <item android:drawable="@drawable/remote_211" android:duration="13" />
+ <item android:drawable="@drawable/remote_212" android:duration="13" />
+ <item android:drawable="@drawable/remote_213" android:duration="13" />
+ <item android:drawable="@drawable/remote_214" android:duration="13" />
+ <item android:drawable="@drawable/remote_215" android:duration="13" />
+ <item android:drawable="@drawable/remote_216" android:duration="13" />
+ <item android:drawable="@drawable/remote_217" android:duration="13" />
+ <item android:drawable="@drawable/remote_218" android:duration="13" />
+ <item android:drawable="@drawable/remote_219" android:duration="13" />
+ <item android:drawable="@drawable/remote_220" android:duration="13" />
+ <item android:drawable="@drawable/remote_221" android:duration="13" />
+ <item android:drawable="@drawable/remote_222" android:duration="13" />
+ <item android:drawable="@drawable/remote_223" android:duration="13" />
+ <item android:drawable="@drawable/remote_224" android:duration="13" />
+ <item android:drawable="@drawable/remote_225" android:duration="13" />
+ <item android:drawable="@drawable/remote_226" android:duration="13" />
+ <item android:drawable="@drawable/remote_227" android:duration="13" />
+ <item android:drawable="@drawable/remote_228" android:duration="13" />
+ <item android:drawable="@drawable/remote_229" android:duration="13" />
+ <item android:drawable="@drawable/remote_230" android:duration="13" />
+ <item android:drawable="@drawable/remote_231" android:duration="13" />
+ <item android:drawable="@drawable/remote_232" android:duration="13" />
+ <item android:drawable="@drawable/remote_233" android:duration="13" />
+ <item android:drawable="@drawable/remote_234" android:duration="13" />
+ <item android:drawable="@drawable/remote_235" android:duration="13" />
+ <item android:drawable="@drawable/remote_236" android:duration="13" />
+ <item android:drawable="@drawable/remote_237" android:duration="13" />
+ <item android:drawable="@drawable/remote_238" android:duration="13" />
+ <item android:drawable="@drawable/remote_239" android:duration="13" />
+</animation-list>
diff --git a/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml b/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml
index e247dec..2b58fc5 100644
--- a/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml
@@ -16,8 +16,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
- <gradient
- android:startColor="#B2000000"
- android:endColor="#00000000"
- android:angle="90"/>
+ <stroke android:width="1dp" android:color="#33FFFFFF" />
</shape>
diff --git a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml b/packages/SystemUI/res/drawable/tv_pip_overlay_text_background.xml
similarity index 61%
copy from packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
copy to packages/SystemUI/res/drawable/tv_pip_overlay_text_background.xml
index 681ff91..e247dec 100644
--- a/packages/SystemUI/res/anim/tv_pip_controls_text_in_recents_focus_gain_animation.xml
+++ b/packages/SystemUI/res/drawable/tv_pip_overlay_text_background.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
+<!--
+ Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:propertyName="alpha"
- android:valueTo="1"
- android:interpolator="@android:interpolator/fast_out_slow_in"
- android:duration="@integer/recents_tv_pip_focus_anim_duration" />
+ <gradient
+ android:startColor="#B2000000"
+ android:endColor="#00000000"
+ android:angle="90"/>
+</shape>
diff --git a/packages/SystemUI/res/drawable/tv_pip_pause_button.xml b/packages/SystemUI/res/drawable/tv_pip_pause_button.xml
deleted file mode 100644
index bcc8973..0000000
--- a/packages/SystemUI/res/drawable/tv_pip_pause_button.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- android:constantSize="true">
- <item android:state_focused="true">
- <layer-list>
- <item android:drawable="@drawable/tv_pip_button_focused" />
- <item android:drawable="@drawable/ic_pause_white_24dp"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
- <item>
- <layer-list>
- <item android:drawable="@drawable/ic_pause_white_24dp"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
-</selector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_play_button.xml b/packages/SystemUI/res/drawable/tv_pip_play_button.xml
deleted file mode 100644
index f77ea1d..0000000
--- a/packages/SystemUI/res/drawable/tv_pip_play_button.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- android:constantSize="true">
- <item android:state_focused="true">
- <layer-list>
- <item android:drawable="@drawable/tv_pip_button_focused" />
- <item android:drawable="@drawable/ic_play_arrow_white_24dp"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
- <item>
- <layer-list>
- <item android:drawable="@drawable/ic_play_arrow_white_24dp"
- android:top="@dimen/tv_pip_button_icon_padding"
- android:bottom="@dimen/tv_pip_button_icon_padding"
- android:left="@dimen/tv_pip_button_icon_padding"
- android:right="@dimen/tv_pip_button_icon_padding" />
- </layer-list>
- </item>
-</selector>
diff --git a/packages/SystemUI/res/layout/recents_on_tv.xml b/packages/SystemUI/res/layout-television/recents_on_tv.xml
similarity index 88%
rename from packages/SystemUI/res/layout/recents_on_tv.xml
rename to packages/SystemUI/res/layout-television/recents_on_tv.xml
index 28ea66d..1dbd1b3 100644
--- a/packages/SystemUI/res/layout/recents_on_tv.xml
+++ b/packages/SystemUI/res/layout-television/recents_on_tv.xml
@@ -19,7 +19,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
- android:clipToPadding="false">
+ android:clipToPadding="false"
+ android:background="@drawable/recents_tv_background_gradient">
<com.android.systemui.recents.tv.views.TaskStackHorizontalGridView
android:id="@+id/task_list"
android:layout_width="wrap_content"
@@ -34,9 +35,9 @@
<!-- Placeholder view to give focus to the PIP menus. -->
<View
android:id="@+id/pip"
- android:layout_width="0dp"
- android:layout_height="0dp"
+ android:layout_width="1dp"
+ android:layout_height="1dp"
android:focusable="true"
- android:visibility="gone" />
+ android:visibility="visible" />
</com.android.systemui.recents.tv.views.RecentsTvView>
diff --git a/packages/SystemUI/res/layout-television/recents_tv_card_dismiss.xml b/packages/SystemUI/res/layout-television/recents_tv_card_dismiss.xml
new file mode 100644
index 0000000..186a058
--- /dev/null
+++ b/packages/SystemUI/res/layout-television/recents_tv_card_dismiss.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/card_dismiss"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_gravity="center_horizontal"
+ android:alpha="0.0"
+ tools:showIn="@layout/recents_tv_task_card_view">
+ <ImageView
+ android:id="@+id/card_dismiss_icon"
+ android:layout_width="@dimen/recents_tv_dismiss_icon_size"
+ android:layout_height="@dimen/recents_tv_dismiss_icon_size"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="@dimen/recents_tv_dismiss_icon_top_margin"
+ android:layout_marginBottom="@dimen/recents_tv_dismiss_icon_bottom_margin"
+ android:src="@drawable/ic_cancel_white_24dp"/>
+ <TextView
+ android:id="@+id/card_dismiss_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="@dimen/recents_tv_dismiss_text_size"
+ android:fontFamily="@string/font_roboto_light"
+ android:textColor="@color/recents_tv_dismiss_text_color"
+ android:text="@string/recents_tv_dismiss"
+ android:layout_gravity="center_horizontal"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout-television/recents_tv_card_info_field.xml b/packages/SystemUI/res/layout-television/recents_tv_card_info_field.xml
new file mode 100644
index 0000000..20397c3
--- /dev/null
+++ b/packages/SystemUI/res/layout-television/recents_tv_card_info_field.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/card_info_field"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ tools:showIn="@layout/recents_tv_task_card_view_fallback_banner">
+ <ImageView
+ android:id="@+id/card_extra_badge"
+ android:layout_width="@dimen/recents_tv_card_extra_badge_size"
+ android:layout_height="@dimen/recents_tv_card_extra_badge_size"
+ android:layout_marginBottom="@dimen/recents_tv_icon_padding_bottom"
+ android:scaleType="fitCenter"
+ android:layout_centerVertical="true"
+ android:layout_alignParentEnd="true"/>
+ <TextView
+ android:id="@+id/card_title_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:includeFontPadding="true"
+ android:singleLine="true"
+ android:shadowColor="@color/recents_tv_text_shadow_color"
+ android:shadowRadius="5"
+ android:shadowDx="0"
+ android:shadowDy="0"
+ android:textColor="@color/recents_tv_card_title_text_color"
+ android:fontFamily="@string/font_roboto_regular"
+ android:textSize="@dimen/recents_tv_title_text_size"
+ android:paddingStart="@dimen/recents_tv_text_padding_start"
+ android:layout_marginBottom="@dimen/recents_tv_text_padding_bottom"
+ android:ellipsize="end"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout-television/recents_tv_task_card_view.xml b/packages/SystemUI/res/layout-television/recents_tv_task_card_view.xml
new file mode 100644
index 0000000..9b89aa0
--- /dev/null
+++ b/packages/SystemUI/res/layout-television/recents_tv_task_card_view.xml
@@ -0,0 +1,46 @@
+<?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.
+-->
+<com.android.systemui.recents.tv.views.TaskCardView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:layout_gravity="center"
+ android:layout_centerInParent="true"
+ android:clipToPadding="false"
+ android:orientation="vertical" >
+ <include layout="@layout/recents_tv_card_info_field"/>
+ <LinearLayout
+ android:id="@+id/card_view_thumbnail"
+ android:layout_width="@dimen/recents_tv_card_width"
+ android:layout_height="@dimen/recents_tv_screenshot_height"
+ android:gravity="center"
+ android:orientation="vertical"
+ android:background="@color/recents_tv_card_background_color"
+ android:layout_centerHorizontal="true" >
+
+ <ImageView
+ android:id="@+id/card_view_banner_icon"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_centerHorizontal="true"
+ android:scaleType="centerCrop"
+ android:gravity="center" />
+
+ </LinearLayout>
+ <include layout="@layout/recents_tv_card_dismiss"/>
+</com.android.systemui.recents.tv.views.TaskCardView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/docked_stack_divider.xml b/packages/SystemUI/res/layout/docked_stack_divider.xml
index cfaf018..70e5451 100644
--- a/packages/SystemUI/res/layout/docked_stack_divider.xml
+++ b/packages/SystemUI/res/layout/docked_stack_divider.xml
@@ -24,6 +24,11 @@
android:id="@+id/docked_divider_background"
android:background="@color/docked_divider_background"/>
+ <com.android.systemui.stackdivider.MinimizedDockShadow
+ style="@style/DockedDividerMinimizedShadow"
+ android:id="@+id/minimized_dock_shadow"
+ android:alpha="0"/>">
+
<com.android.systemui.stackdivider.DividerHandleView
style="@style/DockedDividerHandle"
android:id="@+id/docked_divider_handle"
diff --git a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
index 3865020..63b759b 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
@@ -15,10 +15,10 @@
~ 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">
@@ -29,7 +29,8 @@
android:layout_marginEnd="32dp"
android:layout_gravity="center_vertical"
android:visibility="gone"
- android:layout_alignParentStart="true"/>
+ android:layout_alignParentStart="true"
+ android:layout_centerVertical="true"/>
<TextView
android:id="@+id/keyboard_shortcuts_keyword"
android:layout_toEndOf="@+id/keyboard_shortcuts_icon"
@@ -41,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"
@@ -50,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
index 0cecb96..5db6789 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml
@@ -21,4 +21,4 @@
android:padding="@dimen/ksh_item_padding"
android:layout_marginStart="@dimen/ksh_item_margin_start"
android:scaleType="fitXY"
- android:background="@color/ksh_key_item_background"/>
+ 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 1215029..31a8773 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
@@ -19,7 +19,8 @@
android:layout_height="wrap_content"
android:padding="@dimen/ksh_item_padding"
android:layout_marginStart="@dimen/ksh_item_margin_start"
- android:background="@color/ksh_key_item_background"
+ android:background="@drawable/ksh_key_item_background"
android:textColor="@color/ksh_key_item_color"
android:singleLine="true"
+ android:gravity="center"
android:textSize="@dimen/ksh_item_text_size"/>
diff --git a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
index 9dd3ad2..55d7fab 100644
--- a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
+++ b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
@@ -33,7 +33,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
- android:gravity="center" />
+ android:gravity="center"
+ android:importantForAccessibility="yes"
+ android:focusable="true" />
<TextView
android:id="@android:id/edit"
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/recents.xml b/packages/SystemUI/res/layout/recents.xml
index 186aaf6..ae89631 100644
--- a/packages/SystemUI/res/layout/recents.xml
+++ b/packages/SystemUI/res/layout/recents.xml
@@ -25,6 +25,14 @@
android:layout_height="match_parent">
</com.android.systemui.recents.views.RecentsView>
+ <!-- Incompatible task overlay -->
+ <ViewStub android:id="@+id/incompatible_app_overlay_stub"
+ android:inflatedId="@+id/incompatible_app_overlay"
+ android:layout="@layout/recents_incompatible_app_overlay"
+ android:layout_width="match_parent"
+ android:layout_height="128dp"
+ android:layout_gravity="center_horizontal|top" />
+
<!-- Nav Bar Scrim View -->
<ImageView
android:id="@+id/nav_bar_scrim"
diff --git a/packages/SystemUI/res/layout/recents_incompatible_app_overlay.xml b/packages/SystemUI/res/layout/recents_incompatible_app_overlay.xml
new file mode 100644
index 0000000..2b49dd3
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_incompatible_app_overlay.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:alpha="0"
+ android:background="#88000000"
+ android:forceHasOverlappingRendering="false">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:drawableTop="@drawable/recents_info_light"
+ android:drawablePadding="8dp"
+ android:text="@string/recents_incompatible_app_message" />
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index c813818..1978a93 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -18,34 +18,43 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true">
- <FrameLayout
- android:id="@+id/task_view_content"
+ <com.android.systemui.recents.views.TaskViewThumbnail
+ android:id="@+id/task_view_thumbnail"
android:layout_width="match_parent"
- android:layout_height="match_parent">
- <com.android.systemui.recents.views.TaskViewThumbnail
- android:id="@+id/task_view_thumbnail"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- <include layout="@layout/recents_task_view_header" />
- <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
- android:id="@+id/lock_to_app_fab"
- android:layout_width="@dimen/recents_lock_to_app_size"
- android:layout_height="@dimen/recents_lock_to_app_size"
- android:layout_gravity="bottom|right"
- android:layout_marginRight="15dp"
- android:layout_marginBottom="15dp"
- android:translationZ="4dp"
- android:contentDescription="@string/recents_lock_to_app_button_label"
- android:background="@drawable/recents_lock_to_task_button_bg"
- android:visibility="invisible"
- android:alpha="0">
- <ImageView
- android:layout_width="@dimen/recents_lock_to_app_icon_size"
- android:layout_height="@dimen/recents_lock_to_app_icon_size"
- android:layout_gravity="center"
- android:src="@drawable/recents_lock_to_app_pin" />
- </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
- </FrameLayout>
+ android:layout_height="match_parent" />
+
+ <include layout="@layout/recents_task_view_header" />
+
+ <!-- TODO: Move this into a view stub -->
+ <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
+ android:id="@+id/lock_to_app_fab"
+ android:layout_width="@dimen/recents_lock_to_app_size"
+ android:layout_height="@dimen/recents_lock_to_app_size"
+ android:layout_gravity="bottom|right"
+ android:layout_marginRight="15dp"
+ android:layout_marginBottom="15dp"
+ android:translationZ="4dp"
+ android:contentDescription="@string/recents_lock_to_app_button_label"
+ android:background="@drawable/recents_lock_to_task_button_bg"
+ android:visibility="invisible"
+ android:alpha="0">
+ <ImageView
+ android:layout_width="@dimen/recents_lock_to_app_icon_size"
+ android:layout_height="@dimen/recents_lock_to_app_icon_size"
+ android:layout_gravity="center"
+ android:src="@drawable/recents_lock_to_app_pin" />
+ </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
+
+ <!-- The incompatible app toast -->
+ <ViewStub android:id="@+id/incompatible_app_toast_stub"
+ android:inflatedId="@+id/incompatible_app_toast"
+ android:layout="@*android:layout/transient_notification"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|center_horizontal"
+ android:layout_marginTop="48dp"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp" />
</com.android.systemui.recents.views.TaskView>
diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/res/layout/recents_task_view_header.xml
index 2b3c5df..2df57bf 100644
--- a/packages/SystemUI/res/layout/recents_task_view_header.xml
+++ b/packages/SystemUI/res/layout/recents_task_view_header.xml
@@ -31,40 +31,19 @@
android:paddingBottom="8dp"
android:paddingStart="16dp"
android:paddingEnd="12dp" />
- <LinearLayout
- android:id="@+id/title_container"
+ <TextView
+ android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|start"
- android:orientation="vertical">
- <TextView
- android:id="@+id/title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="start"
- android:textSize="16sp"
- android:textColor="#ffffffff"
- android:text="@string/recents_empty_message"
- android:fontFamily="sans-serif-medium"
- android:singleLine="true"
- android:maxLines="1"
- android:ellipsize="marquee"
- android:fadingEdge="horizontal" />
- <TextView
- android:id="@+id/sub_title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="start"
- android:textSize="11sp"
- android:textColor="#ffffffff"
- android:text="@string/recents_launch_non_dockable_task_label"
- android:fontFamily="sans-serif-medium"
- android:singleLine="true"
- android:maxLines="1"
- android:ellipsize="marquee"
- android:fadingEdge="horizontal"
- android:visibility="gone" />
- </LinearLayout>
+ android:textSize="16sp"
+ android:textColor="#ffffffff"
+ android:text="@string/recents_empty_message"
+ android:fontFamily="sans-serif-medium"
+ android:singleLine="true"
+ android:maxLines="1"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal" />
<com.android.systemui.recents.views.FixedSizeImageView
android:id="@+id/move_task"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/recents_tv_task_card_view.xml b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
deleted file mode 100644
index 766ef60..0000000
--- a/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.systemui.recents.tv.views.TaskCardView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:layout_gravity="center"
- android:layout_centerInParent="true"
- android:orientation="vertical"
- android:layoutDirection="ltr">
-
- <LinearLayout
- android:id="@+id/recents_tv_card"
- android:layout_width="@dimen/recents_tv_card_width"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:layout_gravity="center"
- android:orientation="vertical" >
- <LinearLayout
- android:id="@+id/card_info_field"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <ImageView
- android:id="@+id/card_extra_badge"
- android:layout_width="@dimen/recents_tv_card_extra_badge_size"
- android:layout_height="@dimen/recents_tv_card_extra_badge_size"
- android:layout_marginBottom="@dimen/recents_tv_icon_padding_bottom"
- android:layout_marginEnd="@dimen/recents_tv_icon_padding_end"
- android:scaleType="fitCenter"
- android:layout_centerVertical="true"
- android:layout_alignParentRight="true" />
- <TextView
- android:id="@+id/card_title_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="false"
- android:includeFontPadding="true"
- android:minLines="1"
- android:maxLines="1"
- android:textColor="@color/recents_tv_card_title_text_color"
- android:fontFamily="@string/font_roboto_regular"
- android:textSize="@dimen/recents_tv_title_text_size"
- android:layout_marginBottom="@dimen/recents_tv_text_padding_bottom"
- android:ellipsize="end"/>
- </LinearLayout>
- <ImageView
- android:id="@+id/card_view_thumbnail"
- android:layout_width="match_parent"
- android:layout_height="@dimen/recents_tv_screenshot_height"
- android:scaleType="centerCrop"
- android:gravity="center"
- android:layout_alignParentTop="true"
- android:layout_centerHorizontal="true"
- android:layout_below="@id/card_title_text" />
- </LinearLayout>
- <LinearLayout
- android:id="@+id/card_dismiss"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_gravity="center_horizontal"
- android:layout_below="@id/recents_tv_card"
- android:alpha="0.0">
- <ImageView
- android:id="@+id/card_dismiss_icon"
- android:layout_width="@dimen/recents_tv_dismiss_icon_size"
- android:layout_height="@dimen/recents_tv_dismiss_icon_size"
- android:layout_gravity="center_horizontal"
- android:layout_marginTop="@dimen/recents_tv_dismiss_icon_top_margin"
- android:layout_marginBottom="@dimen/recents_tv_dismiss_icon_bottom_margin"
- android:src="@drawable/ic_cancel_white_24dp" />
- <TextView
- android:id="@+id/card_dismiss_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="@dimen/recents_tv_dismiss_text_size"
- android:fontFamily="@string/font_roboto_light"
- android:textColor="@color/recents_tv_dismiss_text_color"
- android:text="@string/recents_tv_dismiss"
- android:layout_gravity="center_horizontal" />
- </LinearLayout>
-</com.android.systemui.recents.tv.views.TaskCardView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/tv_pip_control_button.xml b/packages/SystemUI/res/layout/tv_pip_control_button.xml
new file mode 100644
index 0000000..0beeda1
--- /dev/null
+++ b/packages/SystemUI/res/layout/tv_pip_control_button.xml
@@ -0,0 +1,42 @@
+<?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.
+*/
+-->
+
+<!-- Layout for {@link com.android.systemui.tv.pip.PipControlButtonView}. -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <ImageView android:id="@+id/button"
+ android:layout_width="34dp"
+ android:layout_height="34dp"
+ android:padding="5dp"
+ android:focusable="true"
+ android:src="@drawable/ic_fullscreen_white_24dp"
+ android:background="@drawable/tv_pip_button_focused"
+ android:layerType="software" />
+
+ <TextView android:id="@+id/desc"
+ android:layout_width="100dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="3dp"
+ android:gravity="center"
+ android:text="@string/pip_fullscreen"
+ android:alpha="0"
+ android:fontFamily="sans-serif"
+ android:textSize="12sp"
+ android:textColor="#EEEEEE" />
+</merge>
diff --git a/packages/SystemUI/res/layout/tv_pip_controls.xml b/packages/SystemUI/res/layout/tv_pip_controls.xml
index 563441f..0a2f320 100644
--- a/packages/SystemUI/res/layout/tv_pip_controls.xml
+++ b/packages/SystemUI/res/layout/tv_pip_controls.xml
@@ -20,77 +20,26 @@
<!-- Layout for {@link com.android.systemui.tv.pip.PipControlsView}. -->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <LinearLayout
+ <com.android.systemui.tv.pip.PipControlButtonView
+ android:id="@+id/full_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:gravity="center">
+ android:src="@drawable/ic_fullscreen_white_24dp"
+ android:text="@string/pip_fullscreen" />
- <ImageView android:id="@+id/full_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:focusable="true"
- android:src="@drawable/tv_pip_full_button" />
-
- <TextView android:id="@+id/full_desc"
- android:layout_width="100dp"
- android:layout_height="wrap_content"
- android:layout_marginTop="3dp"
- android:gravity="center"
- android:visibility="invisible"
- android:text="@string/pip_fullscreen"
- android:fontFamily="sans-serif"
- android:textSize="12sp"
- android:textColor="#EEEEEE" />
- </LinearLayout>
-
- <LinearLayout
+ <com.android.systemui.tv.pip.PipControlButtonView
+ android:id="@+id/close_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginStart="-50dp"
- android:orientation="vertical"
- android:gravity="center">
+ android:src="@drawable/ic_close_white"
+ android:text="@string/pip_close" />
- <ImageView android:id="@+id/close_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:focusable="true"
- android:src="@drawable/tv_pip_close_button" />
-
- <TextView android:id="@+id/close_desc"
- android:layout_width="100dp"
- android:layout_height="wrap_content"
- android:layout_marginTop="3dp"
- android:gravity="center"
- android:visibility="invisible"
- android:text="@string/pip_close"
- android:fontFamily="sans-serif"
- android:textSize="12sp"
- android:textColor="#EEEEEE" />
- </LinearLayout>
-
- <LinearLayout android:id="@+id/play_pause"
+ <com.android.systemui.tv.pip.PipControlButtonView
+ android:id="@+id/play_pause_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginStart="-50dp"
- android:orientation="vertical"
- android:gravity="center" >
-
- <ImageView android:id="@+id/play_pause_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:focusable="true"
- android:src="@drawable/tv_pip_pause_button" />
-
- <TextView android:id="@+id/play_pause_desc"
- android:layout_width="100dp"
- android:layout_height="wrap_content"
- android:layout_marginTop="3dp"
- android:gravity="center"
- android:visibility="invisible"
- android:text="@string/pip_pause"
- android:fontFamily="sans-serif"
- android:textSize="12sp"
- android:textColor="#EEEEEE" />
- </LinearLayout>
+ android:src="@drawable/ic_pause_white_24dp"
+ android:text="@string/pip_pause" />
</merge>
diff --git a/packages/SystemUI/res/layout/tv_pip_menu.xml b/packages/SystemUI/res/layout/tv_pip_menu.xml
index 2647a99..72a4929 100644
--- a/packages/SystemUI/res/layout/tv_pip_menu.xml
+++ b/packages/SystemUI/res/layout/tv_pip_menu.xml
@@ -29,5 +29,6 @@
<com.android.systemui.tv.pip.PipControlsView
android:id="@+id/pip_controls"
android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"
+ android:alpha="0" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/tv_pip_onboarding.xml b/packages/SystemUI/res/layout/tv_pip_onboarding.xml
index b0814cf..288ad1e 100644
--- a/packages/SystemUI/res/layout/tv_pip_onboarding.xml
+++ b/packages/SystemUI/res/layout/tv_pip_onboarding.xml
@@ -17,47 +17,81 @@
*/
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pip_onboarding"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="#C00288D1"
- android:gravity="top|center_horizontal"
+ android:background="#B3000000"
android:orientation="vertical">
- <!-- A rectangle arounds the PIP.
- Size and positions will be programatically set up
- to comply with config_defaultPictureInPictureBounds. -->
<ImageView
- android:id="@+id/pip_outline"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:src="@drawable/tv_pip_outline" />
+ android:id="@+id/remote"
+ android:layout_width="72dp"
+ android:layout_height="273dp"
+ android:layout_marginTop="136dp"
+ android:layout_marginStart="304dp"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentStart="true"
+ android:adjustViewBounds="true"
+ android:src="@drawable/remote"
+ android:alpha="0" />
+ <ImageView
+ android:id="@+id/remote_button"
+ android:layout_width="50dp"
+ android:layout_height="50dp"
+ android:layout_marginTop="256dp"
+ android:layout_marginStart="315dp"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentStart="true"
+ android:scaleType="fitXY"
+ android:src="@drawable/tv_pip_onboarding_remote"
+ android:alpha="0" />
<TextView
+ android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="24dp"
- android:paddingStart="24dp"
- android:paddingEnd="24dp"
+ android:layout_marginTop="188dp"
+ android:layout_marginStart="406dp"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentStart="true"
android:fontFamily="sans-serif"
- android:textSize="16sp"
+ android:textSize="24sp"
android:textColor="#EEEEEE"
- android:lineSpacingMultiplier="1.28"
- android:gravity="top|center_horizontal"
- android:text="@string/pip_onboarding_description" />
+ android:text="@string/pip_onboarding_title"
+ android:alpha="0" />
+ <TextView
+ android:id="@+id/description"
+ android:layout_width="200dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="4dp"
+ android:layout_marginStart="408dp"
+ android:layout_below="@id/title"
+ android:layout_alignParentStart="true"
+ android:fontFamily="sans-serif"
+ android:textSize="14sp"
+ android:textColor="#EEEEEE"
+ android:lineSpacingMultiplier="1.46286"
+ android:text="@string/pip_onboarding_description"
+ android:alpha="0" />
<Button
- android:id="@+id/close"
+ android:id="@+id/button"
android:layout_width="wrap_content"
- android:layout_height="36dp"
- android:layout_marginTop="24dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:layout_marginStart="408dp"
+ android:layout_below="@id/description"
+ android:layout_alignParentStart="true"
android:gravity="center"
+ android:paddingTop="10dp"
+ android:paddingBottom="10dp"
android:paddingStart="24dp"
android:paddingEnd="24dp"
android:fontFamily="sans-serif-condensed"
android:textSize="16sp"
- android:textColor="#026089"
+ android:textColor="#FFFFFF"
android:textAllCaps="true"
android:text="@string/pip_onboarding_button"
- android:background="#EEEEEE"
+ android:alpha="0"
+ android:background="#009688"
android:elevation="4dp" />
-</LinearLayout>
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/tv_pip_overlay.xml b/packages/SystemUI/res/layout/tv_pip_overlay.xml
index 64bf3b5..608680c 100644
--- a/packages/SystemUI/res/layout/tv_pip_overlay.xml
+++ b/packages/SystemUI/res/layout/tv_pip_overlay.xml
@@ -19,7 +19,8 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:background="@drawable/tv_pip_overlay_background">
<TextView
android:id="@+id/guide_overlay"
@@ -33,7 +34,7 @@
android:textSize="14sp"
android:textColor="#EEEEEE"
android:fontFamily="sans-serif"
- android:background="@drawable/tv_pip_overlay_background"
+ android:background="@drawable/tv_pip_overlay_text_background"
android:lineSpacingMultiplier="1.465"
android:gravity="center"
android:maxLines="2"
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..41537a3 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/styles.xml b/packages/SystemUI/res/values-land/styles.xml
index b711faa..82cba58 100644
--- a/packages/SystemUI/res/values-land/styles.xml
+++ b/packages/SystemUI/res/values-land/styles.xml
@@ -31,4 +31,8 @@
<item name="android:layout_height">96dp</item>
</style>
+ <style name="DockedDividerMinimizedShadow">
+ <item name="android:layout_width">8dp</item>
+ <item name="android:layout_height">match_parent</item>
+ </style>
</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..e44642d 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 41075e3..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-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..1dd7254 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-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/colors.xml b/packages/SystemUI/res/values/colors.xml
index d9fcf42..d26fb06 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -151,7 +151,9 @@
<color name="docked_divider_background">#ff000000</color>
<color name="docked_divider_handle">#ffffff</color>
- <drawable name="forced_resizable_background">#40000000</drawable>
+ <drawable name="forced_resizable_background">#59000000</drawable>
+ <color name="minimize_dock_shadow_start">#60000000</color>
+ <color name="minimize_dock_shadow_end">#00000000</color>
<color name="default_remote_input_background">@*android:color/notification_default_color</color>
<color name="remote_input_hint">#99ffffff</color>
@@ -166,11 +168,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">#eeeeee</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/colors_tv.xml b/packages/SystemUI/res/values/colors_tv.xml
index 4126d3c..3817da0 100644
--- a/packages/SystemUI/res/values/colors_tv.xml
+++ b/packages/SystemUI/res/values/colors_tv.xml
@@ -17,7 +17,8 @@
*/
-->
<resources>
- <color name="recents_tv_card_background_color">#FF37474F</color>
+ <color name="recents_tv_card_background_color">#FF263238</color>
<color name="recents_tv_card_title_text_color">#CCEEEEEE</color>
<color name="recents_tv_dismiss_text_color">#7FEEEEEE</color>
+ <color name="recents_tv_text_shadow_color">#7F000000</color>
</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index cf2e338..03b9837 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -606,8 +606,8 @@
<dimen name="recents_layout_z_min">3dp</dimen>
<dimen name="recents_layout_z_max">24dp</dimen>
- <!-- The margin between the freeform and stack. We also don't want this to change across
- configurations that Recents can be opened in, so we define them statically for all
+ <!-- The margin between the freeform and stack. We also don't want this to change across
+ configurations that Recents can be opened in, so we define them statically for all
display sizes. -->
<dimen name="recents_freeform_layout_bottom_margin">16dp</dimen>
@@ -651,4 +651,7 @@
<!-- The amount to translate when animating the removal of a task. -->
<dimen name="recents_task_view_remove_anim_translation_x">100dp</dimen>
+
+ <!-- The alpha to apply to the recents row when it doesn't have focus -->
+ <item name="recents_recents_row_dim_alpha" format="float" type="dimen">0.5</item>
</resources>
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml
index f536f86..367dd1d 100644
--- a/packages/SystemUI/res/values/dimens_tv.xml
+++ b/packages/SystemUI/res/values/dimens_tv.xml
@@ -21,11 +21,13 @@
<dimen name="recents_tv_card_width">240dip</dimen>
<dimen name="recents_tv_screenshot_height">135dip</dimen>
<dimen name="recents_tv_card_extra_badge_size">20dip</dimen>
- <dimen name="recents_tv_banner_width">114dip</dimen>
- <dimen name="recents_tv_banner_height">64dip</dimen>
+ <dimen name="recents_tv_banner_width">130dip</dimen>
+ <dimen name="recents_tv_banner_height">72dip</dimen>
+ <dimen name="recents_tv_fallback_icon_width">40dip</dimen>
+ <dimen name="recents_tv_fallback_icon_height">40dip</dimen>
<dimen name="recents_tv_banner_margin_top">16dip</dimen>
<dimen name="recents_tv_icon_padding_bottom">8dip</dimen>
- <dimen name="recents_tv_icon_padding_end">12dip</dimen>
+ <dimen name="recents_tv_text_padding_start">12dip</dimen>
<dimen name="recents_tv_text_padding_bottom">12dip</dimen>
<!-- Padding for grid view in recents view on tv -->
@@ -54,8 +56,6 @@
<!-- Extra space around the PIP and its outline in PIP onboarding activity -->
<dimen name="tv_pip_bounds_space">3dp</dimen>
- <!-- 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>
diff --git a/packages/SystemUI/res/values/integers_tv.xml b/packages/SystemUI/res/values/integers_tv.xml
index 6984d5a..ebfd8ab 100644
--- a/packages/SystemUI/res/values/integers_tv.xml
+++ b/packages/SystemUI/res/values/integers_tv.xml
@@ -24,4 +24,7 @@
<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>
+
+ <!-- Duration of the onboarding animation duration -->
+ <integer name="tv_pip_onboarding_anim_duration">1000</integer>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a33b7a3..a4d7a18 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -735,10 +735,8 @@
<string name="recents_launch_disabled_message"><xliff:g id="app" example="Calendar">%s</xliff:g> is disabled in safe-mode.</string>
<!-- Recents: Stack action button string. [CHAR LIMIT=NONE] -->
<string name="recents_stack_action_button_label">Clear all</string>
- <!-- Recents: Non-dockable task drag message. [CHAR LIMIT=NONE] -->
- <string name="recents_drag_non_dockable_task_message">This app does not support multi-window</string>
- <!-- Recents: Non-dockable task launch sub header. [CHAR LIMIT=NONE] -->
- <string name="recents_launch_non_dockable_task_label">App does not support multi-window</string>
+ <!-- Recents: Incompatible task message. [CHAR LIMIT=NONE] -->
+ <string name="recents_incompatible_app_message">App doesn\'t support split screen</string>
<!-- Recents: MultiStack add stack split horizontal radio button. [CHAR LIMIT=NONE] -->
<string name="recents_multistack_add_stack_dialog_split_horizontal">Split Horizontal</string>
@@ -1594,4 +1592,10 @@
<!-- 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>
+
+ <!-- accessibility label for paging indicator in quick settings [CHAR LIMITi=NONE] -->
+ <string name="accessibility_quick_settings_page">Page <xliff:g name="current_page" example="1">%1$d</xliff:g> of <xliff:g name="num_pages" example="2">%2$d</xliff:g></string>
+
</resources>
diff --git a/packages/SystemUI/res/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml
index 52aba0d..dcd1654 100644
--- a/packages/SystemUI/res/values/strings_tv.xml
+++ b/packages/SystemUI/res/values/strings_tv.xml
@@ -31,8 +31,10 @@
<string name="pip_hold_home">Hold <b>HOME</b> to control PIP</string>
<!-- Picture-in-Picture (PIP) onboarding screen -->
<eat-comment />
+ <!-- Title for picture-in-picture (PIP) onboarding screen to indicate that an user is in PIP mode. [CHAR LIMIT=NONE] -->
+ <string name="pip_onboarding_title">PIP mode</string>
<!-- Description for picture-in-picture (PIP) onboarding screen to indicate that longpress HOME key to control PIP. [CHAR LIMIT=NONE] -->
- <string name="pip_onboarding_description">Press and hold the HOME button to control PIP</string>
+ <string name="pip_onboarding_description">To control PIP press and hold the <b>HOME</b> button on the remote</string>
<!-- Button to close picture-in-picture (PIP) onboarding screen. -->
<string name="pip_onboarding_button">Got it</string>
<!-- Dismiss icon description -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index f560a13..aeb484f 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -33,6 +33,7 @@
<item name="android:windowBackground">@color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowShowWallpaper">true</item>
+ <item name="android:windowDisablePreview">true</item>
</style>
<!-- Performance optimized Recents theme (no wallpaper) -->
@@ -308,6 +309,11 @@
<item name="android:layout_gravity">center_vertical</item>
</style>
+ <style name="DockedDividerMinimizedShadow">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">8dp</item>
+ </style>
+
<style name="DockedDividerHandle">
<item name="android:layout_gravity">center_horizontal</item>
<item name="android:layout_width">96dp</item>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index a130cf9..1af9075 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -100,10 +100,12 @@
</PreferenceScreen>
+ <!--
<Preference
android:key="color_transform"
android:title="@string/color_and_appearance"
android:fragment="com.android.systemui.tuner.ColorAndAppearanceFragment" />
+ -->
<PreferenceScreen
android:key="volume_and_do_not_disturb"
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
index 087f61e..076b5bc 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
@@ -37,7 +37,7 @@
import com.android.systemui.statusbar.policy.BatteryController;
-public class BatteryMeterDrawable extends Drawable implements DemoMode,
+public class BatteryMeterDrawable extends Drawable implements
BatteryController.BatteryStateChangeCallback {
private static final float ASPECT_RATIO = 9.5f / 14.5f;
@@ -184,14 +184,12 @@
mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
updateShowPercent();
- if (mDemoMode) return;
mBatteryController.addStateChangedCallback(this);
}
public void stopListening() {
mListening = false;
mContext.getContentResolver().unregisterContentObserver(mSettingObserver);
- if (mDemoMode) return;
mBatteryController.removeStateChangedCallback(this);
}
@@ -507,35 +505,6 @@
return 0;
}
- private boolean mDemoMode;
-
- @Override
- public void dispatchDemoCommand(String command, Bundle args) {
- if (!mDemoMode && command.equals(COMMAND_ENTER)) {
- mBatteryController.removeStateChangedCallback(this);
- mDemoMode = true;
- if (mListening) {
- mBatteryController.removeStateChangedCallback(this);
- }
- } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
- mDemoMode = false;
- postInvalidate();
- if (mListening) {
- mBatteryController.addStateChangedCallback(this);
- }
- } else if (mDemoMode && command.equals(COMMAND_BATTERY)) {
- String level = args.getString("level");
- String plugged = args.getString("plugged");
- if (level != null) {
- mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100);
- }
- if (plugged != null) {
- mPluggedIn = Boolean.parseBoolean(plugged);
- }
- postInvalidate();
- }
- }
-
private final class SettingObserver extends ContentObserver {
public SettingObserver() {
super(new Handler());
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
index 001d1f2..73b9d02 100644
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -32,7 +32,8 @@
/**
* Docks the top-most task and opens recents.
*/
- boolean dockTopTask(int dragMode, int stackCreateMode, Rect initialBounds);
+ boolean dockTopTask(int dragMode, int stackCreateMode, Rect initialBounds,
+ int metricsDockAction);
/**
* Called during a drag-from-navbar-in gesture.
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 455a69f..39a3412 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -63,7 +63,8 @@
* above.
*/
private final Class<?>[] SERVICES_PER_USER = new Class[] {
- com.android.systemui.recents.Recents.class
+ com.android.systemui.recents.Recents.class,
+ com.android.systemui.tv.pip.PipUI.class
};
/**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 66754a7..1abd073 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -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);
}
}
}
@@ -1479,13 +1477,14 @@
private void sendUserPresentBroadcast() {
synchronized (this) {
if (mBootCompleted) {
- final UserHandle currentUser = new UserHandle(KeyguardUpdateMonitor.getCurrentUser());
+ int currentUserId = KeyguardUpdateMonitor.getCurrentUser();
+ final UserHandle currentUser = new UserHandle(currentUserId);
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));
}
+ getLockPatternUtils().userPresent(currentUserId);
} else {
mBootSendUserPresent = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
index ba07bf4..e050b0d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
@@ -60,6 +60,8 @@
public void setLocation(float location) {
int index = (int) location;
+ setContentDescription(getContext().getString(R.string.accessibility_quick_settings_page,
+ (index + 1), getChildCount()));
int position = index << 1 | ((location != index) ? 1 : 0);
if (DEBUG) Log.d(TAG, "setLocation " + location + " " + index + " " + position);
@@ -118,6 +120,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/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 4d959d8..af81c19 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -87,6 +87,7 @@
public void setOnKeyguard(boolean onKeyguard) {
mOnKeyguard = onKeyguard;
+ mQuickQsPanel.setVisibility(mOnKeyguard ? View.INVISIBLE : View.VISIBLE);
if (mOnKeyguard) {
clearAnimationState();
}
@@ -290,7 +291,7 @@
@Override
public void onAnimationStarted() {
- mQuickQsPanel.setVisibility(View.VISIBLE);
+ mQuickQsPanel.setVisibility(mOnKeyguard ? View.INVISIBLE : View.VISIBLE);
if (mOnFirstPage) {
final int N = mTopFiveQs.size();
for (int i = 0; i < N; i++) {
@@ -302,12 +303,11 @@
private void clearAnimationState() {
final int N = mAllViews.size();
mQuickQsPanel.setAlpha(0);
- mQuickQsPanel.setVisibility(View.VISIBLE);
for (int i = 0; i < N; i++) {
View v = mAllViews.get(i);
v.setAlpha(1);
- v.setTranslationX(1);
- v.setTranslationY(1);
+ v.setTranslationX(0);
+ v.setTranslationY(0);
}
final int N2 = mTopFiveQs.size();
for (int i = 0; i < N2; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
index e3a4909..ef75562 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
@@ -70,8 +70,8 @@
super.onFinishInflate();
mQSPanel = (QSPanel) findViewById(R.id.quick_settings_panel);
mQSDetail = (QSDetail) findViewById(R.id.qs_detail);
- mQSDetail.setQsPanel(mQSPanel);
mHeader = (BaseStatusBarHeader) findViewById(R.id.header);
+ mQSDetail.setQsPanel(mQSPanel, mHeader);
mQSAnimator = new QSAnimator(this, (QuickQSPanel) mHeader.findViewById(R.id.quick_qs_panel),
mQSPanel);
mQSCustomizer = (QSCustomizer) findViewById(R.id.qs_customize);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 50c0cca..0cf7e479 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -35,6 +35,7 @@
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile.DetailAdapter;
+import com.android.systemui.statusbar.phone.BaseStatusBarHeader;
import com.android.systemui.statusbar.phone.QSTileHost;
public class QSDetail extends LinearLayout {
@@ -62,6 +63,7 @@
private boolean mClosingDetail;
private boolean mFullyExpanded;
private View mQsDetailHeaderBack;
+ private BaseStatusBarHeader mHeader;
public QSDetail(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
@@ -107,8 +109,9 @@
mDetailDoneButton.setOnClickListener(doneListener);
}
- public void setQsPanel(QSPanel panel) {
+ public void setQsPanel(QSPanel panel, BaseStatusBarHeader header) {
mQsPanel = panel;
+ mHeader = header;
mQsPanel.setCallback(mQsPanelCallback);
}
@@ -195,6 +198,7 @@
mClosingDetail = true;
mDetailAdapter = null;
listener = mTeardownDetailWhenDone;
+ mHeader.setVisibility(View.VISIBLE);
mQsPanel.setGridContentVisibility(true);
mQsPanelCallback.onScanStateChanged(false);
}
@@ -273,6 +277,7 @@
// Only hide content if still in detail state.
if (mDetailAdapter != null) {
mQsPanel.setGridContentVisibility(false);
+ mHeader.setVisibility(View.INVISIBLE);
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
index 9e40cfd..44b38f1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
@@ -93,6 +93,12 @@
}
}
+ @Override
+ public boolean hasOverlappingRendering() {
+ // Avoid layers for this layout - we don't need them.
+ return false;
+ }
+
/**
* Update the accessibility order for this view.
*
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index e8e17b1..8925d45 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -387,7 +387,7 @@
}
}
}
- if (mTiles.get(mTiles.size() - 1) == null) {
+ if (mTiles.size() - 1 == mTileDividerIndex) {
mTiles.remove(mTiles.size() - 1);
}
}
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 ab21532..f34df75 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -16,13 +16,18 @@
package com.android.systemui.qs.external;
import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
import android.service.quicksettings.IQSTileService;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
+import libcore.util.Objects;
/**
* Manages the priority which lets {@link TileServices} make decisions about which tiles
@@ -68,6 +73,12 @@
mHandler = handler;
mStateManager = tileLifecycleManager;
mStateManager.setQSService(tileServices);
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addDataScheme("package");
+ mServices.getContext().registerReceiverAsUser(mUninstallReceiver,
+ new UserHandle(ActivityManager.getCurrentUser()), filter, null, mHandler);
}
public boolean isActiveTile() {
@@ -106,6 +117,7 @@
}
public void handleDestroy() {
+ mServices.getContext().unregisterReceiver(mUninstallReceiver);
mStateManager.handleDestroy();
}
@@ -198,4 +210,23 @@
mServices.recalculateBindAllowance();
}
};
+
+ private final BroadcastReceiver mUninstallReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (!Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
+ return;
+ }
+ if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+ return;
+ }
+ Uri data = intent.getData();
+ String pkgName = data.getEncodedSchemeSpecificPart();
+ final ComponentName component = mStateManager.getComponent();
+ if (!Objects.equal(pkgName, component.getPackageName())) {
+ return;
+ }
+ mServices.getHost().removeTile(component);
+ }
+ };
}
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 f36d013..2ab6b5f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -72,6 +72,10 @@
return mContext;
}
+ public QSTileHost getHost() {
+ return mHost;
+ }
+
public TileServiceManager getTileWrapper(CustomTile tile) {
ComponentName component = tile.getComponent();
TileServiceManager service = onCreateTileService(component);
@@ -89,6 +93,7 @@
public void freeService(CustomTile tile, TileServiceManager service) {
synchronized (mServices) {
service.setBindAllowed(false);
+ service.handleDestroy();
mServices.remove(tile);
mTiles.remove(tile.getComponent());
final String slot = tile.getComponent().getClassName();
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 e494fd8..77eaa3b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -130,6 +130,8 @@
}
};
state.label = percentage;
+ state.contentDescription = mContext.getString(R.string.accessibility_quick_settings_battery,
+ percentage);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 287bb22..b2d7b48 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
@@ -36,10 +37,13 @@
import android.provider.Settings;
import android.util.EventLog;
import android.util.Log;
+import android.util.MutableBoolean;
import android.view.Display;
import android.view.View;
import android.widget.Toast;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
@@ -78,6 +82,10 @@
private final static String ACTION_HIDE_RECENTS = "com.android.systemui.recents.ACTION_HIDE";
private final static String ACTION_TOGGLE_RECENTS = "com.android.systemui.recents.ACTION_TOGGLE";
+ private static final String COUNTER_WINDOW_SUPPORTED = "window_enter_supported";
+ private static final String COUNTER_WINDOW_UNSUPPORTED = "window_enter_unsupported";
+ private static final String COUNTER_WINDOW_INCOMPATIBLE = "window_enter_incompatible";
+
private static SystemServicesProxy sSystemServicesProxy;
private static RecentsDebugFlags sDebugFlags;
private static RecentsTaskLoader sTaskLoader;
@@ -393,7 +401,8 @@
}
@Override
- public boolean dockTopTask(int dragMode, int stackCreateMode, Rect initialBounds) {
+ public boolean dockTopTask(int dragMode, int stackCreateMode, Rect initialBounds,
+ int metricsDockAction) {
// Ensure the device has been provisioned before allowing the user to interact with
// recents
if (!isUserSetup()) {
@@ -413,7 +422,12 @@
boolean screenPinningActive = ssp.isScreenPinningActive();
boolean isTopTaskHome = topTask != null && SystemServicesProxy.isHomeStack(topTask.stackId);
if (topTask != null && !isTopTaskHome && !screenPinningActive) {
+ logDockAttempt(mContext, topTask.topActivity, topTask.resizeMode);
if (topTask.isDockable) {
+ if (metricsDockAction != -1) {
+ MetricsLogger.action(mContext, metricsDockAction,
+ topTask.topActivity.flattenToShortString());
+ }
if (sSystemServicesProxy.isSystemUser(currentUser)) {
mImpl.dockTopTask(topTask.id, dragMode, stackCreateMode, initialBounds);
} else {
@@ -435,7 +449,7 @@
mDraggingInRecentsCurrentUser = currentUser;
return true;
} else {
- Toast.makeText(mContext, R.string.recents_drag_non_dockable_task_message,
+ Toast.makeText(mContext, R.string.recents_incompatible_app_message,
Toast.LENGTH_SHORT).show();
return false;
}
@@ -444,6 +458,26 @@
}
}
+ public static void logDockAttempt(Context ctx, ComponentName activity, int resizeMode) {
+ if (resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE) {
+ MetricsLogger.action(ctx, MetricsEvent.ACTION_WINDOW_DOCK_UNRESIZABLE,
+ activity.flattenToShortString());
+ }
+ MetricsLogger.count(ctx, getMetricsCounterForResizeMode(resizeMode), 1);
+ }
+
+ private static String getMetricsCounterForResizeMode(int resizeMode) {
+ switch (resizeMode) {
+ case ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE:
+ return COUNTER_WINDOW_UNSUPPORTED;
+ case ActivityInfo.RESIZE_MODE_RESIZEABLE:
+ case ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE:
+ return COUNTER_WINDOW_SUPPORTED;
+ default:
+ return COUNTER_WINDOW_INCOMPATIBLE;
+ }
+ }
+
@Override
public void onDraggingInRecents(float distanceFromTop) {
if (sSystemServicesProxy.isSystemUser(mDraggingInRecentsCurrentUser)) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index b1d9555..4d69280 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -38,6 +38,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
@@ -58,22 +59,25 @@
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
+import com.android.systemui.recents.events.ui.HideIncompatibleAppOverlayEvent;
import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
import com.android.systemui.recents.events.ui.ShowApplicationInfoEvent;
+import com.android.systemui.recents.events.ui.ShowIncompatibleAppOverlayEvent;
import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
import com.android.systemui.recents.events.ui.UserInteractionEvent;
+import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
import com.android.systemui.recents.misc.DozeTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.RecentsPackageMonitor;
import com.android.systemui.recents.model.RecentsTaskLoadPlan;
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.views.AnimationProps;
import com.android.systemui.recents.views.RecentsView;
import com.android.systemui.recents.views.SystemBarScrimViews;
import com.android.systemui.statusbar.BaseStatusBar;
@@ -90,10 +94,11 @@
private final static boolean DEBUG = false;
public final static int EVENT_BUS_PRIORITY = Recents.EVENT_BUS_PRIORITY + 1;
+ public final static int INCOMPATIBLE_APP_ALPHA_DURATION = 150;
private RecentsPackageMonitor mPackageMonitor;
private long mLastTabKeyEventTime;
- private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
+ private int mLastDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
private boolean mFinishedOnStartup;
private boolean mIgnoreAltTabRelease;
private boolean mIsVisible;
@@ -101,6 +106,7 @@
// Top level views
private RecentsView mRecentsView;
private SystemBarScrimViews mScrimViews;
+ private View mIncompatibleAppOverlay;
// Runnables to finish the Recents activity
private Intent mHomeIntent;
@@ -270,7 +276,7 @@
getWindow().getAttributes().privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
- mLastOrientation = getResources().getConfiguration().orientation;
+ mLastDeviceOrientation = Utilities.getAppConfiguration(this).orientation;
mFocusTimerDuration = getResources().getInteger(R.integer.recents_auto_advance_duration);
mIterateTrigger = new DozeTrigger(mFocusTimerDuration, new Runnable() {
@Override
@@ -420,13 +426,12 @@
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
-
// Notify of the config change
- int newOrientation = getResources().getConfiguration().orientation;
+ int newDeviceOrientation = Utilities.getAppConfiguration(this).orientation;
int numStackTasks = mRecentsView.getStack().getStackTaskCount();
EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */,
- (mLastOrientation != newOrientation), numStackTasks > 0));
- mLastOrientation = newOrientation;
+ (mLastDeviceOrientation != newDeviceOrientation), numStackTasks > 0));
+ mLastDeviceOrientation = newDeviceOrientation;
}
@Override
@@ -449,7 +454,7 @@
int numStackTasks = stack.getStackTaskCount();
EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */,
- false /* fromOrientationChange */, numStackTasks > 0));
+ false /* fromDeviceOrientationChange */, numStackTasks > 0));
if (mRecentsView != null) {
mRecentsView.updateStack(stack);
@@ -674,6 +679,30 @@
MetricsLogger.count(this, "overview_app_info", 1);
}
+ public final void onBusEvent(ShowIncompatibleAppOverlayEvent event) {
+ if (mIncompatibleAppOverlay == null) {
+ mIncompatibleAppOverlay = Utilities.findViewStubById(this,
+ R.id.incompatible_app_overlay_stub).inflate();
+ mIncompatibleAppOverlay.setWillNotDraw(false);
+ mIncompatibleAppOverlay.setVisibility(View.VISIBLE);
+ }
+ mIncompatibleAppOverlay.animate()
+ .alpha(1f)
+ .setDuration(INCOMPATIBLE_APP_ALPHA_DURATION)
+ .setInterpolator(Interpolators.ALPHA_IN)
+ .start();
+ }
+
+ public final void onBusEvent(HideIncompatibleAppOverlayEvent event) {
+ if (mIncompatibleAppOverlay != null) {
+ mIncompatibleAppOverlay.animate()
+ .alpha(0f)
+ .setDuration(INCOMPATIBLE_APP_ALPHA_DURATION)
+ .setInterpolator(Interpolators.ALPHA_OUT)
+ .start();
+ }
+ }
+
public final void onBusEvent(DeleteTaskDataEvent event) {
// Remove any stored data from the loader
RecentsTaskLoader loader = Recents.getTaskLoader();
@@ -723,6 +752,13 @@
mIgnoreAltTabRelease = true;
}
+ public final void onBusEvent(final DragEndEvent event) {
+ // Handle the case where we drop onto a dock region
+ if (event.dropTarget instanceof TaskStack.DockState) {
+ mScrimViews.animateScrimToCurrentNavBarState(false /* hasStackTasks */);
+ }
+ }
+
@Override
public boolean onPreDraw() {
mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
@@ -740,6 +776,8 @@
@Override
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
super.dump(prefix, fd, writer, args);
+ EventBus.getDefault().dump(prefix, writer);
+
String id = Integer.toHexString(System.identityHashCode(this));
writer.print(prefix); writer.print(TAG);
@@ -750,6 +788,5 @@
if (mRecentsView != null) {
mRecentsView.dump(prefix, writer);
}
- EventBus.getDefault().dump(prefix, writer);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index fda340d..c230cd8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -175,7 +175,11 @@
ssp.registerTaskStackListener(mTaskStackListener);
// Initialize the static configuration resources
- reloadHeaderBarLayout();
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ mDummyStackView = new TaskStackView(mContext);
+ mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header,
+ null, false);
+ reloadResources();
// When we start, preload the data associated with the previous recent tasks.
// We can use a new plan since the caches will be the same.
@@ -194,7 +198,9 @@
}
public void onConfigurationChanged() {
- reloadHeaderBarLayout();
+ reloadResources();
+ mDummyStackView.reloadOnConfigurationChange();
+ mHeaderBar.onConfigurationChanged();
}
/**
@@ -542,11 +548,10 @@
}
/**
- * Reloads all the layouts for the header bar transition.
+ * Reloads all the resources for the current configuration.
*/
- private void reloadHeaderBarLayout() {
+ private void reloadResources() {
Resources res = mContext.getResources();
- LayoutInflater inflater = LayoutInflater.from(mContext);
mStatusBarHeight = res.getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
@@ -561,9 +566,6 @@
R.dimen.recents_task_view_header_height_tablet_land,
R.dimen.recents_task_view_header_height,
R.dimen.recents_task_view_header_height_tablet_land);
- mDummyStackView = new TaskStackView(mContext);
- mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header,
- null, false);
}
/**
@@ -687,7 +689,7 @@
TaskStackViewScroller stackScroller = stackView.getScroller();
stackView.updateLayoutAlgorithm(true /* boundScroll */);
- stackView.updateToInitialState(true /* scrollToInitialState */);
+ stackView.updateToInitialState();
for (int i = tasks.size() - 1; i >= 0; i--) {
Task task = tasks.get(i);
@@ -740,7 +742,7 @@
// Get the transform for the running task
stackView.updateLayoutAlgorithm(true /* boundScroll */);
- stackView.updateToInitialState(true /* scrollToInitialState */);
+ stackView.updateToInitialState();
stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask,
stackView.getScroller().getStackScroll(), mTmpTransform, null);
return mTmpTransform;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
index e3bc2a7..53b67cf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
@@ -24,13 +24,13 @@
public class ConfigurationChangedEvent extends EventBus.AnimatedEvent {
public final boolean fromMultiWindow;
- public final boolean fromOrientationChange;
+ public final boolean fromDeviceOrientationChange;
public final boolean hasStackTasks;
- public ConfigurationChangedEvent(boolean fromMultiWindow, boolean fromOrientationChange,
+ public ConfigurationChangedEvent(boolean fromMultiWindow, boolean fromDeviceOrientationChange,
boolean hasStackTasks) {
this.fromMultiWindow = fromMultiWindow;
- this.fromOrientationChange = fromOrientationChange;
+ this.fromDeviceOrientationChange = fromDeviceOrientationChange;
this.hasStackTasks = hasStackTasks;
}
}
diff --git a/telephony/java/com/android/internal/telephony/TelephonyEvent.aidl b/packages/SystemUI/src/com/android/systemui/recents/events/ui/HideIncompatibleAppOverlayEvent.java
similarity index 69%
rename from telephony/java/com/android/internal/telephony/TelephonyEvent.aidl
rename to packages/SystemUI/src/com/android/systemui/recents/events/ui/HideIncompatibleAppOverlayEvent.java
index 1e74b31..d6ef636 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyEvent.aidl
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/HideIncompatibleAppOverlayEvent.java
@@ -14,6 +14,13 @@
* limitations under the License.
*/
-package com.android.internal.telephony;
+package com.android.systemui.recents.events.ui;
-parcelable TelephonyEvent;
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when a user stops draggin an incompatible app task.
+ */
+public class HideIncompatibleAppOverlayEvent extends EventBus.Event {
+ // Simple event
+}
diff --git a/telephony/java/com/android/internal/telephony/TelephonyEvent.aidl b/packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowIncompatibleAppOverlayEvent.java
similarity index 68%
copy from telephony/java/com/android/internal/telephony/TelephonyEvent.aidl
copy to packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowIncompatibleAppOverlayEvent.java
index 1e74b31..3a4350e 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyEvent.aidl
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowIncompatibleAppOverlayEvent.java
@@ -14,6 +14,13 @@
* limitations under the License.
*/
-package com.android.internal.telephony;
+package com.android.systemui.recents.events.ui;
-parcelable TelephonyEvent;
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when a user starts dragging an incompatible app task.
+ */
+public class ShowIncompatibleAppOverlayEvent extends EventBus.Event {
+ // Simple event
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
index 69d98af..f6cc12b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
@@ -18,18 +18,24 @@
import android.animation.Animator;
import android.animation.AnimatorSet;
+import android.animation.RectEvaluator;
import android.annotation.FloatRange;
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
+import android.os.Trace;
import android.util.ArraySet;
import android.util.IntProperty;
import android.util.Property;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewParent;
+import android.view.ViewStub;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.views.TaskViewTransform;
@@ -68,7 +74,7 @@
};
public static final RectFEvaluator RECTF_EVALUATOR = new RectFEvaluator();
-
+ public static final RectEvaluator RECT_EVALUATOR = new RectEvaluator(new Rect());
public static final Rect EMPTY_RECT = new Rect();
/**
@@ -220,6 +226,20 @@
}
/**
+ * Returns a view stub for the given view id.
+ */
+ public static ViewStub findViewStubById(View v, int stubId) {
+ return (ViewStub) v.findViewById(stubId);
+ }
+
+ /**
+ * Returns a view stub for the given view id.
+ */
+ public static ViewStub findViewStubById(Activity a, int stubId) {
+ return (ViewStub) a.findViewById(stubId);
+ }
+
+ /**
* Updates {@param transforms} to be the same size as {@param tasks}.
*/
public static void matchTaskListSize(List<Task> tasks, List<TaskViewTransform> transforms) {
@@ -245,6 +265,22 @@
}
/**
+ * Adds a trace event for debugging.
+ */
+ public static void addTraceEvent(String event) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, event);
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+
+ /**
+ * Returns the application configuration, which is independent of the activity's current
+ * configuration in multiwindow.
+ */
+ public static Configuration getAppConfiguration(Context context) {
+ return context.getApplicationContext().getResources().getConfiguration();
+ }
+
+ /**
* Returns a lightweight dump of a rect.
*/
public static String dumpRect(Rect r) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 7aeff1f..af1628b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -206,7 +206,7 @@
Task task = new Task(taskKey, t.affiliatedTaskId, t.affiliatedTaskColor, icon,
thumbnail, title, titleDescription, dismissDescription, appInfoDescription,
activityColor, backgroundColor, isLaunchTarget, isStackTask, isSystemApp,
- t.isDockable, t.bounds, t.taskDescription);
+ t.isDockable, t.bounds, t.taskDescription, t.resizeMode, t.topActivity);
allTasks.add(task);
affiliatedTaskCounts.put(taskKey.id, affiliatedTaskCounts.get(taskKey.id, 0) + 1);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 24eeaf2..68c46a9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -19,6 +19,7 @@
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;
@@ -174,6 +175,15 @@
@ViewDebug.ExportedProperty(category="recents")
public boolean isDockable;
+ /**
+ * Resize mode. See {@link ActivityInfo#resizeMode}.
+ */
+ @ViewDebug.ExportedProperty(category="recents")
+ public int resizeMode;
+
+ @ViewDebug.ExportedProperty(category="recents")
+ public ComponentName topActivity;
+
private ArrayList<TaskCallbacks> mCallbacks = new ArrayList<>();
public Task() {
@@ -184,7 +194,8 @@
Bitmap thumbnail, String title, String titleDescription, String dismissDescription,
String appInfoDescription, int colorPrimary, int colorBackground,
boolean isLaunchTarget, boolean isStackTask, boolean isSystemApp,
- boolean isDockable, Rect bounds, ActivityManager.TaskDescription taskDescription) {
+ boolean isDockable, Rect bounds, ActivityManager.TaskDescription taskDescription,
+ int resizeMode, ComponentName topActivity) {
boolean isInAffiliationGroup = (affiliationTaskId != key.id);
boolean hasAffiliationGroupColor = isInAffiliationGroup && (affiliationColor != 0);
this.key = key;
@@ -206,6 +217,8 @@
this.isStackTask = isStackTask;
this.isSystemApp = isSystemApp;
this.isDockable = isDockable;
+ this.resizeMode = resizeMode;
+ this.topActivity = topActivity;
}
/**
@@ -231,6 +244,8 @@
this.isStackTask = o.isStackTask;
this.isSystemApp = o.isSystemApp;
this.isDockable = o.isDockable;
+ this.resizeMode = o.resizeMode;
+ this.topActivity = o.topActivity;
}
/**
@@ -300,6 +315,15 @@
return key.id != affiliationTaskId;
}
+ /**
+ * Returns the top activity component.
+ */
+ public ComponentName getTopComponent() {
+ return topActivity != null
+ ? topActivity
+ : key.baseIntent.getComponent();
+ }
+
@Override
public boolean equals(Object o) {
// Check that the id matches
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index fbb5987..95e276f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -299,7 +299,7 @@
if (bounds != null && !dockAreaOverlay.getBounds().equals(bounds)) {
if (animateBounds) {
PropertyValuesHolder prop = PropertyValuesHolder.ofObject(
- Utilities.DRAWABLE_RECT, new RectEvaluator(new Rect()),
+ Utilities.DRAWABLE_RECT, Utilities.RECT_EVALUATOR,
dockAreaOverlay.getBounds(), bounds);
animators.add(ObjectAnimator.ofPropertyValuesHolder(dockAreaOverlay, prop));
} else {
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 13e1a14..7378102 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
@@ -55,6 +55,7 @@
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.recents.views.AnimationProps;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.tv.pip.PipManager;
import com.android.systemui.tv.pip.PipRecentsOverlayManager;
@@ -106,7 +107,9 @@
public void onMoveToFullscreen() {
// Recents should be dismissed when PIP moves to fullscreen. If not, Recents will
// be unnecessarily shown in the scenario: PIP->Fullscreen->PIP.
- dismissRecentsToLaunchTargetTaskOrHome();
+ // Do not show Recents close animation because PIP->Fullscreen animation will be shown
+ // instead.
+ dismissRecentsToLaunchTargetTaskOrHome(false);
}
@Override
@@ -117,7 +120,7 @@
new PipRecentsOverlayManager.Callback() {
@Override
public void onClosed() {
- dismissRecentsToLaunchTargetTaskOrHome();
+ dismissRecentsToLaunchTargetTaskOrHome(true);
}
@Override
@@ -210,13 +213,15 @@
}
}
- boolean dismissRecentsToLaunchTargetTaskOrHome() {
+ boolean dismissRecentsToLaunchTargetTaskOrHome(boolean animate) {
SystemServicesProxy ssp = Recents.getSystemServices();
if (ssp.isRecentsTopMost(ssp.getTopMostTask(), null)) {
// If we have a focused Task, launch that Task now
- if (mRecentsView.launchPreviousTask()) return true;
+ if (mRecentsView.launchPreviousTask(animate)) {
+ return true;
+ }
// If none of the other cases apply, then just go Home
- dismissRecentsToHome(true /* animateTaskViews */);
+ dismissRecentsToHome(animate /* animateTaskViews */);
}
return false;
}
@@ -246,7 +251,7 @@
dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
dismissEvent.addPostAnimationCallback(closeSystemWindows);
- if(mTaskStackHorizontalGridView.getChildCount() > 0) {
+ if (mTaskStackHorizontalGridView.getChildCount() > 0 && animateTaskViews) {
mHomeRecentsEnterExitAnimationHolder.startExitAnimation(dismissEvent);
} else {
closeSystemWindows.run();
@@ -343,6 +348,13 @@
} else {
mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
}
+ if(mTaskStackHorizontalGridView.getStack().getTaskCount() > 1 && !mLaunchedFromHome) {
+ // If there are 2 or more tasks, and we are not launching from home
+ // set the selected position to the 2nd task to allow for faster app switching
+ mTaskStackHorizontalGridView.setSelectedPosition(1);
+ } else {
+ mTaskStackHorizontalGridView.setSelectedPosition(0);
+ }
// 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
@@ -366,7 +378,7 @@
public void onEnterAnimationComplete() {
super.onEnterAnimationComplete();
if(mLaunchedFromHome) {
- mHomeRecentsEnterExitAnimationHolder.startEnterAnimation();
+ mHomeRecentsEnterExitAnimationHolder.startEnterAnimation(mPipManager.isPipShown());
}
EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
}
@@ -455,7 +467,7 @@
if (launchState.launchedFromHome) {
dismissRecentsToHome(true /* animateTaskViews */);
} else {
- dismissRecentsToLaunchTargetTaskOrHome();
+ dismissRecentsToLaunchTargetTaskOrHome(true);
}
}
@@ -494,12 +506,10 @@
}
public final void onBusEvent(AllTaskViewsDismissedEvent event) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (ssp.hasDockedTask()) {
+ if (mPipManager.isPipShown()) {
mRecentsView.showEmptyView();
} else {
- // Just go straight home (no animation necessary because there are no more task views)
- dismissRecentsToHome(false /* animateTaskViews */);
+ dismissRecentsToHome(false);
}
}
@@ -555,6 +565,8 @@
// as if it's the part of the Recents UI.
mPipRecentsOverlayManager.requestFocus(
mTaskStackViewAdapter.getItemCount() > 0);
+ } else {
+ mPipRecentsOverlayManager.clearFocus();
}
}
}
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 fd31872..dc0d1f1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
@@ -75,7 +75,8 @@
if (useThumbnailTransition) {
// Try starting with a thumbnail transition
- ActivityOptions opts = getThumbnailTransitionActivityOptionsForTV(topTask);
+ ActivityOptions opts = getThumbnailTransitionActivityOptionsForTV(topTask,
+ stack.getTaskCount());
if (opts != null) {
startRecentsActivity(topTask, opts, false /* fromHome */, true /* fromThumbnail */);
} else {
@@ -118,8 +119,8 @@
* Creates the activity options for an app->recents transition on TV.
*/
private ActivityOptions getThumbnailTransitionActivityOptionsForTV(
- ActivityManager.RunningTaskInfo topTask) {
- Rect rect = TaskCardView.getStartingCardThumbnailRect(mContext);
+ ActivityManager.RunningTaskInfo topTask, int numTasks) {
+ Rect rect = TaskCardView.getStartingCardThumbnailRect(mContext, numTasks);
SystemServicesProxy ssp = Recents.getSystemServices();
ThumbnailData thumbnailData = ssp.getTaskThumbnail(topTask.id);
if (thumbnailData.thumbnail != null) {
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 fbcfa97..66d8576 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,6 +18,7 @@
import android.animation.Animator;
import android.content.res.Resources;
+import android.view.View;
import android.widget.LinearLayout;
import com.android.systemui.Interpolators;
import com.android.systemui.recents.tv.views.TaskCardView;
@@ -26,17 +27,20 @@
public class DismissAnimationsHolder {
private LinearLayout mDismissArea;
- private LinearLayout mTaskCardView;
- private int mCardYDelta;
+ private LinearLayout mInfoField;
+ private View mThumbnailView;
+ private int mDismissEnterYDelta;
+ private int mDismissStartYDelta;
private long mShortDuration;
private long mLongDuration;
public DismissAnimationsHolder(TaskCardView taskCardView) {
- mTaskCardView = (LinearLayout) taskCardView.findViewById(R.id.recents_tv_card);
+ mInfoField = (LinearLayout) taskCardView.findViewById(R.id.card_info_field);
mDismissArea = (LinearLayout) taskCardView.findViewById(R.id.card_dismiss);
-
+ mThumbnailView = taskCardView.findViewById(R.id.card_view_thumbnail);
Resources res = taskCardView.getResources();
- mCardYDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_shift_down);
+ mDismissEnterYDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_shift_down);
+ mDismissStartYDelta = mDismissEnterYDelta * 2;
mShortDuration = res.getInteger(R.integer.dismiss_short_duration);
mLongDuration = res.getInteger(R.integer.dismiss_long_duration);
}
@@ -47,10 +51,16 @@
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.alpha(1.0f);
- mTaskCardView.animate()
+ mInfoField.animate()
.setDuration(mShortDuration)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .translationYBy(mCardYDelta)
+ .translationY(mDismissEnterYDelta)
+ .alpha(0.5f);
+
+ mThumbnailView.animate()
+ .setDuration(mShortDuration)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .translationY(mDismissEnterYDelta)
.alpha(0.5f);
}
@@ -60,10 +70,16 @@
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.alpha(0.0f);
- mTaskCardView.animate()
+ mInfoField.animate()
.setDuration(mShortDuration)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .translationYBy(-mCardYDelta)
+ .translationY(0)
+ .alpha(1.0f);
+
+ mThumbnailView.animate()
+ .setDuration(mShortDuration)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .translationY(0)
.alpha(1.0f);
}
@@ -73,11 +89,25 @@
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.alpha(0.0f);
- mTaskCardView.animate()
+ mInfoField.animate()
.setDuration(mLongDuration)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .translationYBy(mCardYDelta)
+ .translationY(mDismissStartYDelta)
.alpha(0.0f)
.setListener(listener);
+
+ mThumbnailView.animate()
+ .setDuration(mLongDuration)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .translationY(mDismissStartYDelta)
+ .alpha(0.0f);
+ }
+
+ public void reset() {
+ mInfoField.setAlpha(1.0f);
+ mInfoField.setTranslationY(0);
+ mInfoField.animate().setListener(null);
+ mThumbnailView.setAlpha(1.0f);
+ mThumbnailView.setTranslationY(0);
}
}
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
index 278de87..92718a3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/HomeRecentsEnterExitAnimationHolder.java
@@ -28,6 +28,7 @@
private Context mContext;
private TaskStackHorizontalGridView mGridView;
+ private float mDimAlpha;
private long mDelay;
private int mDuration;
private int mTranslationX;
@@ -36,19 +37,19 @@
TaskStackHorizontalGridView gridView) {
mContext = context;
mGridView = gridView;
+ mDimAlpha = mContext.getResources().getFloat(R.dimen.recents_recents_row_dim_alpha);
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() {
+ public void startEnterAnimation(boolean isPipShown) {
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)
+ .alpha(isPipShown ? mDimAlpha : 1.0f)
.translationX(0)
.setDuration(mDuration)
.setStartDelay(mDelay * i)
@@ -76,7 +77,7 @@
public void setEnterFromHomeStartingAnimationValues() {
for(int i = 0; i < mGridView.getChildCount(); i++) {
TaskCardView view = (TaskCardView) mGridView.getChildAt(i);
- view.setTranslationX(-mTranslationX);
+ view.setTranslationX(0);
view.setAlpha(0.0f);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
index 28abc34..160835f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/RecentsRowFocusAnimationHolder.java
@@ -29,8 +29,6 @@
* Recents row's focus animation with PIP controls.
*/
public class RecentsRowFocusAnimationHolder {
- private static final float DIM_ALPHA = 0.5f;
-
private View mView;
private View mTitleView;
@@ -43,6 +41,7 @@
Resources res = view.getResources();
int duration = res.getInteger(R.integer.recents_tv_pip_focus_anim_duration);
+ float dimAlpha = res.getFloat(R.dimen.recents_recents_row_dim_alpha);
mFocusGainAnimatorSet = new AnimatorSet();
mFocusGainAnimatorSet.playTogether(
@@ -53,7 +52,7 @@
mFocusLoseAnimatorSet = new AnimatorSet();
mFocusLoseAnimatorSet.playTogether(
- ObjectAnimator.ofFloat(mView, "alpha", DIM_ALPHA),
+ ObjectAnimator.ofFloat(mView, "alpha", dimAlpha),
ObjectAnimator.ofFloat(mTitleView, "alpha", 0f));
mFocusLoseAnimatorSet.setDuration(duration);
mFocusLoseAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
index 888561c..9edd5af 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
@@ -26,6 +26,7 @@
import android.view.animation.Interpolator;
import com.android.systemui.R;
+import com.android.systemui.recents.tv.views.TaskCardView;
public class ViewFocusAnimator implements View.OnFocusChangeListener {
private final float mUnselectedScale;
@@ -94,10 +95,13 @@
mTargetView.setScaleX(scale);
mTargetView.setScaleY(scale);
- mTargetView.setZ(z);
mTargetView.setPadding((int) spacing, mTargetView.getPaddingTop(),
(int) spacing, mTargetView.getPaddingBottom());
+
+ if (mTargetView instanceof TaskCardView) {
+ ((TaskCardView) mTargetView).getThumbnailView().setZ(z);
+ }
}
public float getFocusProgress() {
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 fb1127e..812bff1 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,7 +16,6 @@
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;
@@ -122,11 +121,13 @@
}
try {
Rect taskRect = taskView.getFocusedThumbnailRect();
- Bitmap thumbnail = Bitmap.createScaledBitmap(task.thumbnail, taskRect.width(),
- taskRect.height(), false);
- WindowManagerGlobal.getWindowManagerService()
- .overridePendingAppTransitionAspectScaledThumb(thumbnail, taskRect.left,
- taskRect.top, taskRect.width(), taskRect.height(), callback, true);
+ if (taskRect != null) {
+ Bitmap thumbnail = Bitmap.createScaledBitmap(task.thumbnail, taskRect.width(),
+ taskRect.height(), false);
+ WindowManagerGlobal.getWindowManagerService()
+ .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 53fdf62..4058c62 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,6 @@
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;
@@ -35,7 +34,6 @@
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;
@@ -114,7 +112,7 @@
if (mTaskStackHorizontalView != null) {
Task task = mTaskStackHorizontalView.getFocusedTask();
if (task != null) {
- launchTaskFomRecents(task);
+ launchTaskFomRecents(task, true);
return true;
}
}
@@ -122,12 +120,12 @@
}
/** Launches the task that recents was launched from if possible */
- public boolean launchPreviousTask() {
+ public boolean launchPreviousTask(boolean animate) {
if (mTaskStackHorizontalView != null) {
TaskStack stack = mTaskStackHorizontalView.getStack();
Task task = stack.getLaunchTarget();
if (task != null) {
- launchTaskFomRecents(task);
+ launchTaskFomRecents(task, animate);
return true;
}
}
@@ -139,18 +137,25 @@
* attempt to scroll to focus the task before launching.
* @param task
*/
- private void launchTaskFomRecents(final Task task) {
- if(task != mTaskStackHorizontalView.getFocusedTask()) {
- if(mScrollListener != null) {
+ private void launchTaskFomRecents(final Task task, boolean animate) {
+ if (!animate) {
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ ssp.startActivityFromRecents(getContext(), task.key, task.title, null);
+ return;
+ }
+ mTaskStackHorizontalView.requestFocus();
+ Task focusedTask = mTaskStackHorizontalView.getFocusedTask();
+ if (focusedTask != null && task != focusedTask) {
+ 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) {
+ if (newState == RecyclerView.SCROLL_STATE_IDLE) {
TaskCardView cardView = mTaskStackHorizontalView.getChildViewForTask(task);
- if(cardView != null) {
+ if (cardView != null) {
mTransitionHelper.launchTaskFromRecents(mStack, task,
mTaskStackHorizontalView, cardView, null, INVALID_STACK_ID);
} else {
@@ -250,8 +255,9 @@
public TaskStackHorizontalGridView setTaskStackViewAdapter(
TaskStackHorizontalViewAdapter taskStackViewAdapter) {
- if(mTaskStackHorizontalView != null) {
+ if (mTaskStackHorizontalView != null) {
mTaskStackHorizontalView.setAdapter(taskStackViewAdapter);
+ taskStackViewAdapter.setTaskStackHorizontalGridView(mTaskStackHorizontalView);
}
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 99d478b..a72a7e6 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
@@ -17,10 +17,15 @@
import android.animation.Animator;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
import android.view.KeyEvent;
@@ -38,7 +43,8 @@
public class TaskCardView extends LinearLayout {
- private ImageView mThumbnailView;
+ private static final String TAG = "TaskCardView";
+ private View mThumbnailView;
private TextView mTitleTextView;
private ImageView mBadgeView;
private Task mTask;
@@ -58,26 +64,28 @@
public TaskCardView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mViewFocusAnimator = new ViewFocusAnimator(this);
mDismissState = false;
+ Configuration config = getResources().getConfiguration();
+ setLayoutDirection(config.getLayoutDirection());
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mThumbnailView = (ImageView) findViewById(R.id.card_view_thumbnail);
+ mThumbnailView = findViewById(R.id.card_view_thumbnail);
mTitleTextView = (TextView) findViewById(R.id.card_title_text);
mBadgeView = (ImageView) findViewById(R.id.card_extra_badge);
mDismissAnimationsHolder = new DismissAnimationsHolder(this);
View title = findViewById(R.id.card_info_field);
mRecentsRowFocusAnimationHolder = new RecentsRowFocusAnimationHolder(this, title);
+ mViewFocusAnimator = new ViewFocusAnimator(this);
}
public void init(Task task) {
mTask = task;
- mThumbnailView.setImageBitmap(task.thumbnail);
mTitleTextView.setText(task.title);
mBadgeView.setImageDrawable(task.icon);
+ setThumbnailView();
}
public Task getTask() {
@@ -95,7 +103,38 @@
return r;
}
- public static Rect getStartingCardThumbnailRect(Context context) {
+ public static Rect getStartingCardThumbnailRect(Context context, int numberOfTasks) {
+ if(numberOfTasks > 1) {
+ return getStartingCardThumbnailRectForStartPosition(context);
+ } else {
+ return getStartingCardThumbnailRectForFocusedPosition(context);
+ }
+ }
+
+ private static Rect getStartingCardThumbnailRectForStartPosition(Context context) {
+ Resources res = context.getResources();
+
+ int width = res.getDimensionPixelOffset(R.dimen.recents_tv_card_width);
+ int totalSpacing = res.getDimensionPixelOffset(R.dimen.recents_tv_gird_card_spacing) * 2
+ + res.getDimensionPixelOffset(R.dimen.recents_tv_gird_focused_card_delta);
+ int height = res.getDimensionPixelOffset(R.dimen.recents_tv_screenshot_height);
+ int topMargin = res.getDimensionPixelOffset(R.dimen.recents_tv_gird_row_top_margin);
+ int headerHeight = res.getDimensionPixelOffset(R.dimen.recents_tv_card_extra_badge_size) +
+ res.getDimensionPixelOffset(R.dimen.recents_tv_icon_padding_bottom);
+
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ Display display = wm.getDefaultDisplay();
+ Point size = new Point();
+ display.getSize(size);
+ int screenWidth = size.x;
+
+ return new Rect(screenWidth / 2 + width / 2 + totalSpacing,
+ topMargin + headerHeight,
+ screenWidth / 2 + width / 2 + totalSpacing + width,
+ topMargin + headerHeight + height);
+ }
+
+ private static Rect getStartingCardThumbnailRectForFocusedPosition(Context context) {
Resources res = context.getResources();
TypedValue out = new TypedValue();
@@ -127,7 +166,6 @@
Point size = new Point();
display.getSize(size);
int screenWidth = size.x;
- int screenHeight = size.y;
return new Rect(screenWidth / 2 - width / 2 - widthDelta / 2,
topMargin - totalHeightDelta / 2 + (int) (headerHeight * scale),
@@ -189,6 +227,7 @@
}
public void startDismissTaskAnimation(Animator.AnimatorListener listener) {
+ mDismissState = false;
mDismissAnimationsHolder.startDismissAnimation(listener);
}
@@ -201,4 +240,70 @@
super.onDetachedFromWindow();
setDismissState(false);
}
+
+ public void reset() {
+ mDismissState = false;
+ mRecentsRowFocusAnimationHolder.reset();
+ mDismissAnimationsHolder.reset();
+ }
+
+ private void setThumbnailView() {
+ ImageView screenshotView = (ImageView) findViewById(R.id.card_view_banner_icon);
+ PackageManager pm = getContext().getPackageManager();
+ if (mTask.thumbnail != null) {
+ setAsScreenShotView(mTask.thumbnail, screenshotView);
+ } else {
+ try {
+ Drawable banner = null;
+ if (mTask.key != null) {
+ banner = pm.getActivityBanner(mTask.key.baseIntent);
+ }
+ if (banner != null) {
+ setAsBannerView(banner, screenshotView);
+ } else {
+ setAsIconView(mTask.icon, screenshotView);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Package not found : " + e);
+ setAsIconView(mTask.icon, screenshotView);
+ }
+ }
+ }
+
+ private void setAsScreenShotView(Bitmap screenshot, ImageView screenshotView) {
+ LayoutParams lp = (LayoutParams) screenshotView.getLayoutParams();
+ lp.width = getResources()
+ .getDimensionPixelSize(R.dimen.recents_tv_card_width);
+ lp.height = getResources()
+ .getDimensionPixelSize(R.dimen.recents_tv_screenshot_height);
+
+ screenshotView.setLayoutParams(lp);
+ screenshotView.setImageBitmap(screenshot);
+ }
+
+ private void setAsBannerView(Drawable banner, ImageView bannerView) {
+ LayoutParams lp = (LayoutParams) bannerView.getLayoutParams();
+ lp.width = getResources()
+ .getDimensionPixelSize(R.dimen.recents_tv_banner_width);
+ lp.height = getResources()
+ .getDimensionPixelSize(R.dimen.recents_tv_banner_height);
+
+ bannerView.setLayoutParams(lp);
+ bannerView.setImageDrawable(banner);
+ }
+
+ private void setAsIconView(Drawable icon, ImageView iconView) {
+ LayoutParams lp = (LayoutParams) iconView.getLayoutParams();
+ lp.width = getResources()
+ .getDimensionPixelSize(R.dimen.recents_tv_fallback_icon_width);
+ lp.height = getResources()
+ .getDimensionPixelSize(R.dimen.recents_tv_fallback_icon_height);
+
+ iconView.setLayoutParams(lp);
+ iconView.setImageDrawable(icon);
+ }
+
+ public View getThumbnailView() {
+ return mThumbnailView;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
index 603721a..9f52abd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
@@ -33,9 +33,6 @@
import com.android.systemui.recents.model.TaskStack.TaskStackCallbacks;
import com.android.systemui.recents.views.AnimationProps;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* Horizontal Grid View Implementation to show the Task Stack for TV.
*/
@@ -179,13 +176,14 @@
@Override
public void onStackTaskAdded(TaskStack stack, Task newTask) {
- getAdapter().notifyItemInserted(stack.getStackTasks().indexOf(newTask));
+ ((TaskStackHorizontalViewAdapter) getAdapter()).addTaskAt(newTask,
+ stack.indexOfStackTask(newTask));
}
@Override
public void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
Task newFrontMostTask, AnimationProps animation, boolean fromDockGesture) {
- getAdapter().notifyItemRemoved(stack.getStackTasks().indexOf(removedTask));
+ ((TaskStackHorizontalViewAdapter) getAdapter()).removeTask(removedTask);
if (mFocusedTask == removedTask) {
resetFocusedTask(removedTask);
}
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 97712ea..eb3b02d 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
@@ -28,6 +28,7 @@
import com.android.systemui.recents.events.activity.LaunchTvTaskEvent;
import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.views.AnimationProps;
import java.util.ArrayList;
import java.util.List;
@@ -40,10 +41,12 @@
//Full class name is 30 characters
private static final String TAG = "TaskStackViewAdapter";
private List<Task> mTaskList;
+ private TaskStackHorizontalGridView mGridView;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private TaskCardView mTaskCardView;
private Task mTask;
+ private boolean mShouldReset;
public ViewHolder(View v) {
super(v);
if(v instanceof TaskCardView) {
@@ -62,11 +65,10 @@
try {
if (mTaskCardView.isInDismissState()) {
mTaskCardView.startDismissTaskAnimation(
- getRemoveAtListener(getAdapterPosition(), mTaskCardView));
+ getRemoveAtListener(getAdapterPosition(), mTaskCardView.getTask()));
} else {
EventBus.getDefault().send(new LaunchTvTaskEvent(mTaskCardView, mTask,
null, INVALID_STACK_ID));
- ((Activity) (v.getContext())).finish();
}
} catch (Exception e) {
Log.e(TAG, v.getContext()
@@ -74,6 +76,29 @@
}
}
+
+ private Animator.AnimatorListener getRemoveAtListener(final int position,
+ final Task task) {
+ return new Animator.AnimatorListener() {
+
+ @Override
+ public void onAnimationStart(Animator animation) { }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ removeAt(position);
+ EventBus.getDefault().send(new DeleteTaskDataEvent(task));
+ mShouldReset = true;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) { }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) { }
+ };
+
+ }
}
public TaskStackHorizontalViewAdapter(List tasks) {
@@ -89,9 +114,9 @@
@Override
public TaskStackHorizontalViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
- View view = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.recents_tv_task_card_view, parent, false);
- ViewHolder viewHolder = new ViewHolder(view);
+ LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+ ViewHolder viewHolder = new ViewHolder(
+ inflater.inflate(R.layout.recents_tv_task_card_view, parent, false));
return viewHolder;
}
@@ -101,39 +126,49 @@
}
@Override
+ public void onViewDetachedFromWindow(ViewHolder holder) {
+ // We only want to reset on view detach if this is the last task being dismissed.
+ // This is so that we do not reset when shifting to apps etc, as it is not needed.
+ if (holder.mShouldReset) {
+ holder.mTaskCardView.reset();
+ holder.mShouldReset = false;
+ }
+ }
+
+ @Override
public int getItemCount() {
return mTaskList.size();
}
- private Animator.AnimatorListener getRemoveAtListener(final int position,
- final TaskCardView taskCardView) {
- return new Animator.AnimatorListener() {
-
- @Override
- public void onAnimationStart(Animator animation) { }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- removeAt(position);
- EventBus.getDefault().send(new DeleteTaskDataEvent(taskCardView.getTask()));
- }
-
- @Override
- public void onAnimationCancel(Animator animation) { }
-
- @Override
- public void onAnimationRepeat(Animator animation) { }
- };
-
+ private void removeAt(int position) {
+ Task removedTask = mTaskList.remove(position);
+ if (mGridView != null) {
+ mGridView.getStack().removeTask(removedTask, AnimationProps.IMMEDIATE,
+ false);
+ }
+ notifyItemRemoved(position);
}
- private void removeAt(int position) {
- mTaskList.remove(position);
- notifyItemRemoved(position);
+ public void removeTask(Task task) {
+ int position = mTaskList.indexOf(task);
+ if (position >= 0) {
+ mTaskList.remove(position);
+ notifyItemRemoved(position);
+ }
}
public int getPositionOfTask(Task task) {
int position = mTaskList.indexOf(task);
return (position >= 0) ? position : 0;
}
+
+
+ public void setTaskStackHorizontalGridView(TaskStackHorizontalGridView gridView) {
+ mGridView = gridView;
+ }
+
+ public void addTaskAt(Task task, int position) {
+ mTaskList.add(position, task);
+ notifyItemInserted(position);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeFrameLayout.java b/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeFrameLayout.java
index 9f2b00a..471df6a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeFrameLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeFrameLayout.java
@@ -88,6 +88,10 @@
*/
protected void layoutContents(Rect bounds, boolean changed) {
super.onLayout(changed, bounds.left, bounds.top, bounds.right, bounds.bottom);
+
+ int width = getMeasuredWidth();
+ int height = getMeasuredHeight();
+ onSizeChanged(width, height, width, height);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 21a43d5..d55c7d8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -519,7 +519,9 @@
@Override
public void onAnimationStarted() {
EventBus.getDefault().send(new DockedFirstAnimationFrameEvent());
- mTaskStackView.getStack().removeTask(event.task, AnimationProps.IMMEDIATE,
+ // Remove the task and don't bother relaying out, as all the tasks will be
+ // relaid out when the stack changes on the multiwindow change event
+ mTaskStackView.getStack().removeTask(event.task, null,
true /* fromDockGesture */);
}
};
@@ -540,7 +542,8 @@
mTransitionHelper.wrapStartedListener(startedListener),
true /* scaleUp */);
- MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_DRAG_DROP);
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_DRAG_DROP,
+ event.task.getTopComponent().flattenToShortString());
} else {
// Animate the overlay alpha back to 0
updateVisibleDockRegions(null, true /* isDefaultDockState */, -1,
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..70c4dbd 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,18 @@
import android.app.ActivityManager;
import android.content.res.Configuration;
import android.graphics.Point;
+import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewDebug;
-import android.widget.Toast;
-import com.android.systemui.R;
+import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
+import com.android.systemui.recents.events.ui.HideIncompatibleAppOverlayEvent;
+import com.android.systemui.recents.events.ui.ShowIncompatibleAppOverlayEvent;
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;
@@ -38,7 +41,6 @@
import java.util.ArrayList;
-
/**
* Represents the dock regions for each orientation.
*/
@@ -81,12 +83,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,10 +160,12 @@
mTaskView.setTranslationY(y);
mVisibleDockStates.clear();
- if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask()) {
+ if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask()
+ && mDividerSnapAlgorithm.isSplitScreenFeasible()) {
+ Recents.logDockAttempt(mRv.getContext(), event.task.getTopComponent(),
+ event.task.resizeMode);
if (!event.task.isDockable) {
- Toast.makeText(mRv.getContext(), R.string.recents_drag_non_dockable_task_message,
- Toast.LENGTH_SHORT).show();
+ EventBus.getDefault().send(new ShowIncompatibleAppOverlayEvent());
} else {
// Add the dock state drop targets (these take priority)
TaskStack.DockState[] dockStates = getDockStatesForCurrentOrientation();
@@ -170,12 +182,19 @@
}
public final void onBusEvent(DragEndEvent event) {
+ if (!mDragTask.isDockable) {
+ EventBus.getDefault().send(new HideIncompatibleAppOverlayEvent());
+ }
mDragRequested = false;
mDragTask = null;
mTaskView = null;
mLastDropTarget = null;
}
+ public final void onBusEvent(ConfigurationChangedEvent event) {
+ updateSnapAlgorithm();
+ }
+
/**
* Handles dragging touch events
*/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
index 07a1d4e..dce2353 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -152,7 +152,7 @@
/**
* Animates the scrim to match the state of the current nav bar.
*/
- private void animateScrimToCurrentNavBarState(boolean hasStackTasks) {
+ public void animateScrimToCurrentNavBarState(boolean hasStackTasks) {
boolean hasNavBarScrim = isNavBarScrimRequired(hasStackTasks);
if (mHasNavBarScrim != hasNavBarScrim) {
AnimationProps animation = hasNavBarScrim
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index fe91f42..76aab59d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -19,6 +19,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.Log;
import android.view.View;
@@ -77,7 +78,7 @@
public static final int ENTER_FROM_HOME_ALPHA_DURATION = 100;
public static final int ENTER_FROM_HOME_TRANSLATION_DURATION = 333;
- public static final int ENTER_WHILE_DOCKING_DURATION = 150;
+ public static final int ENTER_WHILE_DOCKING_DURATION = 250;
private static final PathInterpolator ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR =
new PathInterpolator(0, 0, 0, 1f);
@@ -135,6 +136,8 @@
R.dimen.recents_task_stack_animation_affiliate_enter_offset);
int launchedWhileDockingOffset = res.getDimensionPixelSize(
R.dimen.recents_task_stack_animation_launched_while_docking_offset);
+ boolean isLandscape = mStackView.getContext().getApplicationContext().getResources()
+ .getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
// Prepare each of the task views for their enter animation from front to back
List<TaskView> taskViews = mStackView.getTaskViews();
@@ -169,7 +172,10 @@
mTmpTransform.alpha = 0f;
mStackView.updateTaskViewToTransform(tv, mTmpTransform, AnimationProps.IMMEDIATE);
} else if (launchState.launchedViaDockGesture) {
- mTmpTransform.rect.offset(0, launchedWhileDockingOffset);
+ int offset = isLandscape
+ ? launchedWhileDockingOffset
+ : (int) (offscreenYOffset * 0.9f);
+ mTmpTransform.rect.offset(0, offset);
mTmpTransform.alpha = 0f;
mStackView.updateTaskViewToTransform(tv, mTmpTransform, AnimationProps.IMMEDIATE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index b75a91e..34d6bce 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -23,13 +23,13 @@
import android.graphics.Path;
import android.graphics.Rect;
import android.util.ArraySet;
+import android.util.MutableFloat;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.ViewDebug;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsActivity;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsDebugFlags;
@@ -297,9 +297,6 @@
private FreePathInterpolator mUnfocusedDimCurveInterpolator;
private FreePathInterpolator mFocusedDimCurveInterpolator;
- // Indexed from the front of the stack, the normalized x in the unfocused range for each task
- private float[] mInitialNormX;
-
// The state of the stack focus (0..1), which controls the transition of the stack from the
// focused to non-focused state
@ViewDebug.ExportedProperty(category="recents")
@@ -406,8 +403,10 @@
/**
* Sets the system insets.
*/
- public void setSystemInsets(Rect systemInsets) {
+ public boolean setSystemInsets(Rect systemInsets) {
+ boolean changed = mSystemInsets.equals(systemInsets);
mSystemInsets.set(systemInsets);
+ return changed;
}
/**
@@ -545,13 +544,11 @@
} else {
mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
}
- mInitialNormX = null;
} else if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
// If there is one stack task, ignore the min/max/initial scroll positions
mMinScrollP = 0;
mMaxScrollP = 0;
mInitialScrollP = 0;
- mInitialNormX = null;
} else {
// Set the max scroll to be the point where the front most task is visible with the
// stack bottom offset
@@ -565,42 +562,50 @@
launchState.launchedViaDockGesture;
if (launchState.launchedWithAltTab) {
mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
- mInitialNormX = null;
} else if (scrollToFront) {
mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
- mInitialNormX = null;
} else {
// We are overriding the initial two task positions, so set the initial scroll
// position to match the second task (aka focused task) position
float initialTopNormX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP);
mInitialScrollP = Math.max(mMinScrollP, Math.min(mMaxScrollP, (mNumStackTasks - 2))
- Math.max(0, mUnfocusedRange.getAbsoluteX(initialTopNormX)));
-
- // Set the initial scroll to the predefined state (which differs from the stack)
- mInitialNormX = new float[] {
- getNormalizedXFromUnfocusedY(mSystemInsets.bottom + mInitialBottomOffset,
- FROM_BOTTOM),
- initialTopNormX
- };
}
}
}
- public void updateToInitialState(List<Task> tasks) {
- if (mInitialNormX == null) {
- return;
- }
+ /**
+ * Creates task overrides to ensure the initial stack layout if necessary.
+ */
+ public void setTaskOverridesForInitialState(TaskStack stack) {
+ RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- mUnfocusedRange.offset(0f);
- int taskCount = tasks.size();
- for (int i = taskCount - 1; i >= 0; i--) {
- int indexFromFront = taskCount - i - 1;
- if (indexFromFront >= mInitialNormX.length) {
- break;
+ mTaskIndexOverrideMap.clear();
+
+ boolean scrollToFront = launchState.launchedFromHome ||
+ launchState.launchedViaDockGesture;
+ if (getInitialFocusState() == STATE_UNFOCUSED && mNumStackTasks > 1) {
+ if (!launchState.launchedWithAltTab && !scrollToFront) {
+ // Set the initial scroll to the predefined state (which differs from the stack)
+ float [] initialNormX = new float[] {
+ getNormalizedXFromUnfocusedY(mSystemInsets.bottom + mInitialBottomOffset,
+ FROM_BOTTOM),
+ getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP)
+ };
+
+ mUnfocusedRange.offset(0f);
+ List<Task> tasks = stack.getStackTasks();
+ int taskCount = tasks.size();
+ for (int i = taskCount - 1; i >= 0; i--) {
+ int indexFromFront = taskCount - i - 1;
+ if (indexFromFront >= initialNormX.length) {
+ break;
+ }
+ float newTaskProgress = mInitialScrollP +
+ mUnfocusedRange.getAbsoluteX(initialNormX[indexFromFront]);
+ mTaskIndexOverrideMap.put(tasks.get(i).key.id, newTaskProgress);
+ }
}
- float newTaskProgress = mInitialScrollP +
- mUnfocusedRange.getAbsoluteX(mInitialNormX[indexFromFront]);
- mTaskIndexOverrideMap.put(tasks.get(i).key.id, newTaskProgress);
}
}
@@ -628,22 +633,24 @@
/**
* Updates this stack when a scroll happens.
+ *
*/
- public void updateFocusStateOnScroll(float stackScroll, float deltaScroll) {
- if (deltaScroll == 0f) {
- return;
+ public float updateFocusStateOnScroll(float lastTargetStackScroll, float targetStackScroll,
+ float lastStackScroll) {
+ if (targetStackScroll == lastStackScroll) {
+ return targetStackScroll;
}
+ float deltaScroll = targetStackScroll - lastStackScroll;
+ float deltaTargetScroll = targetStackScroll - lastTargetStackScroll;
+ float newScroll = targetStackScroll;
+ mUnfocusedRange.offset(targetStackScroll);
for (int i = mTaskIndexOverrideMap.size() - 1; i >= 0; i--) {
int taskId = mTaskIndexOverrideMap.keyAt(i);
float x = mTaskIndexMap.get(taskId);
float overrideX = mTaskIndexOverrideMap.get(taskId, 0f);
float newOverrideX = overrideX + deltaScroll;
- mUnfocusedRange.offset(stackScroll);
- boolean outOfBounds = mUnfocusedRange.getNormalizedX(newOverrideX) < 0f ||
- mUnfocusedRange.getNormalizedX(newOverrideX) > 1f;
- if (outOfBounds || (overrideX >= x && x >= newOverrideX) ||
- (overrideX <= x && x <= newOverrideX)) {
+ if (isInvalidOverrideX(x, overrideX, newOverrideX)) {
// Remove the override once we reach the original task index
mTaskIndexOverrideMap.removeAt(i);
} else if ((overrideX >= x && deltaScroll <= 0f) ||
@@ -652,11 +659,23 @@
mTaskIndexOverrideMap.put(taskId, newOverrideX);
} else {
// Scrolling override x away from x, we should still move the scroll towards x
- float deltaX = overrideX - x;
- newOverrideX = Math.signum(deltaX) * (Math.abs(deltaX) - Math.abs(deltaScroll));
- mTaskIndexOverrideMap.put(taskId, x + newOverrideX);
+ newScroll = lastStackScroll;
+ newOverrideX = overrideX - deltaTargetScroll;
+ if (isInvalidOverrideX(x, overrideX, newOverrideX)) {
+ mTaskIndexOverrideMap.removeAt(i);
+ } else{
+ mTaskIndexOverrideMap.put(taskId, newOverrideX);
+ }
}
}
+ return newScroll;
+ }
+
+ private boolean isInvalidOverrideX(float x, float overrideX, float newOverrideX) {
+ boolean outOfBounds = mUnfocusedRange.getNormalizedX(newOverrideX) < 0f ||
+ mUnfocusedRange.getNormalizedX(newOverrideX) > 1f;
+ return outOfBounds || (overrideX >= x && x >= newOverrideX) ||
+ (overrideX <= x && x <= newOverrideX);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 13c8403..a75d1e1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -28,11 +28,9 @@
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
-import android.os.Parcelable;
import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -105,12 +103,6 @@
private static final String TAG = "TaskStackView";
- private final static String KEY_SAVED_STATE_SUPER = "saved_instance_state_super";
- private final static String KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE =
- "saved_instance_state_layout_focused_state";
- private final static String KEY_SAVED_STATE_LAYOUT_STACK_SCROLL =
- "saved_instance_state_layout_stack_scroll";
-
// The thresholds at which to show/hide the stack action button.
private static final float SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD = 0.3f;
private static final float HIDE_STACK_ACTION_BUTTON_SCROLL_THRESHOLD = 0.3f;
@@ -350,11 +342,9 @@
/**
* Updates this TaskStackView to the initial state.
*/
- public void updateToInitialState(boolean scrollToInitialState) {
- if (scrollToInitialState) {
- mStackScroller.setStackScrollToInitialState();
- }
- mLayoutAlgorithm.updateToInitialState(mStack.getStackTasks());
+ public void updateToInitialState() {
+ mStackScroller.setStackScrollToInitialState();
+ mLayoutAlgorithm.setTaskOverridesForInitialState(mStack);
}
/** Updates the list of task views */
@@ -638,18 +628,11 @@
/**
* @see #relayoutTaskViews(AnimationProps, ArraySet<Task.TaskKey>, boolean)
*/
- void relayoutTaskViews(AnimationProps animation) {
+ public void relayoutTaskViews(AnimationProps animation) {
relayoutTaskViews(animation, mIgnoreTasks, false /* ignoreTaskOverrides */);
}
/**
- * @see #relayoutTaskViews(AnimationProps, ArraySet<Task.TaskKey>, boolean)
- */
- void relayoutTaskViews(AnimationProps animation, ArraySet<Task.TaskKey> ignoreTasksSet) {
- relayoutTaskViews(animation, ignoreTasksSet, false /* ignoreTaskOverrides */);
- }
-
- /**
* Relayout the the visible {@link TaskView}s to their current transforms as specified by the
* {@link TaskStackLayoutAlgorithm} with the given {@param animation}. This call cancels any
* animations that are current running on those task views, and will ensure that the children
@@ -657,7 +640,7 @@
*
* @param ignoreTasksSet the set of tasks to ignore in the relayout
*/
- void relayoutTaskViews(AnimationProps animation, ArraySet<Task.TaskKey> ignoreTasksSet,
+ private void relayoutTaskViews(AnimationProps animation, ArraySet<Task.TaskKey> ignoreTasksSet,
boolean ignoreTaskOverrides) {
// If we had a deferred animation, cancel that
mDeferredTaskViewLayoutAnimation = null;
@@ -841,7 +824,7 @@
*
* @param ignoreTasksSet the set of tasks to ignore in the relayout
*/
- public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax,
+ private void updateLayoutAlgorithm(boolean boundScrollToNewMinMax,
ArraySet<Task.TaskKey> ignoreTasksSet) {
// Compute the min and max scroll values
mLayoutAlgorithm.update(mStack, ignoreTasksSet);
@@ -1098,24 +1081,6 @@
}
@Override
- protected Parcelable onSaveInstanceState() {
- Bundle savedState = new Bundle();
- savedState.putParcelable(KEY_SAVED_STATE_SUPER, super.onSaveInstanceState());
- savedState.putInt(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE, mLayoutAlgorithm.getFocusState());
- savedState.putFloat(KEY_SAVED_STATE_LAYOUT_STACK_SCROLL, mStackScroller.getStackScroll());
- return super.onSaveInstanceState();
- }
-
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- Bundle savedState = (Bundle) state;
- super.onRestoreInstanceState(savedState.getParcelable(KEY_SAVED_STATE_SUPER));
-
- mLayoutAlgorithm.setFocusState(savedState.getInt(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE));
- mStackScroller.setStackScroll(savedState.getFloat(KEY_SAVED_STATE_LAYOUT_STACK_SCROLL));
- }
-
- @Override
public CharSequence getAccessibilityClassName() {
return TaskStackView.class.getName();
}
@@ -1181,9 +1146,10 @@
* Updates the system insets.
*/
public void setSystemInsets(Rect systemInsets) {
- if (!systemInsets.equals(mLayoutAlgorithm.mSystemInsets)) {
- mStableLayoutAlgorithm.setSystemInsets(systemInsets);
- mLayoutAlgorithm.setSystemInsets(systemInsets);
+ boolean changed = false;
+ changed |= mStableLayoutAlgorithm.setSystemInsets(systemInsets);
+ changed |= mLayoutAlgorithm.setSystemInsets(systemInsets);
+ if (changed) {
requestLayout();
}
}
@@ -1215,13 +1181,17 @@
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
mLayoutAlgorithm.initialize(mWindowRect, mStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
- updateLayoutAlgorithm(false /* boundScroll */, mIgnoreTasks);
+ updateLayoutAlgorithm(false /* boundScroll */);
// If this is the first layout, then scroll to the front of the stack, then update the
// TaskViews with the stack so that we can lay them out
if (mAwaitingFirstLayout || mInitialState != INITIAL_STATE_UPDATE_NONE) {
- updateToInitialState(mInitialState != INITIAL_STATE_UPDATE_LAYOUT_ONLY);
- mInitialState = INITIAL_STATE_UPDATE_NONE;
+ if (mInitialState != INITIAL_STATE_UPDATE_LAYOUT_ONLY) {
+ updateToInitialState();
+ }
+ if (!mAwaitingFirstLayout) {
+ mInitialState = INITIAL_STATE_UPDATE_NONE;
+ }
}
// Rebind all the views, including the ignore ones
@@ -1245,16 +1215,16 @@
* Measures a TaskView.
*/
private void measureTaskView(TaskView tv) {
+ Rect padding = new Rect();
if (tv.getBackground() != null) {
- tv.getBackground().getPadding(mTmpRect);
- } else {
- mTmpRect.setEmpty();
+ tv.getBackground().getPadding(padding);
}
- Rect taskRect = mStableLayoutAlgorithm.mTaskRect;
+ mTmpRect.set(mStableLayoutAlgorithm.mTaskRect);
+ mTmpRect.union(mLayoutAlgorithm.mTaskRect);
tv.measure(
- MeasureSpec.makeMeasureSpec(taskRect.width() + mTmpRect.left + mTmpRect.right,
+ MeasureSpec.makeMeasureSpec(mTmpRect.width() + padding.left + padding.right,
MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(taskRect.height() + mTmpRect.top + mTmpRect.bottom,
+ MeasureSpec.makeMeasureSpec(mTmpRect.height() + padding.top + padding.bottom,
MeasureSpec.EXACTLY));
}
@@ -1276,11 +1246,12 @@
}
// Relayout all of the task views including the ignored ones
- relayoutTaskViews(AnimationProps.IMMEDIATE, mIgnoreTasks);
+ relayoutTaskViews(AnimationProps.IMMEDIATE);
clipTaskViews();
if (mAwaitingFirstLayout || !mEnterAnimationComplete) {
mAwaitingFirstLayout = false;
+ mInitialState = INITIAL_STATE_UPDATE_NONE;
onFirstLayout();
}
}
@@ -1290,15 +1261,15 @@
*/
private void layoutTaskView(boolean changed, TaskView tv) {
if (changed) {
+ Rect padding = new Rect();
if (tv.getBackground() != null) {
- tv.getBackground().getPadding(mTmpRect);
- } else {
- mTmpRect.setEmpty();
+ tv.getBackground().getPadding(padding);
}
- Rect taskRect = mStableLayoutAlgorithm.mTaskRect;
+ mTmpRect.set(mStableLayoutAlgorithm.mTaskRect);
+ mTmpRect.union(mLayoutAlgorithm.mTaskRect);
tv.cancelTransformAnimation();
- tv.layout(taskRect.left - mTmpRect.left, taskRect.top - mTmpRect.top,
- taskRect.right + mTmpRect.right, taskRect.bottom + mTmpRect.bottom);
+ tv.layout(mTmpRect.left - padding.left, mTmpRect.top - padding.top,
+ mTmpRect.right + padding.right, mTmpRect.bottom + padding.bottom);
} else {
// If the layout has not changed, then just lay it out again in-place
tv.layout(tv.getLeft(), tv.getTop(), tv.getRight(), tv.getBottom());
@@ -1618,7 +1589,6 @@
if (animation != null) {
relayoutTaskViewsOnNextFrame(animation);
}
- mLayoutAlgorithm.updateFocusStateOnScroll(curScroll, curScroll - prevScroll);
if (mEnterAnimationComplete) {
if (prevScroll > SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
@@ -1837,9 +1807,17 @@
// Calculate the new task stack bounds that matches the window size that Recents will
// have after the drop
final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget;
+ Rect systemInsets = new Rect(mStableLayoutAlgorithm.mSystemInsets);
+ // When docked, the nav bar insets are consumed and the activity is measured without
+ // insets. However, the window bounds include the insets, so we need to subtract them
+ // here to make them identical.
+ int height = getMeasuredHeight();
+ height -= systemInsets.bottom;
+ systemInsets.bottom = 0;
mStackBounds.set(dockState.getDockedTaskStackBounds(getMeasuredWidth(),
- getMeasuredHeight(), mDividerSize, mLayoutAlgorithm.mSystemInsets,
+ height, mDividerSize, systemInsets,
mLayoutAlgorithm, getResources(), mWindowRect));
+ mLayoutAlgorithm.setSystemInsets(systemInsets);
mLayoutAlgorithm.initialize(mWindowRect, mStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
updateLayoutAlgorithm(true /* boundScroll */);
@@ -1850,6 +1828,7 @@
mWindowRect.set(mStableWindowRect);
mStackBounds.set(mStableStackBounds);
removeIgnoreTask(event.task);
+ mLayoutAlgorithm.setSystemInsets(mStableLayoutAlgorithm.mSystemInsets);
mLayoutAlgorithm.initialize(mWindowRect, mStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
updateLayoutAlgorithm(true /* boundScroll */);
@@ -1971,25 +1950,31 @@
public final void onBusEvent(MultiWindowStateChangedEvent event) {
if (!event.inMultiWindow) {
- // Scroll the stack to the front to see the undocked task
- mStackScroller.animateScroll(mLayoutAlgorithm.mMaxScrollP, new Runnable() {
+ // Defer until the next frame to ensure that we have received all the system insets, and
+ // initial layout updates
+ post(new Runnable() {
@Override
public void run() {
- List<TaskView> taskViews = getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- TaskView tv = taskViews.get(i);
- tv.getHeaderView().rebindToTask(tv.getTask(), tv.mTouchExplorationEnabled,
- tv.mIsDisabledInSafeMode);
- }
+ // Scroll the stack to the front to see the undocked task
+ mStackScroller.animateScroll(mLayoutAlgorithm.mMaxScrollP, new Runnable() {
+ @Override
+ public void run() {
+ List<TaskView> taskViews = getTaskViews();
+ int taskViewCount = taskViews.size();
+ for (int i = 0; i < taskViewCount; i++) {
+ TaskView tv = taskViews.get(i);
+ tv.getHeaderView().rebindToTask(tv.getTask(),
+ tv.mTouchExplorationEnabled, tv.mIsDisabledInSafeMode);
+ }
+ }
+ });
}
});
}
}
public final void onBusEvent(ConfigurationChangedEvent event) {
- mStableLayoutAlgorithm.reloadOnConfigurationChange(getContext());
- mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
+ reloadOnConfigurationChange();
// Notify the task views of the configuration change so they can reload their resources
if (!event.fromMultiWindow) {
@@ -2004,11 +1989,17 @@
// Trigger a new layout and update to the initial state if necessary
if (event.fromMultiWindow) {
- mInitialState = INITIAL_STATE_UPDATE_ALL;
- } else if (event.fromOrientationChange) {
mInitialState = INITIAL_STATE_UPDATE_LAYOUT_ONLY;
+ requestLayout();
+ } else if (event.fromDeviceOrientationChange) {
+ mInitialState = INITIAL_STATE_UPDATE_ALL;
+ requestLayout();
}
- requestLayout();
+ }
+
+ public void reloadOnConfigurationChange() {
+ mStableLayoutAlgorithm.reloadOnConfigurationChange(getContext());
+ mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
}
/**
@@ -2097,7 +2088,7 @@
if (mFocusedTask != null) {
writer.print(innerPrefix);
writer.print("Focused task: ");
- mFocusedTask.dump(innerPrefix, writer);
+ mFocusedTask.dump("", writer);
}
mLayoutAlgorithm.dump(innerPrefix, writer);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index 19b3c94..1fa73c6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.util.FloatProperty;
import android.util.Log;
+import android.util.MutableFloat;
import android.util.Property;
import android.view.ViewDebug;
import android.widget.OverScroller;
@@ -66,6 +67,8 @@
@ViewDebug.ExportedProperty(category="recents")
float mStackScrollP;
+ @ViewDebug.ExportedProperty(category="recents")
+ float mLastDeltaP = 0f;
float mFlingDownScrollP;
int mFlingDownY;
@@ -84,6 +87,11 @@
/** Resets the task scroller. */
void reset() {
mStackScrollP = 0f;
+ mLastDeltaP = 0f;
+ }
+
+ void resetDeltaScroll() {
+ mLastDeltaP = 0f;
}
/** Gets the current stack scroll */
@@ -99,14 +107,27 @@
}
/**
+ * Sets the current stack scroll immediately, and returns the difference between the target
+ * scroll and the actual scroll after accounting for the effect on the focus state.
+ */
+ public float setDeltaStackScroll(float downP, float deltaP) {
+ float targetScroll = downP + deltaP;
+ float newScroll = mLayoutAlgorithm.updateFocusStateOnScroll(downP + mLastDeltaP, targetScroll,
+ mStackScrollP);
+ setStackScroll(newScroll, AnimationProps.IMMEDIATE);
+ mLastDeltaP = deltaP;
+ return newScroll - targetScroll;
+ }
+
+ /**
* Sets the current stack scroll, but indicates to the callback the preferred animation to
* update to this new scroll.
*/
- public void setStackScroll(float s, AnimationProps animation) {
- float prevStackScroll = mStackScrollP;
- mStackScrollP = s;
+ public void setStackScroll(float newScroll, AnimationProps animation) {
+ float prevScroll = mStackScrollP;
+ mStackScrollP = newScroll;
if (mCb != null) {
- mCb.onStackScrollChanged(prevStackScroll, mStackScrollP, animation);
+ mCb.onStackScrollChanged(prevScroll, mStackScrollP, animation);
}
}
@@ -115,9 +136,9 @@
* @return whether the stack progress changed.
*/
public boolean setStackScrollToInitialState() {
- float prevStackScrollP = mStackScrollP;
+ float prevScroll = mStackScrollP;
setStackScroll(mLayoutAlgorithm.mInitialScrollP);
- return Float.compare(prevStackScrollP, mStackScrollP) != 0;
+ return Float.compare(prevScroll, mStackScrollP) != 0;
}
/**
@@ -227,10 +248,9 @@
boolean computeScroll() {
if (mScroller.computeScrollOffset()) {
float deltaP = mLayoutAlgorithm.getDeltaPForY(mFlingDownY, mScroller.getCurrY());
- float scroll = mFlingDownScrollP + deltaP;
- setStackScroll(scroll);
+ mFlingDownScrollP += setDeltaStackScroll(mFlingDownScrollP, deltaP);
if (DEBUG) {
- Log.d(TAG, "computeScroll: " + scroll);
+ Log.d(TAG, "computeScroll: " + (mFlingDownScrollP + deltaP));
}
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index ee0de1a..3cdb1fb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -200,6 +200,7 @@
// Stop the current scroll if it is still flinging
mScroller.stopScroller();
mScroller.stopBoundScrollAnimation();
+ mScroller.resetDeltaScroll();
Utilities.cancelAnimationWithoutCallbacks(mScrollFlingAnimator);
// Finish any existing task animations from the delete
@@ -223,6 +224,7 @@
mDownY = (int) ev.getY(index);
mLastY = mDownY;
mDownScrollP = mScroller.getStackScroll();
+ mScroller.resetDeltaScroll();
mVelocityTracker.addMovement(ev);
break;
}
@@ -256,20 +258,21 @@
// If we just move linearly on the screen, then that would map to 1/arclength
// of the curve, so just move the scroll proportional to that
float deltaP = layoutAlgorithm.getDeltaPForY(mDownY, y);
- float curScrollP = mDownScrollP + deltaP;
// Modulate the overscroll to prevent users from pulling the stack too far
float minScrollP = layoutAlgorithm.mMinScrollP;
float maxScrollP = layoutAlgorithm.mMaxScrollP;
+ float curScrollP = mDownScrollP + deltaP;
if (curScrollP < minScrollP || curScrollP > maxScrollP) {
float clampedScrollP = Utilities.clamp(curScrollP, minScrollP, maxScrollP);
float overscrollP = (curScrollP - clampedScrollP);
float overscrollX = Math.abs(overscrollP) / MAX_OVERSCROLL;
- curScrollP = clampedScrollP + (Math.signum(overscrollP) *
- (OVERSCROLL_INTERP.getInterpolation(overscrollX) * MAX_OVERSCROLL));
+ float interpX = OVERSCROLL_INTERP.getInterpolation(overscrollX);
+ curScrollP = clampedScrollP + Math.signum(overscrollP) *
+ (interpX * MAX_OVERSCROLL);
}
-
- mScroller.setStackScroll(curScrollP);
+ mDownScrollP += mScroller.setDeltaStackScroll(mDownScrollP,
+ curScrollP - mDownScrollP);
mStackViewScrolledEvent.updateY(y - mLastY);
EventBus.getDefault().send(mStackViewScrolledEvent);
}
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 6e585ae..37f5a9f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -39,6 +39,7 @@
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewOutlineProvider;
+import android.widget.TextView;
import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
@@ -151,12 +152,12 @@
private final TaskViewTransform mTargetAnimationTransform = new TaskViewTransform();
private ArrayList<Animator> mTmpAnimators = new ArrayList<>();
- View mContent;
@ViewDebug.ExportedProperty(deepExport=true, prefix="thumbnail_")
TaskViewThumbnail mThumbnailView;
@ViewDebug.ExportedProperty(deepExport=true, prefix="header_")
TaskViewHeader mHeaderView;
View mActionButtonView;
+ View mIncompatibleAppToastView;
TaskViewCallbacks mCb;
@ViewDebug.ExportedProperty(category="recents")
@@ -224,9 +225,9 @@
@Override
protected void onFinishInflate() {
// Bind the views
- mContent = findViewById(R.id.task_view_content);
mHeaderView = (TaskViewHeader) findViewById(R.id.task_view_bar);
mThumbnailView = (TaskViewThumbnail) findViewById(R.id.task_view_thumbnail);
+ mThumbnailView.updateClipToTaskBar(mHeaderView);
mActionButtonView = findViewById(R.id.lock_to_app_fab);
mActionButtonView.setOutlineProvider(new ViewOutlineProvider() {
@Override
@@ -253,6 +254,9 @@
if (w > 0 && h > 0) {
mHeaderView.onTaskViewSizeChanged(w, h);
mThumbnailView.onTaskViewSizeChanged(w, h);
+
+ mActionButtonView.setTranslationX(w - getMeasuredWidth());
+ mActionButtonView.setTranslationY(h - getMeasuredHeight());
}
}
@@ -274,13 +278,11 @@
protected void measureContents(int width, int height) {
int widthWithoutPadding = width - mPaddingLeft - mPaddingRight;
int heightWithoutPadding = height - mPaddingTop - mPaddingBottom;
+ int widthSpec = MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY);
+ int heightSpec = MeasureSpec.makeMeasureSpec(heightWithoutPadding, MeasureSpec.EXACTLY);
// Measure the content
- mContent.measure(MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(heightWithoutPadding, MeasureSpec.EXACTLY));
-
- // Optimization: Prevent overdraw of the thumbnail under the header view
- mThumbnailView.updateClipToTaskBar(mHeaderView);
+ measureChildren(widthSpec, heightSpec);
setMeasuredDimension(width, height);
}
@@ -344,7 +346,12 @@
mActionButtonView.setScaleX(1f);
mActionButtonView.setScaleY(1f);
mActionButtonView.setAlpha(0f);
+ mActionButtonView.setTranslationX(0f);
+ mActionButtonView.setTranslationY(0f);
mActionButtonView.setTranslationZ(mActionButtonTranslationZ);
+ if (mIncompatibleAppToastView != null) {
+ mIncompatibleAppToastView.setVisibility(View.INVISIBLE);
+ }
}
/**
@@ -536,6 +543,10 @@
// These values will be animated in when onStartLaunchTargetEnterAnimation() is called
setDimAlphaWithoutHeader(0);
mActionButtonView.setAlpha(0f);
+ if (mIncompatibleAppToastView != null &&
+ mIncompatibleAppToastView.getVisibility() == View.VISIBLE) {
+ mIncompatibleAppToastView.setAlpha(0f);
+ }
}
@Override
@@ -554,6 +565,15 @@
if (screenPinningEnabled) {
showActionButton(true /* fadeIn */, duration /* fadeInDuration */);
}
+
+ if (mIncompatibleAppToastView != null &&
+ mIncompatibleAppToastView.getVisibility() == View.VISIBLE) {
+ mIncompatibleAppToastView.animate()
+ .alpha(1f)
+ .setDuration(duration)
+ .setInterpolator(Interpolators.ALPHA_IN)
+ .start();
+ }
}
@Override
@@ -587,6 +607,18 @@
mTask = t;
mTask.addCallback(this);
mIsDisabledInSafeMode = !mTask.isSystemApp && ssp.isInSafeMode();
+
+ if (!t.isDockable && ssp.hasDockedTask()) {
+ if (mIncompatibleAppToastView == null) {
+ mIncompatibleAppToastView = Utilities.findViewStubById(this,
+ R.id.incompatible_app_toast_stub).inflate();
+ TextView msg = (TextView) findViewById(com.android.internal.R.id.message);
+ msg.setText(R.string.recents_incompatible_app_message);
+ }
+ mIncompatibleAppToastView.setVisibility(View.VISIBLE);
+ } else if (mIncompatibleAppToastView != null) {
+ mIncompatibleAppToastView.setVisibility(View.INVISIBLE);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 570ff8a..fb0fc30 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -39,7 +39,6 @@
import android.view.ViewAnimationUtils;
import android.view.ViewDebug;
import android.view.ViewGroup;
-import android.view.ViewStub;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
@@ -141,15 +140,12 @@
// Header views
ImageView mIconView;
TextView mTitleView;
- TextView mSubTitleView;
ImageView mMoveTaskButton;
ImageView mDismissButton;
- ViewStub mAppOverlayViewStub;
FrameLayout mAppOverlayView;
ImageView mAppIconView;
ImageView mAppInfoView;
TextView mAppTitleView;
- ViewStub mFocusTimerIndicatorStub;
ProgressBar mFocusTimerIndicator;
// Header drawables
@@ -242,13 +238,10 @@
mIconView.setClickable(false);
mIconView.setOnLongClickListener(this);
mTitleView = (TextView) findViewById(R.id.title);
- mSubTitleView = (TextView) findViewById(R.id.sub_title);
mDismissButton = (ImageView) findViewById(R.id.dismiss_task);
if (ssp.hasFreeformWorkspaceSupport()) {
mMoveTaskButton = (ImageView) findViewById(R.id.move_task);
}
- mFocusTimerIndicatorStub = (ViewStub) findViewById(R.id.focus_timer_indicator_stub);
- mAppOverlayViewStub = (ViewStub) findViewById(R.id.app_overlay_stub);
onConfigurationChanged();
}
@@ -287,28 +280,31 @@
/**
* Update the header view when the configuration changes.
*/
- void onConfigurationChanged() {
+ public void onConfigurationChanged() {
// Update the dimensions of everything in the header. We do this because we need to use
// resources for the display, and not the current configuration.
Resources res = getResources();
- mHeaderBarHeight = TaskStackLayoutAlgorithm.getDimensionForDevice(res,
+ int headerBarHeight = TaskStackLayoutAlgorithm.getDimensionForDevice(res,
R.dimen.recents_task_view_header_height,
R.dimen.recents_task_view_header_height,
R.dimen.recents_task_view_header_height,
R.dimen.recents_task_view_header_height_tablet_land,
R.dimen.recents_task_view_header_height,
R.dimen.recents_task_view_header_height_tablet_land);
- mHeaderButtonPadding = TaskStackLayoutAlgorithm.getDimensionForDevice(res,
+ int headerButtonPadding = TaskStackLayoutAlgorithm.getDimensionForDevice(res,
R.dimen.recents_task_view_header_button_padding,
R.dimen.recents_task_view_header_button_padding,
R.dimen.recents_task_view_header_button_padding,
R.dimen.recents_task_view_header_button_padding_tablet_land,
R.dimen.recents_task_view_header_button_padding,
R.dimen.recents_task_view_header_button_padding_tablet_land);
- updateLayoutParams(mIconView, findViewById(R.id.title_container), mMoveTaskButton,
- mDismissButton);
- if (mAppOverlayView != null) {
- updateLayoutParams(mAppIconView, mAppTitleView, null, mAppInfoView);
+ if (headerBarHeight != mHeaderBarHeight || headerButtonPadding != mHeaderButtonPadding) {
+ mHeaderBarHeight = headerBarHeight;
+ mHeaderButtonPadding = headerButtonPadding;
+ updateLayoutParams(mIconView, mTitleView, mMoveTaskButton, mDismissButton);
+ if (mAppOverlayView != null) {
+ updateLayoutParams(mAppIconView, mAppTitleView, null, mAppInfoView);
+ }
}
}
@@ -354,6 +350,8 @@
}
mDismissButton.setVisibility(showDismissIcon ? View.VISIBLE : View.INVISIBLE);
mDismissButton.setTranslationX(rightInset);
+
+ setLeftTopRightBottom(0, 0, width, getMeasuredHeight());
}
@Override
@@ -442,7 +440,6 @@
/** Binds the bar view to the task */
public void rebindToTask(Task t, boolean touchExplorationEnabled, boolean disabledInSafeMode) {
- SystemServicesProxy ssp = Recents.getSystemServices();
mTask = t;
// If an activity icon is defined, then we use that as the primary icon to show in the bar,
@@ -462,13 +459,6 @@
mTitleView.setContentDescription(t.titleDescription);
mTitleView.setTextColor(t.useLightOnPrimaryColor ?
mTaskBarViewLightTextColor : mTaskBarViewDarkTextColor);
- if (!t.isDockable && ssp.hasDockedTask()) {
- mSubTitleView.setVisibility(View.VISIBLE);
- mSubTitleView.setTextColor(t.useLightOnPrimaryColor ?
- mTaskBarViewLightTextColor : mTaskBarViewDarkTextColor);
- } else {
- mSubTitleView.setVisibility(View.GONE);
- }
mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ?
mLightDismissDrawable : mDarkDismissDrawable);
mDismissButton.setContentDescription(t.dismissDescription);
@@ -491,7 +481,8 @@
if (Recents.getDebugFlags().isFastToggleRecentsEnabled()) {
if (mFocusTimerIndicator == null) {
- mFocusTimerIndicator = (ProgressBar) mFocusTimerIndicatorStub.inflate();
+ mFocusTimerIndicator = (ProgressBar) Utilities.findViewStubById(this,
+ R.id.focus_timer_indicator_stub).inflate();
}
mFocusTimerIndicator.getProgressDrawable()
.setColorFilter(
@@ -637,7 +628,8 @@
// Inflate the overlay if necessary
if (mAppOverlayView == null) {
- mAppOverlayView = (FrameLayout) mAppOverlayViewStub.inflate();
+ mAppOverlayView = (FrameLayout) Utilities.findViewStubById(this,
+ R.id.app_overlay_stub).inflate();
mAppOverlayView.setBackground(mOverlayBackground);
mAppIconView = (ImageView) mAppOverlayView.findViewById(R.id.app_icon);
mAppIconView.setOnClickListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index e5ac0d3..4de7713 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -123,6 +123,7 @@
}
mTaskViewRect.set(0, 0, width, height);
+ setLeftTopRightBottom(0, 0, width, height);
updateThumbnailScale();
}
@@ -143,43 +144,32 @@
int viewWidth = mTaskViewRect.width();
int viewHeight = mTaskViewRect.height();
- if (mBitmapShader != null) {
+ int thumbnailWidth = Math.min(viewWidth,
+ (int) (mThumbnailRect.width() * mThumbnailScale));
+ int thumbnailHeight = Math.min(viewHeight,
+ (int) (mThumbnailRect.height() * mThumbnailScale));
+ if (mBitmapShader != null && thumbnailWidth > 0 && thumbnailHeight > 0) {
+ int topOffset = mTaskBar != null
+ ? mTaskBar.getHeight() - mCornerRadius
+ : 0;
- // We are drawing the thumbnail in the same orientation, so just fit the width
- int thumbnailWidth = (int) (mThumbnailRect.width() * mThumbnailScale);
- int thumbnailHeight = (int) (mThumbnailRect.height() * mThumbnailScale);
-
- if (thumbnailWidth >= viewWidth && thumbnailHeight >= viewHeight) {
- // Thumbnail fills the full task view bounds, so just draw it
- canvas.drawRoundRect(0, 0, viewWidth, viewHeight, mCornerRadius, mCornerRadius,
- mDrawPaint);
- } else {
- // Thumbnail does not fill the full task view bounds, so just draw it and fill the
- // empty areas with the background color
- int count = canvas.save();
-
- // Since we only want the top corners to be rounded, draw slightly beyond the
- // thumbnail height, but clip to the thumbnail height
- canvas.clipRect(0, 0, thumbnailWidth, thumbnailHeight, Region.Op.REPLACE);
- canvas.drawRoundRect(0, 0,
- thumbnailWidth + (thumbnailWidth < viewWidth ? mCornerRadius : 0),
- thumbnailHeight + (thumbnailHeight < viewHeight ? mCornerRadius : 0),
- mCornerRadius, mCornerRadius, mDrawPaint);
-
- // In the remaining space, draw the background color
- if (thumbnailWidth < viewWidth) {
- canvas.clipRect(thumbnailWidth, 0, viewWidth, viewHeight, Region.Op.REPLACE);
- canvas.drawRoundRect(Math.max(0, thumbnailWidth - mCornerRadius), 0,
- viewWidth, viewHeight, mCornerRadius, mCornerRadius, mBgFillPaint);
- }
- if (thumbnailWidth > 0 && thumbnailHeight < viewHeight) {
- canvas.clipRect(0, thumbnailHeight, viewWidth, viewHeight, Region.Op.REPLACE);
- canvas.drawRoundRect(0, Math.max(0, thumbnailHeight - mCornerRadius),
- viewWidth, viewHeight, mCornerRadius, mCornerRadius, mBgFillPaint);
- }
-
- canvas.restoreToCount(count);
+ // Draw the background, there will be some small overdraw with the thumbnail
+ if (thumbnailWidth < viewWidth) {
+ // Portrait thumbnail on a landscape task view
+ canvas.drawRoundRect(Math.max(0, thumbnailWidth - mCornerRadius), topOffset,
+ viewWidth, viewHeight,
+ mCornerRadius, mCornerRadius, mBgFillPaint);
}
+ if (thumbnailHeight < viewHeight) {
+ // Landscape thumbnail on a portrait task view
+ canvas.drawRoundRect(0, Math.max(topOffset, thumbnailHeight - mCornerRadius),
+ viewWidth, viewHeight,
+ mCornerRadius, mCornerRadius, mBgFillPaint);
+ }
+
+ // Draw the thumbnail
+ canvas.drawRoundRect(0, topOffset, thumbnailWidth, thumbnailHeight,
+ mCornerRadius, mCornerRadius, mDrawPaint);
} else {
canvas.drawRoundRect(0, 0, viewWidth, viewHeight, mCornerRadius, mCornerRadius,
mBgFillPaint);
@@ -289,10 +279,7 @@
/** Updates the clip rect based on the given task bar. */
void updateClipToTaskBar(View taskBar) {
mTaskBar = taskBar;
- int top = (int) Math.max(0, taskBar.getTranslationY() +
- taskBar.getMeasuredHeight() - 1);
- mClipRect.set(0, top, getMeasuredWidth(), getMeasuredHeight());
- setClipBounds(mClipRect);
+ invalidate();
}
/** Updates the visibility of the the thumbnail. */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
index b512393..397f24e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -19,11 +19,14 @@
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
+import android.graphics.Rect;
import android.graphics.RectF;
import android.util.IntProperty;
import android.util.Property;
import android.view.View;
+import com.android.systemui.recents.misc.Utilities;
+
import java.util.ArrayList;
/**
@@ -31,55 +34,20 @@
*/
public class TaskViewTransform {
- public static final Property<View, Integer> LEFT =
- new IntProperty<View>("left") {
+ public static final Property<View, Rect> LTRB =
+ new Property<View, Rect>(Rect.class, "leftTopRightBottom") {
+
+ private Rect mTmpRect = new Rect();
+
@Override
- public void setValue(View object, int v) {
- object.setLeft(v);
+ public void set(View v, Rect ltrb) {
+ v.setLeftTopRightBottom(ltrb.left, ltrb.top, ltrb.right, ltrb.bottom);
}
@Override
- public Integer get(View object) {
- return object.getLeft();
- }
- };
-
- public static final Property<View, Integer> TOP =
- new IntProperty<View>("top") {
- @Override
- public void setValue(View object, int v) {
- object.setTop(v);
- }
-
- @Override
- public Integer get(View object) {
- return object.getTop();
- }
- };
-
- public static final Property<View, Integer> RIGHT =
- new IntProperty<View>("right") {
- @Override
- public void setValue(View object, int v) {
- object.setRight(v);
- }
-
- @Override
- public Integer get(View object) {
- return object.getRight();
- }
- };
-
- public static final Property<View, Integer> BOTTOM =
- new IntProperty<View>("bottom") {
- @Override
- public void setValue(View object, int v) {
- object.setBottom(v);
- }
-
- @Override
- public Integer get(View object) {
- return object.getBottom();
+ public Rect get(View v) {
+ mTmpRect.set(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
+ return mTmpRect;
}
};
@@ -205,11 +173,12 @@
animators.add(animation.apply(AnimationProps.ALPHA, anim));
}
if (hasRectChangedFrom(v)) {
+ Rect fromViewRect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
+ Rect toViewRect = new Rect();
+ rect.round(toViewRect);
ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(v,
- PropertyValuesHolder.ofInt(LEFT, v.getLeft(), (int) rect.left),
- PropertyValuesHolder.ofInt(TOP, v.getTop(), (int) rect.top),
- PropertyValuesHolder.ofInt(RIGHT, v.getRight(), (int) rect.right),
- PropertyValuesHolder.ofInt(BOTTOM, v.getBottom(), (int) rect.bottom));
+ PropertyValuesHolder.ofObject(LTRB, Utilities.RECT_EVALUATOR,
+ fromViewRect, toViewRect));
animators.add(animation.apply(AnimationProps.BOUNDS, anim));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 69dcabe..0aeb7b4 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -102,8 +102,8 @@
int dockMode = (shortcutCode == SC_DOCK_LEFT)
? ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
: ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
- recents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE, dockMode, null);
- MetricsLogger.action(mContext, MetricsEvent.WINDOW_DOCK_SHORTCUTS);
+ recents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE, dockMode, null,
+ MetricsEvent.WINDOW_DOCK_SHORTCUTS);
} else {
// If there is already a docked window, we respond by resizing the docking pane.
DividerView dividerView = getComponent(Divider.class).getView();
@@ -115,7 +115,8 @@
DividerSnapAlgorithm.SnapTarget target = snapAlgorithm.cycleNonDismissTarget(
currentTarget, increment);
dividerView.startDragging(true /* animate */, false /* touching */);
- dividerView.stopDragging(target.position, 0f, true /* avoidDismissStart */);
+ dividerView.stopDragging(target.position, 0f, true /* avoidDismissStart */,
+ true /* logMetrics */);
}
} catch (RemoteException e) {
Log.e(TAG, "handleDockKey() failed.");
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index d294c80..2bf0b40 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -146,5 +146,10 @@
throws RemoteException {
updateMinimizedDockedStack(minimized, animDuration);
}
+
+ @Override
+ public void onDockSideChanged(final int newDockSide) throws RemoteException {
+ mView.post(() -> mView.notifyDockSideChanged(newDockSide));
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 3005535..66a413c 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -31,12 +31,13 @@
import android.graphics.Region.Op;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
+import android.os.Vibrator;
import android.util.AttributeSet;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.GestureDetector;
-import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.VelocityTracker;
@@ -45,7 +46,6 @@
import android.view.ViewConfiguration;
import android.view.ViewTreeObserver.InternalInsetsInfo;
import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -54,11 +54,14 @@
import android.view.animation.PathInterpolator;
import android.widget.FrameLayout;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
import com.android.internal.policy.DockedDividerUtils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.recents.Constants.Metrics;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
@@ -80,7 +83,13 @@
static final long TOUCH_ANIMATION_DURATION = 150;
static final long TOUCH_RELEASE_ANIMATION_DURATION = 200;
- private static final String TAG = "DividerView";
+ private static final int LOG_VALUE_RESIZE_50_50 = 0;
+ private static final int LOG_VALUE_RESIZE_DOCKED_SMALLER = 1;
+ private static final int LOG_VALUE_RESIZE_DOCKED_LARGER = 2;
+
+ private static final int LOG_VALUE_UNDOCK_MAX_DOCKED = 0;
+ private static final int LOG_VALUE_UNDOCK_MAX_OTHER = 1;
+
private static final int TASK_POSITION_SAME = Integer.MAX_VALUE;
private static final boolean SWAPPING_ENABLED = false;
@@ -88,7 +97,7 @@
/**
* How much the background gets scaled when we are in the minimized dock state.
*/
- private static final float MINIMIZE_DOCK_SCALE = 0.375f;
+ private static final float MINIMIZE_DOCK_SCALE = 0f;
private static final PathInterpolator SLOWDOWN_INTERPOLATOR =
new PathInterpolator(0.5f, 1f, 0.5f, 1f);
@@ -97,6 +106,7 @@
private DividerHandleView mHandle;
private View mBackground;
+ private MinimizedDockShadow mMinimizedShadow;
private int mStartX;
private int mStartY;
private int mStartPosition;
@@ -133,6 +143,8 @@
private boolean mGrowRecents;
private ValueAnimator mCurrentAnimator;
private boolean mEntranceAnimationRunning;
+ private boolean mExitAnimationRunning;
+ private int mExitStartPosition;
private GestureDetector mGestureDetector;
private boolean mDockedStackMinimized;
@@ -201,6 +213,7 @@
super.onFinishInflate();
mHandle = (DividerHandleView) findViewById(R.id.docked_divider_handle);
mBackground = findViewById(R.id.docked_divider_background);
+ mMinimizedShadow = (MinimizedDockShadow) findViewById(R.id.minimized_dock_shadow);
mHandle.setOnTouchListener(this);
mDividerWindowWidth = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_thickness);
@@ -267,6 +280,18 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
+ int minimizeLeft = 0;
+ int minimizeTop = 0;
+ if (mDockSide == WindowManager.DOCKED_TOP) {
+ minimizeTop = mBackground.getTop();
+ } else if (mDockSide == WindowManager.DOCKED_LEFT) {
+ minimizeLeft = mBackground.getLeft();
+ } else if (mDockSide == WindowManager.DOCKED_RIGHT) {
+ minimizeLeft = mBackground.getRight() - mMinimizedShadow.getWidth();
+ }
+ mMinimizedShadow.layout(minimizeLeft, minimizeTop,
+ minimizeLeft + mMinimizedShadow.getMeasuredWidth(),
+ minimizeTop + mMinimizedShadow.getMeasuredHeight());
if (changed) {
mWindowManagerProxy.setTouchRegion(new Rect(mHandle.getLeft(), mHandle.getTop(),
mHandle.getRight(), mHandle.getBottom()));
@@ -297,22 +322,28 @@
return mDockSide != WindowManager.DOCKED_INVALID;
}
- public void stopDragging(int position, float velocity, boolean avoidDismissStart) {
+ public void stopDragging(int position, float velocity, boolean avoidDismissStart,
+ boolean logMetrics) {
mHandle.setTouching(false, true /* animate */);
- fling(position, velocity, avoidDismissStart);
+ fling(position, velocity, avoidDismissStart, logMetrics);
mWindowManager.setSlippery(true);
releaseBackground();
}
public void stopDragging(int position, SnapTarget target, long duration,
Interpolator interpolator) {
- stopDragging(position, target, duration, 0 /* startDelay*/, interpolator);
+ stopDragging(position, target, duration, 0 /* startDelay*/, 0 /* endDelay */, interpolator);
+ }
+
+ public void stopDragging(int position, SnapTarget target, long duration,
+ Interpolator interpolator, long endDelay) {
+ stopDragging(position, target, duration, 0 /* startDelay*/, endDelay, interpolator);
}
public void stopDragging(int position, SnapTarget target, long duration, long startDelay,
- Interpolator interpolator) {
+ long endDelay, Interpolator interpolator) {
mHandle.setTouching(false, true /* animate */);
- flingTo(position, target, duration, startDelay, interpolator);
+ flingTo(position, target, duration, startDelay, endDelay, interpolator);
mWindowManager.setSlippery(true);
releaseBackground();
}
@@ -325,6 +356,7 @@
private void updateDockSide() {
mDockSide = mWindowManagerProxy.getDockSide();
+ mMinimizedShadow.setDockSide(mDockSide);
}
private void initializeSnapAlgorithm() {
@@ -396,37 +428,70 @@
mVelocityTracker.computeCurrentVelocity(1000);
int position = calculatePosition(x, y);
stopDragging(position, isHorizontalDivision() ? mVelocityTracker.getYVelocity()
- : mVelocityTracker.getXVelocity(), false /* avoidDismissStart */);
+ : mVelocityTracker.getXVelocity(), false /* avoidDismissStart */,
+ true /* log */);
mMoving = false;
break;
}
return true;
}
+ private void logResizeEvent(SnapTarget snapTarget) {
+ if (snapTarget == mSnapAlgorithm.getDismissStartTarget()) {
+ MetricsLogger.action(
+ mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_MAX, dockSideTopLeft(mDockSide)
+ ? LOG_VALUE_UNDOCK_MAX_OTHER
+ : LOG_VALUE_UNDOCK_MAX_DOCKED);
+ } else if (snapTarget == mSnapAlgorithm.getDismissEndTarget()) {
+ MetricsLogger.action(
+ mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_MAX, dockSideBottomRight(mDockSide)
+ ? LOG_VALUE_UNDOCK_MAX_OTHER
+ : LOG_VALUE_UNDOCK_MAX_DOCKED);
+ } else if (snapTarget == mSnapAlgorithm.getMiddleTarget()) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
+ LOG_VALUE_RESIZE_50_50);
+ } else if (snapTarget == mSnapAlgorithm.getFirstSplitTarget()) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
+ dockSideTopLeft(mDockSide)
+ ? LOG_VALUE_RESIZE_DOCKED_SMALLER
+ : LOG_VALUE_RESIZE_DOCKED_LARGER);
+ } else if (snapTarget == mSnapAlgorithm.getLastSplitTarget()) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
+ dockSideTopLeft(mDockSide)
+ ? LOG_VALUE_RESIZE_DOCKED_LARGER
+ : LOG_VALUE_RESIZE_DOCKED_SMALLER);
+ }
+ }
+
private void convertToScreenCoordinates(MotionEvent event) {
event.setLocation(event.getRawX(), event.getRawY());
}
- private void fling(int position, float velocity, boolean avoidDismissStart) {
+ private void fling(int position, float velocity, boolean avoidDismissStart,
+ boolean logMetrics) {
SnapTarget snapTarget = mSnapAlgorithm.calculateSnapTarget(position, velocity);
if (avoidDismissStart && snapTarget == mSnapAlgorithm.getDismissStartTarget()) {
snapTarget = mSnapAlgorithm.getFirstSplitTarget();
}
- ValueAnimator anim = getFlingAnimator(position, snapTarget);
+ if (logMetrics) {
+ logResizeEvent(snapTarget);
+ }
+ ValueAnimator anim = getFlingAnimator(position, snapTarget, 0 /* endDelay */);
mFlingAnimationUtils.apply(anim, position, snapTarget.position, velocity);
anim.start();
}
private void flingTo(int position, SnapTarget target, long duration, long startDelay,
- Interpolator interpolator) {
- ValueAnimator anim = getFlingAnimator(position, target);
+ long endDelay, Interpolator interpolator) {
+ ValueAnimator anim = getFlingAnimator(position, target, endDelay);
anim.setDuration(duration);
anim.setStartDelay(startDelay);
anim.setInterpolator(interpolator);
anim.start();
}
- private ValueAnimator getFlingAnimator(int position, final SnapTarget snapTarget) {
+ private ValueAnimator getFlingAnimator(int position, final SnapTarget snapTarget,
+ final long endDelay) {
ValueAnimator anim = ValueAnimator.ofInt(position, snapTarget.position);
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
@@ -437,15 +502,31 @@
: snapTarget.position, snapTarget);
}
});
+ Runnable endAction = () -> {
+ commitSnapFlags(snapTarget);
+ mWindowManagerProxy.setResizing(false);
+ mDockSide = WindowManager.DOCKED_INVALID;
+ mCurrentAnimator = null;
+ mEntranceAnimationRunning = false;
+ mExitAnimationRunning = false;
+ EventBus.getDefault().send(new StoppedDragingEvent());
+ };
anim.addListener(new AnimatorListenerAdapter() {
+
+ private boolean mCancelled;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
+
@Override
public void onAnimationEnd(Animator animation) {
- commitSnapFlags(snapTarget);
- mWindowManagerProxy.setResizing(false);
- mDockSide = WindowManager.DOCKED_INVALID;
- mCurrentAnimator = null;
- mEntranceAnimationRunning = false;
- EventBus.getDefault().send(new StoppedDragingEvent());
+ if (endDelay == 0 || mCancelled) {
+ endAction.run();
+ } else {
+ postDelayed(endAction, endDelay);
+ }
}
});
mCurrentAnimator = anim;
@@ -538,6 +619,7 @@
: mBackground.getWidth());
mBackground.setScaleX(MINIMIZE_DOCK_SCALE);
}
+ mMinimizedShadow.setAlpha(minimized ? 1f : 0f);
mDockedStackMinimized = minimized;
}
@@ -563,6 +645,11 @@
if (!minimized) {
mBackground.animate().withEndAction(mResetBackgroundRunnable);
}
+ mMinimizedShadow.animate()
+ .alpha(minimized ? 1f : 0f)
+ .setInterpolator(Interpolators.ALPHA_IN)
+ .setDuration(animDuration)
+ .start();
mBackground.animate()
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.setDuration(animDuration)
@@ -575,6 +662,7 @@
mBackground.setPivotY(mBackground.getHeight() / 2);
mBackground.setScaleX(1f);
mBackground.setScaleY(1f);
+ mMinimizedShadow.setAlpha(0f);
}
@Override
@@ -583,6 +671,13 @@
updateDisplayInfo();
}
+
+ public void notifyDockSideChanged(int newDockSide) {
+ mDockSide = newDockSide;
+ mMinimizedShadow.setDockSide(mDockSide);
+ requestLayout();
+ }
+
private void updateDisplayInfo() {
final DisplayManager displayManager =
(DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
@@ -654,6 +749,15 @@
mOtherTaskRect);
mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, null,
mOtherTaskRect, null);
+ } else if (mExitAnimationRunning && taskPosition != TASK_POSITION_SAME) {
+ calculateBoundsForPosition(taskPosition,
+ mDockSide, mDockedTaskRect);
+ calculateBoundsForPosition(mExitStartPosition,
+ DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
+ mOtherInsetRect.set(mOtherTaskRect);
+ applyExitAnimationParallax(mOtherTaskRect, position);
+ mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, null,
+ mOtherTaskRect, mOtherInsetRect);
} else if (taskPosition != TASK_POSITION_SAME) {
calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
mOtherRect);
@@ -692,6 +796,16 @@
dimFraction);
}
+ private void applyExitAnimationParallax(Rect taskRect, int position) {
+ if (mDockSide == WindowManager.DOCKED_TOP) {
+ taskRect.offset(0, (int) ((position - mExitStartPosition) * 0.25f));
+ } else if (mDockSide == WindowManager.DOCKED_LEFT) {
+ taskRect.offset((int) ((position - mExitStartPosition) * 0.25f), 0);
+ } else if (mDockSide == WindowManager.DOCKED_RIGHT) {
+ taskRect.offset((int) ((mExitStartPosition - position) * 0.25f), 0);
+ }
+ }
+
private float getDimFraction(int position, SnapTarget dismissTarget) {
if (mEntranceAnimationRunning) {
return 0f;
@@ -866,20 +980,26 @@
mEntranceAnimationRunning = true;
resizeStack(position, mSnapAlgorithm.getMiddleTarget().position,
mSnapAlgorithm.getMiddleTarget());
+
+ // Vibrate after docking
+ performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}
public final void onBusEvent(RecentsDrawnEvent drawnEvent) {
if (mAnimateAfterRecentsDrawn) {
mAnimateAfterRecentsDrawn = false;
updateDockSide();
- stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(), 250,
- Interpolators.TOUCH_RESPONSE);
+
+ // Delay switching resizing mode because this might cause jank in recents animation
+ // that's long than this animation.
+ stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(),
+ 250 /* startDelay */, Interpolators.FAST_OUT_SLOW_IN, 200 /* endDelay */);
}
if (mGrowAfterRecentsDrawn) {
mGrowAfterRecentsDrawn = false;
updateDockSide();
stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(), 250,
- Interpolators.TOUCH_RESPONSE);
+ Interpolators.FAST_OUT_SLOW_IN);
}
}
@@ -892,8 +1012,13 @@
: mSnapAlgorithm.getDismissStartTarget();
// Don't start immediately - give a little bit time to settle the drag resize change.
- stopDragging(getCurrentPosition(), target, 336 /* duration */, 100 /* startDelay */,
- Interpolators.TOUCH_RESPONSE);
+ mExitAnimationRunning = true;
+ mExitStartPosition = getCurrentPosition();
+ stopDragging(mExitStartPosition, target, 336 /* duration */, 100 /* startDelay */,
+ 0 /* endDelay */, Interpolators.FAST_OUT_SLOW_IN);
+
+ // Vibrate after undocking
+ performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
index d4922c3..177296b 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
@@ -48,6 +48,7 @@
setContentView(R.layout.forced_resizable_activity);
TextView tv = (TextView) findViewById(com.android.internal.R.id.message);
tv.setText(R.string.dock_forced_resizable);
+ getWindow().setTitle(getString(R.string.dock_forced_resizable));
getWindow().getDecorView().setOnTouchListener(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/MinimizedDockShadow.java b/packages/SystemUI/src/com/android/systemui/stackdivider/MinimizedDockShadow.java
new file mode 100644
index 0000000..ecff54f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/MinimizedDockShadow.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.stackdivider;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Shader;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.WindowManager;
+
+import com.android.systemui.R;
+
+/**
+ * Shadow for the minimized dock state on homescreen.
+ */
+public class MinimizedDockShadow extends View {
+
+ private final Paint mShadowPaint = new Paint();
+
+ private int mDockSide = WindowManager.DOCKED_INVALID;
+
+ public MinimizedDockShadow(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public void setDockSide(int dockSide) {
+ if (dockSide != mDockSide) {
+ mDockSide = dockSide;
+ updatePaint(getLeft(), getTop(), getRight(), getBottom());
+ invalidate();
+ }
+ }
+
+ private void updatePaint(int left, int top, int right, int bottom) {
+ int startColor = mContext.getResources().getColor(
+ R.color.minimize_dock_shadow_start, null);
+ int endColor = mContext.getResources().getColor(
+ R.color.minimize_dock_shadow_end, null);
+ final int middleColor = Color.argb(
+ (Color.alpha(startColor) + Color.alpha(endColor)) / 2, 0, 0, 0);
+ final int quarter = Color.argb(
+ (int) (Color.alpha(startColor) * 0.25f + Color.alpha(endColor) * 0.75f),
+ 0, 0, 0);
+ if (mDockSide == WindowManager.DOCKED_TOP) {
+ mShadowPaint.setShader(new LinearGradient(
+ 0, 0, 0, bottom - top,
+ new int[] { startColor, middleColor, quarter, endColor },
+ new float[] { 0f, 0.35f, 0.6f, 1f }, Shader.TileMode.CLAMP));
+ } else if (mDockSide == WindowManager.DOCKED_LEFT) {
+ mShadowPaint.setShader(new LinearGradient(
+ 0, 0, right - left, 0,
+ new int[] { startColor, middleColor, quarter, endColor },
+ new float[] { 0f, 0.35f, 0.6f, 1f }, Shader.TileMode.CLAMP));
+ } else if (mDockSide == WindowManager.DOCKED_RIGHT) {
+ mShadowPaint.setShader(new LinearGradient(
+ right - left, 0, 0, 0,
+ new int[] { startColor, middleColor, quarter, endColor },
+ new float[] { 0f, 0.35f, 0.6f, 1f }, Shader.TileMode.CLAMP));
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ if (changed) {
+ updatePaint(left, top, right, bottom);
+ invalidate();
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ canvas.drawRect(0, 0, getWidth(), getHeight(), mShadowPaint);
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 1b2393a..237ca5e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -63,6 +63,8 @@
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
@@ -262,11 +264,24 @@
protected AssistManager mAssistManager;
+ protected boolean mVrMode;
+
@Override // NotificationData.Environment
public boolean isDeviceProvisioned() {
return mDeviceProvisioned;
}
+ private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
+ @Override
+ public void onVrStateChanged(boolean enabled) {
+ mVrMode = enabled;
+ }
+ };
+
+ public boolean isDeviceInVrMode() {
+ return mVrMode;
+ }
+
protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
@@ -776,6 +791,14 @@
mContext.registerReceiverAsUser(mAllUsersReceiver, UserHandle.ALL, allUsersFilter,
null, null);
updateCurrentProfilesCache();
+
+ IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService("vrmanager"));
+ try {
+ vrManager.registerListener(mVrStateCallbacks);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to register VR mode state listener: " + e);
+ }
+
}
protected void notifyUserAboutHiddenNotifications() {
@@ -1207,7 +1230,7 @@
@Override
public void toggleSplitScreen() {
- toggleSplitScreenMode();
+ toggleSplitScreenMode(-1 /* metricsDockAction */, -1 /* metricsUndockAction */);
}
@Override
@@ -1283,9 +1306,12 @@
/**
* Toggle docking the app window
*
- * @return {@code true} if the app window is docked after the toggle, {@code false} otherwise.
+ * @param metricsDockAction the action to log when docking is successful, or -1 to not log
+ * anything on successful docking
+ * @param metricsUndockAction the action to log when undocking, or -1 to not log anything when
+ * undocking
*/
- protected abstract boolean toggleSplitScreenMode();
+ protected abstract void toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction);
/** Proxy for RecentsComponent */
@@ -1315,7 +1341,7 @@
}
protected void toggleKeyboardShortcuts(int deviceId) {
- getKeyboardShortcuts().toggleKeyboardShortcuts(deviceId);
+ KeyboardShortcuts.toggle(mContext, deviceId);
}
protected void cancelPreloadingRecents() {
@@ -1549,7 +1575,11 @@
row.setRemoteInputController(mRemoteInputController);
row.setOnExpandClickListener(this);
- // Get the app name
+ // Get the app name.
+ // Note that Notification.Builder#bindHeaderAppName has similar logic
+ // but since this field is used in the guts, it must be accurate.
+ // Therefore we will only show the application label, or, failing that, the
+ // package name. No substitutions.
final String pkg = sbn.getPackageName();
String appname = pkg;
try {
@@ -1712,14 +1742,6 @@
}
}
- protected KeyboardShortcuts getKeyboardShortcuts() {
- if (mKeyboardShortcuts == null) {
- mKeyboardShortcuts = new KeyboardShortcuts(mContext);
- }
-
- return mKeyboardShortcuts;
- }
-
public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
if (!isDeviceProvisioned()) return;
@@ -2353,6 +2375,10 @@
}
protected boolean shouldPeek(Entry entry, StatusBarNotification sbn) {
+ if (isDeviceInVrMode()) {
+ return false;
+ }
+
if (mNotificationData.shouldFilterOut(sbn)) {
if (DEBUG) Log.d(TAG, "No peeking: filtered notification: " + sbn.getKey());
return false;
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/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index fff1491..79e06c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -58,6 +58,8 @@
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;
@@ -68,6 +70,10 @@
*/
public final class KeyboardShortcuts {
private static final String TAG = KeyboardShortcuts.class.getSimpleName();
+ private static final Object sLock = new Object();
+ private static KeyboardShortcuts sInstance;
+ private static boolean sIsShowing;
+
private final SparseArray<String> mSpecialCharacterNames = new SparseArray<>();
private final SparseArray<String> mModifierNames = new SparseArray<>();
private final SparseArray<Drawable> mSpecialCharacterDrawables = new SparseArray<>();
@@ -76,21 +82,79 @@
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final Context mContext;
private final IPackageManager mPackageManager;
- private final OnClickListener dialogCloseListener = new DialogInterface.OnClickListener() {
+ private final OnClickListener mDialogCloseListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
- dismissKeyboardShortcutsDialog();
+ dismissKeyboardShortcuts();
}
};
+ 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) {
+ private KeyboardShortcuts(Context context) {
this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_Material_Light);
this.mPackageManager = AppGlobals.getPackageManager();
loadResources(context);
}
+ private static KeyboardShortcuts getInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = new KeyboardShortcuts(context);
+ }
+ return sInstance;
+ }
+
+ public static void show(Context context, int deviceId) {
+ synchronized (sLock) {
+ if (sInstance != null && !sInstance.mContext.equals(context)) {
+ dismiss();
+ }
+ getInstance(context).showKeyboardShortcuts(deviceId);
+ sIsShowing = true;
+ }
+ }
+
+ public static void toggle(Context context, int deviceId) {
+ synchronized (sLock) {
+ if (sIsShowing) {
+ dismiss();
+ } else {
+ show(context, deviceId);
+ }
+ }
+ }
+
+ public static void dismiss() {
+ synchronized (sLock) {
+ if (sInstance != null) {
+ sInstance.dismissKeyboardShortcuts();
+ sInstance = null;
+ }
+ sIsShowing = false;
+ }
+ }
+
private void loadResources(Context context) {
mSpecialCharacterNames.put(
KeyEvent.KEYCODE_HOME, context.getString(R.string.keyboard_key_home));
@@ -254,13 +318,38 @@
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();
+ /**
+ * 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;
+ }
}
- if (mKeyboardShortcutsDialog == null) {
- Recents.getSystemServices().requestKeyboardShortcuts(mContext,
+ 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();
+ }
+
+ private void showKeyboardShortcuts(int deviceId) {
+ retrieveKeyCharacterMap(deviceId);
+ Recents.getSystemServices().requestKeyboardShortcuts(mContext,
new KeyboardShortcutsReceiver() {
@Override
public void onKeyboardShortcutsReceived(
@@ -273,12 +362,9 @@
showKeyboardShortcutsDialog(result);
}
}, deviceId);
- } else {
- dismissKeyboardShortcutsDialog();
- }
}
- public void dismissKeyboardShortcutsDialog() {
+ private void dismissKeyboardShortcuts() {
if (mKeyboardShortcutsDialog != null) {
mKeyboardShortcutsDialog.dismiss();
mKeyboardShortcutsDialog = null;
@@ -320,9 +406,7 @@
private KeyboardShortcutGroup getDefaultApplicationShortcuts() {
final int userId = mContext.getUserId();
- final KeyboardShortcutGroup applicationGroup = new KeyboardShortcutGroup(
- mContext.getString(R.string.keyboard_shortcut_group_applications),
- true);
+ List<KeyboardShortcutInfo> keyboardShortcutInfoAppItems = new ArrayList<>();
// Assist.
final AssistUtils assistUtils = new AssistUtils(mContext);
@@ -340,7 +424,7 @@
assistPackageInfo.applicationInfo.packageName,
assistPackageInfo.applicationInfo.icon);
- applicationGroup.addItem(new KeyboardShortcutInfo(
+ keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo(
mContext.getString(R.string.keyboard_shortcut_group_applications_assist),
assistIcon,
KeyEvent.KEYCODE_UNKNOWN,
@@ -350,7 +434,7 @@
// Browser.
final Icon browserIcon = getIconForIntentCategory(Intent.CATEGORY_APP_BROWSER, userId);
if (browserIcon != null) {
- applicationGroup.addItem(new KeyboardShortcutInfo(
+ keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo(
mContext.getString(R.string.keyboard_shortcut_group_applications_browser),
browserIcon,
KeyEvent.KEYCODE_B,
@@ -361,7 +445,7 @@
// Contacts.
final Icon contactsIcon = getIconForIntentCategory(Intent.CATEGORY_APP_CONTACTS, userId);
if (contactsIcon != null) {
- applicationGroup.addItem(new KeyboardShortcutInfo(
+ keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo(
mContext.getString(R.string.keyboard_shortcut_group_applications_contacts),
contactsIcon,
KeyEvent.KEYCODE_C,
@@ -371,7 +455,7 @@
// Email.
final Icon emailIcon = getIconForIntentCategory(Intent.CATEGORY_APP_EMAIL, userId);
if (emailIcon != null) {
- applicationGroup.addItem(new KeyboardShortcutInfo(
+ keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo(
mContext.getString(R.string.keyboard_shortcut_group_applications_email),
emailIcon,
KeyEvent.KEYCODE_E,
@@ -381,7 +465,7 @@
// Messaging.
final Icon messagingIcon = getIconForIntentCategory(Intent.CATEGORY_APP_MESSAGING, userId);
if (messagingIcon != null) {
- applicationGroup.addItem(new KeyboardShortcutInfo(
+ keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo(
mContext.getString(R.string.keyboard_shortcut_group_applications_im),
messagingIcon,
KeyEvent.KEYCODE_T,
@@ -391,7 +475,7 @@
// Music.
final Icon musicIcon = getIconForIntentCategory(Intent.CATEGORY_APP_MUSIC, userId);
if (musicIcon != null) {
- applicationGroup.addItem(new KeyboardShortcutInfo(
+ keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo(
mContext.getString(R.string.keyboard_shortcut_group_applications_music),
musicIcon,
KeyEvent.KEYCODE_P,
@@ -401,14 +485,24 @@
// Calendar.
final Icon calendarIcon = getIconForIntentCategory(Intent.CATEGORY_APP_CALENDAR, userId);
if (calendarIcon != null) {
- applicationGroup.addItem(new KeyboardShortcutInfo(
+ keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo(
mContext.getString(R.string.keyboard_shortcut_group_applications_calendar),
calendarIcon,
KeyEvent.KEYCODE_L,
KeyEvent.META_META_ON));
}
- return applicationGroup.getItems().size() == 0 ? null : applicationGroup;
+ 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) {
@@ -459,7 +553,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();
@@ -471,8 +565,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 shortcutTextItemHeight = getShortcutTextItemHeight(inflater);
+ 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(
@@ -488,12 +589,6 @@
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<StringOrDrawable> shortcutKeys = getHumanReadableShortcutKeys(info);
if (shortcutKeys == null) {
// Ignore shortcuts we can't display keys for.
@@ -529,8 +624,8 @@
ImageView shortcutKeyIconView = (ImageView) inflater.inflate(
R.layout.keyboard_shortcuts_key_icon_view, shortcutItemsContainer,
false);
- Bitmap bitmap = Bitmap.createBitmap(shortcutTextItemHeight,
- shortcutTextItemHeight, Bitmap.Config.ARGB_8888);
+ Bitmap bitmap = Bitmap.createBitmap(shortcutKeyIconItemHeightWidth,
+ shortcutKeyIconItemHeightWidth, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
shortcutRepresentation.drawable.setBounds(0, 0, canvas.getWidth(),
canvas.getHeight());
@@ -541,6 +636,7 @@
TextView shortcutKeyTextView = (TextView) inflater.inflate(
R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer,
false);
+ shortcutKeyTextView.setMinimumWidth(shortcutKeyTextItemMinWidth);
shortcutKeyTextView.setText(shortcutRepresentation.string);
shortcutItemsContainer.addView(shortcutKeyTextView);
}
@@ -557,16 +653,6 @@
}
}
- private int getShortcutTextItemHeight(LayoutInflater inflater) {
- TextView shortcutKeyTextView = (TextView) inflater.inflate(
- R.layout.keyboard_shortcuts_key_view, null, false);
- shortcutKeyTextView.measure(
- View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
- return shortcutKeyTextView.getMeasuredHeight()
- - shortcutKeyTextView.getPaddingTop()
- - shortcutKeyTextView.getPaddingBottom();
- }
-
private List<StringOrDrawable> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
List<StringOrDrawable> shortcutKeys = getHumanReadableModifiers(info);
if (shortcutKeys == null) {
@@ -585,9 +671,7 @@
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 {
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..5f4ebd8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.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())) {
+ KeyboardShortcuts.show(context, -1 /* deviceId unknown */);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 5b00523..491ffde 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -348,6 +348,12 @@
setVisible(isShown());
}
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ getViewTreeObserver().removeOnPreDrawListener(mEnableAnimationPredrawListener);
+ }
+
private void setVisible(final boolean isVisible) {
if (isVisible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
index a5ebbba..9ed5022 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
@@ -232,8 +232,9 @@
return;
}
final boolean isRtl = mParent.isLayoutRtl();
- final float left = isRtl ? -(mParent.getWidth() - mHorizSpaceForGear) : 0;
- final float right = isRtl ? 0 : (mParent.getWidth() - mHorizSpaceForGear);
+ // TODO No need to cast to float here once b/28050538 is fixed.
+ final float left = (float) (isRtl ? -(mParent.getWidth() - mHorizSpaceForGear) : 0);
+ final float right = (float) (isRtl ? 0 : (mParent.getWidth() - mHorizSpaceForGear));
setTranslationX(onLeft ? left : right);
mOnLeft = onLeft;
}
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..244536d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarBatteryController.java
@@ -0,0 +1,276 @@
+/*
+ * 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 void dispatchDemoCommand(String command, Bundle args) {
+ // TODO: Car demo mode.
+ }
+
+ @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/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 7fbb176..74bd096 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -30,6 +30,7 @@
import com.android.systemui.BatteryMeterView;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.qs.QSPanel;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.UserInfoController;
@@ -150,6 +151,10 @@
});
}
+ public void setQSPanel(QSPanel qsp) {
+ mMultiUserSwitch.setQsPanel(qsp);
+ }
+
@Override
public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index 3812429..92f3585 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -21,8 +21,12 @@
import android.app.IWallpaperManagerCallback;
import android.app.WallpaperManager;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.DrawableWrapper;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
@@ -151,4 +155,57 @@
getBitmap();
mBar.updateMediaMetaData(true /* metaDataChanged */, true /* allowEnterAnimation */);
}
+
+ /**
+ * Drawable that aligns left horizontally and center vertically (like ImageWallpaper).
+ */
+ public static class WallpaperDrawable extends DrawableWrapper {
+
+ private Bitmap mBackground;
+ private Rect mTmpRect = new Rect();
+
+ public WallpaperDrawable(Resources r, Bitmap b) {
+ super(new BitmapDrawable(r, b));
+ mBackground = b;
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return -1;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return -1;
+ }
+
+ @Override
+ protected void onBoundsChange(Rect bounds) {
+ int vwidth = getBounds().width();
+ int vheight = getBounds().height();
+ int dwidth = mBackground.getWidth();
+ int dheight = mBackground.getHeight();
+ float scale;
+ float dx = 0, dy = 0;
+
+ if (dwidth * vheight > vwidth * dheight) {
+ scale = (float) vheight / (float) dheight;
+ } else {
+ scale = (float) vwidth / (float) dwidth;
+ }
+
+ if (scale <= 1f) {
+ scale = 1f;
+ }
+ dy = (vheight - dheight * scale) * 0.5f;
+
+ mTmpRect.set(
+ bounds.left,
+ bounds.top + Math.round(dy),
+ bounds.left + Math.round(dwidth * scale),
+ bounds.top + Math.round(dheight * scale + dy));
+
+ super.onBoundsChange(mTmpRect);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index 54af684..6698d13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -127,10 +127,10 @@
mTmpInt2);
}
} else {
- Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
- getContext(), v, ContactsContract.Profile.CONTENT_URI,
- ContactsContract.QuickContact.MODE_LARGE, null);
if (mQsPanel != null) {
+ Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
+ getContext(), v, ContactsContract.Profile.CONTENT_URI,
+ ContactsContract.QuickContact.MODE_LARGE, null);
mQsPanel.getHost().startActivityDismissingKeyguard(intent);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index bb03454..583a63e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -214,15 +214,14 @@
< mContext.getResources().getDisplayMetrics().widthPixels / 2) {
createMode = ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
}
- boolean docked = mRecentsComponent.dockTopTask(dragMode, createMode, initialBounds);
+ boolean docked = mRecentsComponent.dockTopTask(dragMode, createMode, initialBounds,
+ MetricsEvent.ACTION_WINDOW_DOCK_SWIPE);
if (docked) {
mDragMode = dragMode;
if (mDragMode == DRAG_MODE_DIVIDER) {
mDivider.getView().startDragging(false /* animate */, true /* touching*/);
}
mDockWindowTouchSlopExceeded = true;
- MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_SWIPE);
-
return true;
}
}
@@ -250,7 +249,7 @@
mIsVertical
? mVelocityTracker.getXVelocity()
: mVelocityTracker.getYVelocity(),
- true /* avoidDismissStart */);
+ true /* avoidDismissStart */, false /* logMetrics */);
} else if (mDragMode == DRAG_MODE_RECENTS) {
mRecentsComponent.onDraggingInRecentsEnded(mVelocityTracker.getYVelocity());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 6859348..d7fa567 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -372,7 +372,10 @@
mDisabledFlags = disabledFlags;
final boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
- boolean disableRecent = ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
+
+ // Disable recents always in car mode.
+ boolean disableRecent = (
+ mCarMode || (disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0)
&& ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) == 0);
final boolean disableSearch = ((disabledFlags & View.STATUS_BAR_DISABLE_SEARCH) != 0);
@@ -526,6 +529,10 @@
public void onDockedStackMinimizedChanged(boolean minimized, long animDuration)
throws RemoteException {
}
+
+ @Override
+ public void onDockSideChanged(int newDockSide) throws RemoteException {
+ }
});
} catch (RemoteException e) {
Log.e(TAG, "Failed registering docked stack exists listener", e);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index a27ec28..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,7 @@
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Objects;
/**
@@ -37,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;
@@ -142,6 +144,9 @@
&& group.summary.notification.getNotification().isGroupSummary()
&& hasIsolatedChildren(group)));
if (prevSuppressed != group.suppressed) {
+ if (group.suppressed) {
+ handleSuppressedSummaryHeadsUpped(group.summary);
+ }
mListener.onGroupsChanged();
}
}
@@ -160,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) {
@@ -332,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())) {
@@ -344,6 +361,32 @@
}
}
+ 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.isGroup() && !sbn.getNotification().isGroupSummary())
@@ -360,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/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index d036fe4..b6fc66b 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;
@@ -48,6 +46,7 @@
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.InputMethodService;
@@ -135,6 +134,7 @@
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.GestureRecorder;
+import com.android.systemui.statusbar.KeyboardShortcuts;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.NotificationData.Entry;
@@ -147,6 +147,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 +731,7 @@
mHeadsUpManager.addListener(mGroupManager);
mNotificationPanel.setHeadsUpManager(mHeadsUpManager);
mNotificationData.setHeadsUpManager(mHeadsUpManager);
+ mGroupManager.setHeadsUpManager(mHeadsUpManager);
if (MULTIUSER_DEBUG) {
mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(
@@ -826,7 +828,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) {
@@ -893,6 +895,7 @@
qsContainer.setHost(qsh);
mQSPanel = qsContainer.getQsPanel();
mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
+ mKeyguardStatusBar.setQSPanel(mQSPanel);
mHeader = qsContainer.getHeader();
initSignalCluster(mHeader);
mHeader.setActivityStarter(PhoneStatusBar.this);
@@ -943,6 +946,10 @@
return mStatusBarView;
}
+ protected BatteryController createBatteryController() {
+ return new BatteryControllerImpl(mContext);
+ }
+
@Override
protected void reInflateViews() {
super.reInflateViews();
@@ -1167,35 +1174,32 @@
@Override
public boolean onLongClick(View v) {
- if (mRecents == null || !ActivityManager.supportsMultiWindow()) {
+ if (mRecents == null || !ActivityManager.supportsMultiWindow()
+ || !getComponent(Divider.class).getView().getSnapAlgorithm()
+ .isSplitScreenFeasible()) {
return false;
}
- boolean initiallyDocked = WindowManagerProxy.getInstance().getDockSide()
- == WindowManager.DOCKED_INVALID;
- boolean dockedAtEnd = toggleSplitScreenMode();
- if (dockedAtEnd != initiallyDocked) {
- int logAction = dockedAtEnd ? MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS
- : MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS;
- MetricsLogger.action(mContext, logAction);
- return true;
- }
- return false;
+ toggleSplitScreenMode(MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS,
+ MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS);
+ return true;
}
};
@Override
- protected boolean toggleSplitScreenMode() {
+ protected void toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) {
if (mRecents == null) {
- return false;
+ return;
}
int dockSide = WindowManagerProxy.getInstance().getDockSide();
if (dockSide == WindowManager.DOCKED_INVALID) {
- return mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE,
- ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, null);
+ mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE,
+ ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, null, metricsDockAction);
} else {
EventBus.getDefault().send(new UndockingTaskEvent());
- return false;
+ if (metricsUndockAction != -1) {
+ MetricsLogger.action(mContext, metricsUndockAction);
+ }
}
}
@@ -1368,6 +1372,10 @@
}
private boolean shouldSuppressFullScreenIntent(String key) {
+ if (isDeviceInVrMode()) {
+ return true;
+ }
+
if (mPowerManager.isInteractive()) {
return mNotificationData.shouldSuppressScreenOn(key);
} else {
@@ -1921,19 +1929,27 @@
+ " state=" + mState);
}
- Bitmap artworkBitmap = null;
+ Drawable artworkDrawable = null;
if (mMediaMetadata != null) {
+ Bitmap artworkBitmap = null;
artworkBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
if (artworkBitmap == null) {
artworkBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
// might still be null
}
+ if (artworkBitmap != null) {
+ artworkDrawable = new BitmapDrawable(mBackdropBack.getResources(), artworkBitmap);
+ }
}
- if (ENABLE_LOCKSCREEN_WALLPAPER && artworkBitmap == null) {
- artworkBitmap = mLockscreenWallpaper.getBitmap();
+ if (ENABLE_LOCKSCREEN_WALLPAPER && artworkDrawable == null) {
+ Bitmap lockWallpaper = mLockscreenWallpaper.getBitmap();
+ if (lockWallpaper != null) {
+ artworkDrawable = new LockscreenWallpaper.WallpaperDrawable(
+ mBackdropBack.getResources(), lockWallpaper);
+ }
}
- final boolean hasArtwork = artworkBitmap != null;
+ final boolean hasArtwork = artworkDrawable != null;
if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK) && mState != StatusBarState.SHADE
&& mFingerprintUnlockController.getMode()
@@ -1978,7 +1994,7 @@
mBackdropBack.setBackgroundColor(0xFFFFFFFF);
mBackdropBack.setImageDrawable(new ColorDrawable(c));
} else {
- mBackdropBack.setImageBitmap(artworkBitmap);
+ mBackdropBack.setImageDrawable(artworkDrawable);
}
if (mScrimSrcModeEnabled) {
mBackdropBack.getDrawable().mutate().setXfermode(mSrcXferMode);
@@ -3155,7 +3171,7 @@
if (DEBUG) Log.v(TAG, "onReceive: " + intent);
String action = intent.getAction();
if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
- getKeyboardShortcuts().dismissKeyboardShortcutsDialog();
+ KeyboardShortcuts.dismiss();
if (isCurrentProfile(getSendingUserId())) {
int flags = CommandQueue.FLAG_EXCLUDE_NONE;
String reason = intent.getStringExtra("reason");
@@ -3464,7 +3480,7 @@
@Override
public void run() {
mLeaveOpenOnKeyguardHide = true;
- executeRunnableDismissingKeyguard(runnable, null, false, true);
+ executeRunnableDismissingKeyguard(runnable, null, false, false);
}
});
}
@@ -3585,11 +3601,10 @@
dispatchDemoCommandToView(command, args, R.id.clock);
}
if (modeChange || command.equals(COMMAND_BATTERY)) {
- dispatchDemoCommandToView(command, args, R.id.battery);
+ mBatteryController.dispatchDemoCommand(command, args);
}
if (modeChange || command.equals(COMMAND_STATUS)) {
mIconController.dispatchDemoCommand(command, args);
-
}
if (mNetworkController != null && (modeChange || command.equals(COMMAND_NETWORK))) {
mNetworkController.dispatchDemoCommand(command, args);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 0ac2e7c..823af36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -139,6 +139,7 @@
filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
+ filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
// listen for user / profile change.
@@ -509,7 +510,8 @@
} else if (action.equals(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED)) {
updateTTY(intent);
} else if (action.equals(Intent.ACTION_MANAGED_PROFILE_AVAILABLE) ||
- action.equals(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)) {
+ action.equals(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE) ||
+ action.equals(Intent.ACTION_MANAGED_PROFILE_REMOVED)) {
updateQuietState();
updateManagedProfile();
} else if (action.equals(AudioManager.ACTION_HEADSET_PLUG)) {
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 ea9a5a5..2b03dfb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -125,6 +125,7 @@
// RenderThread is doing more harm than good when touching the header (to expand quick
// settings), so disable it for this view
((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
+ ((RippleDrawable) mExpandIndicator.getBackground()).setForceSoftware(true);
updateResources();
}
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..559436b 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,35 @@
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 com.android.systemui.DemoMode;
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 extends DemoMode {
+ /**
+ * 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..5d734c6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -0,0 +1,210 @@
+/*
+ * 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.Bundle;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.util.Log;
+import com.android.systemui.DemoMode;
+
+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;
+ private final Context mContext;
+
+ protected int mLevel;
+ protected boolean mPluggedIn;
+ protected boolean mCharging;
+ protected boolean mCharged;
+ protected boolean mPowerSave;
+ private boolean mTestmode = false;
+
+ public BatteryControllerImpl(Context context) {
+ mContext = context;
+ mHandler = new Handler();
+ mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+
+ registerReceiver();
+ updatePowerSave();
+ }
+
+ private void registerReceiver() {
+ 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);
+ mContext.registerReceiver(this, filter);
+ }
+
+ @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);
+ }
+ }
+
+ private boolean mDemoMode;
+
+ @Override
+ public void dispatchDemoCommand(String command, Bundle args) {
+ if (!mDemoMode && command.equals(COMMAND_ENTER)) {
+ mDemoMode = true;
+ mContext.unregisterReceiver(this);
+ } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
+ mDemoMode = false;
+ registerReceiver();
+ updatePowerSave();
+ } else if (mDemoMode && command.equals(COMMAND_BATTERY)) {
+ String level = args.getString("level");
+ String plugged = args.getString("plugged");
+ if (level != null) {
+ mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100);
+ }
+ if (plugged != null) {
+ mPluggedIn = Boolean.parseBoolean(plugged);
+ }
+ fireBatteryLevelChanged();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
index 6dd196b..c4c64e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
@@ -33,24 +33,29 @@
}
private void handleRestrictBackgroundChanged(boolean isDataSaving) {
- final int N = mListeners.size();
- for (int i = 0; i < N; i++) {
- mListeners.get(i).onDataSaverChanged(isDataSaving);
+ synchronized (mListeners) {
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onDataSaverChanged(isDataSaving);
+ }
}
}
public void addListener(Listener listener) {
- mListeners.add(listener);
- if (mListeners.size() == 1) {
- mPolicyManager.registerListener(mPolicyListener);
+ synchronized (mListeners) {
+ mListeners.add(listener);
+ if (mListeners.size() == 1) {
+ mPolicyManager.registerListener(mPolicyListener);
+ }
}
listener.onDataSaverChanged(isDataSaverEnabled());
}
public void remListener(Listener listener) {
- mListeners.remove(listener);
- if (mListeners.size() == 0) {
- mPolicyManager.unregisterListener(mPolicyListener);
+ synchronized (mListeners) {
+ mListeners.remove(listener);
+ if (mListeners.size() == 0) {
+ mPolicyManager.unregisterListener(mPolicyListener);
+ }
}
}
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..52fb470 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));
}
@@ -669,6 +674,13 @@
} else if (!selfFullscreen && otherFullscreen) {
return 1;
}
+
+ if (remoteInputActive && !o.remoteInputActive) {
+ return -1;
+ } else if (!remoteInputActive && o.remoteInputActive) {
+ return 1;
+ }
+
return postTime < o.postTime ? 1
: postTime == o.postTime ? entry.key.compareTo(o.entry.key)
: -1;
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/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 7c5cdfb..8b52bf6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -3799,6 +3799,7 @@
} else {
getViewTreeObserver().removeOnPreDrawListener(mShadowUpdater);
}
+ mContinuousShadowUpdate = continuousShadowUpdate;
}
}
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 450001f..acef81b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -127,8 +127,7 @@
}
@Override
- protected boolean toggleSplitScreenMode() {
- return false;
+ protected void toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) {
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index 748ee97..5e5da74 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -36,11 +36,16 @@
super.onCreate(savedInstanceState);
if (getFragmentManager().findFragmentByTag(TAG_TUNER) == null) {
+ final String action = getIntent().getAction();
+ boolean showDemoMode = action != null && action.equals(
+ "com.android.settings.action.DEMO_MODE");
boolean showNightMode = getIntent().getBooleanExtra(
NightModeFragment.EXTRA_SHOW_NIGHT_MODE, false);
+ final PreferenceFragment fragment = showNightMode ? new NightModeFragment()
+ : showDemoMode ? new DemoModeFragment()
+ : new TunerFragment();
getFragmentManager().beginTransaction().replace(R.id.content_frame,
- showNightMode ? new NightModeFragment() : new TunerFragment(),
- TAG_TUNER).commit();
+ fragment, TAG_TUNER).commit();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java
new file mode 100644
index 0000000..c65415e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlButtonView.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.tv.pip;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View.OnFocusChangeListener;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+
+/**
+ * A view containing PIP controls including fullscreen, close, and media controls.
+ */
+public class PipControlButtonView extends LinearLayout {
+ private OnFocusChangeListener mFocusChangeListener;
+ private ImageView mButtonImageView;
+ private TextView mDescriptionTextView;
+ private Animator mFocusGainAnimator;
+ private Animator mFocusLoseAnimator;
+
+ private final OnFocusChangeListener mInternalFocusChangeListener =
+ new OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ if (hasFocus) {
+ if (mFocusLoseAnimator.isStarted()) {
+ mFocusLoseAnimator.cancel();
+ }
+ mFocusGainAnimator.start();
+ } else {
+ if (mFocusGainAnimator.isStarted()) {
+ mFocusGainAnimator.cancel();
+ }
+ mFocusLoseAnimator.start();
+ }
+
+ if (mFocusChangeListener != null) {
+ mFocusChangeListener.onFocusChange(v, hasFocus);
+ }
+ }
+ };
+
+ public PipControlButtonView(Context context) {
+ this(context, null, 0, 0);
+ }
+
+ public PipControlButtonView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0, 0);
+ }
+
+ public PipControlButtonView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public PipControlButtonView(
+ Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ LayoutInflater inflater = (LayoutInflater) getContext()
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ inflater.inflate(R.layout.tv_pip_control_button, this);
+
+ setOrientation(LinearLayout.VERTICAL);
+ setGravity(Gravity.CENTER);
+
+ mButtonImageView = (ImageView) findViewById(R.id.button);
+ mDescriptionTextView = (TextView) findViewById(R.id.desc);
+
+ int[] values = new int[] {android.R.attr.src, android.R.attr.text};
+ TypedArray typedArray =
+ context.obtainStyledAttributes(attrs, values, defStyleAttr, defStyleRes);
+
+ mButtonImageView.setImageDrawable(typedArray.getDrawable(0));
+ mDescriptionTextView.setText(typedArray.getText(1));
+
+ typedArray.recycle();
+ }
+
+ @Override
+ public void onFinishInflate() {
+ super.onFinishInflate();
+ mButtonImageView.setOnFocusChangeListener(mInternalFocusChangeListener);
+
+ mFocusGainAnimator = AnimatorInflater.loadAnimator(getContext(),
+ R.anim.tv_pip_controls_text_focus_gain_animation);
+ mFocusGainAnimator.setTarget(mDescriptionTextView);
+ mFocusLoseAnimator = AnimatorInflater.loadAnimator(getContext(),
+ R.anim.tv_pip_controls_text_focus_lose_animation);
+ mFocusLoseAnimator.setTarget(mDescriptionTextView);
+ }
+
+ @Override
+ public void setOnClickListener(OnClickListener listener) {
+ mButtonImageView.setOnClickListener(listener);
+ }
+
+ @Override
+ public void setOnFocusChangeListener(OnFocusChangeListener listener) {
+ mFocusChangeListener = listener;
+ }
+
+ /**
+ * Sets the drawable for the button with the given resource id.
+ */
+ public void setImageResource(int resId) {
+ mButtonImageView.setImageResource(resId);
+ }
+
+ /**
+ * Sets the text for description the with the given resource id.
+ */
+ public void setText(int resId) {
+ mDescriptionTextView.setText(resId);
+ }
+
+ @Override
+ public boolean isFocused() {
+ return mButtonImageView.isFocused();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java
index 3f87611..d15799c 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipControlsView.java
@@ -57,13 +57,9 @@
final PipManager mPipManager = PipManager.getInstance();
Listener mListener;
- View mFullButtonView;
- View mFullDescriptionView;
- View mPlayPauseView;
- ImageView mPlayPauseButtonImageView;
- TextView mPlayPauseDescriptionTextView;
- View mCloseButtonView;
- View mCloseDescriptionView;
+ PipControlButtonView mFullButtonView;
+ PipControlButtonView mCloseButtonView;
+ PipControlButtonView mPlayPauseButtonView;
private boolean mHasFocus;
private OnFocusChangeListener mOnChildFocusChangeListener;
@@ -75,13 +71,20 @@
}
};
- private PipManager.MediaListener mPipMediaListener = new PipManager.MediaListener() {
+ private final PipManager.MediaListener mPipMediaListener = new PipManager.MediaListener() {
@Override
public void onMediaControllerChanged() {
updateMediaController();
}
};
+ private final OnFocusChangeListener mFocusChangeListener = new OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ onChildViewFocusChanged();
+ }
+ };
+
public PipControlsView(Context context) {
this(context, null, 0, 0);
}
@@ -108,26 +111,30 @@
public void onFinishInflate() {
super.onFinishInflate();
- mFullButtonView = findViewById(R.id.full_button);
- mFullDescriptionView = findViewById(R.id.full_desc);
+ mFullButtonView = (PipControlButtonView) findViewById(R.id.full_button);
+ mFullButtonView.setOnFocusChangeListener(mFocusChangeListener);
mFullButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPipManager.movePipToFullscreen();
}
});
- mFullButtonView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+
+ mCloseButtonView = (PipControlButtonView) findViewById(R.id.close_button);
+ mCloseButtonView.setOnFocusChangeListener(mFocusChangeListener);
+ mCloseButtonView.setOnClickListener(new View.OnClickListener() {
@Override
- public void onFocusChange(View v, boolean hasFocus) {
- mFullDescriptionView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
- onChildViewFocusChanged();
+ public void onClick(View v) {
+ mPipManager.closePip();
+ if (mListener != null) {
+ mListener.onClosed();
+ }
}
});
- mPlayPauseView = findViewById(R.id.play_pause);
- mPlayPauseButtonImageView = (ImageView) findViewById(R.id.play_pause_button);
- mPlayPauseDescriptionTextView = (TextView) findViewById(R.id.play_pause_desc);
- mPlayPauseButtonImageView.setOnClickListener(new View.OnClickListener() {
+ mPlayPauseButtonView = (PipControlButtonView) findViewById(R.id.play_pause_button);
+ mPlayPauseButtonView.setOnFocusChangeListener(mFocusChangeListener);
+ mPlayPauseButtonView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mMediaController == null || mMediaController.getPlaybackState() == null) {
@@ -143,33 +150,6 @@
// View will be updated later in {@link mMediaControllerCallback}
}
});
- mPlayPauseButtonImageView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- mPlayPauseDescriptionTextView.setVisibility(
- hasFocus ? View.VISIBLE : View.INVISIBLE);
- onChildViewFocusChanged();
- }
- });
-
- mCloseButtonView = findViewById(R.id.close_button);
- mCloseDescriptionView = findViewById(R.id.close_desc);
- mCloseButtonView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- mPipManager.closePip();
- if (mListener != null) {
- mListener.onClosed();
- }
- }
- });
- mCloseButtonView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- mCloseDescriptionView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
- onChildViewFocusChanged();
- }
- });
}
@Override
@@ -206,15 +186,15 @@
private void updatePlayPauseView() {
int state = mPipManager.getPlaybackState();
if (state == PLAYBACK_STATE_UNAVAILABLE) {
- mPlayPauseView.setVisibility(View.GONE);
+ mPlayPauseButtonView.setVisibility(View.GONE);
} else {
- mPlayPauseView.setVisibility(View.VISIBLE);
+ mPlayPauseButtonView.setVisibility(View.VISIBLE);
if (state == PLAYBACK_STATE_PLAYING) {
- mPlayPauseButtonImageView.setImageResource(R.drawable.tv_pip_pause_button);
- mPlayPauseDescriptionTextView.setText(R.string.pip_pause);
+ mPlayPauseButtonView.setImageResource(R.drawable.ic_pause_white_24dp);
+ mPlayPauseButtonView.setText(R.string.pip_pause);
} else {
- mPlayPauseButtonImageView.setImageResource(R.drawable.tv_pip_play_button);
- mPlayPauseDescriptionTextView.setText(R.string.pip_play);
+ mPlayPauseButtonView.setImageResource(R.drawable.ic_play_arrow_white_24dp);
+ mPlayPauseButtonView.setText(R.string.pip_play);
}
}
}
@@ -229,7 +209,7 @@
private void onChildViewFocusChanged() {
// At this moment, hasFocus() returns true although there's no focused child.
boolean hasFocus = (mFullButtonView != null && mFullButtonView.isFocused())
- || (mPlayPauseButtonImageView != null && mPlayPauseButtonImageView.isFocused())
+ || (mPlayPauseButtonView != null && mPlayPauseButtonView.isFocused())
|| (mCloseButtonView != null && mCloseButtonView.isFocused());
if (mHasFocus != hasFocus) {
mHasFocus = hasFocus;
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 a445e77..5febb9b 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -35,6 +35,7 @@
import android.os.Handler;
import android.os.RemoteException;
import android.os.SystemProperties;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
@@ -144,6 +145,7 @@
private ComponentName mPipComponentName;
private MediaController mPipMediaController;
private boolean mOnboardingShown;
+ private String[] mLastPackagesResourceGranted;
private final Runnable mResizePinnedStackRunnable = new Runnable() {
@Override
@@ -166,7 +168,7 @@
String[] packageNames = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
int resourceType = intent.getIntExtra(Intent.EXTRA_MEDIA_RESOURCE_TYPE,
INVALID_RESOURCE_TYPE);
- if (mState != STATE_NO_PIP && packageNames != null && packageNames.length > 0
+ if (packageNames != null && packageNames.length > 0
&& resourceType == Intent.EXTRA_MEDIA_RESOURCE_TYPE_VIDEO_CODEC) {
handleMediaResourceGranted(packageNames);
}
@@ -446,41 +448,24 @@
}
private void handleMediaResourceGranted(String[] packageNames) {
- StackInfo fullscreenStack = null;
- try {
- fullscreenStack = mActivityManager.getStackInfo(FULLSCREEN_WORKSPACE_STACK_ID);
- } catch (RemoteException e) {
- Log.e(TAG, "getStackInfo failed", e);
- }
- if (fullscreenStack == null) {
- return;
- }
- int fullscreenTopTaskId = fullscreenStack.taskIds[fullscreenStack.taskIds.length - 1];
- List<RunningTaskInfo> tasks = null;
- try {
- tasks = mActivityManager.getTasks(MAX_RUNNING_TASKS_COUNT, 0);
- } catch (RemoteException e) {
- Log.e(TAG, "getTasks failed", e);
- }
- if (tasks == null) {
- return;
- }
- boolean wasGrantedInFullscreen = false;
- boolean wasGrantedInPip = false;
- for (int i = tasks.size() - 1; i >= 0; --i) {
- RunningTaskInfo task = tasks.get(i);
- for (int j = packageNames.length - 1; j >= 0; --j) {
- if (task.topActivity.getPackageName().equals(packageNames[j])) {
- if (task.id == fullscreenTopTaskId) {
- wasGrantedInFullscreen = true;
- } else if (task.id == mPipTaskId) {
- wasGrantedInPip= true;
+ if (mState == STATE_NO_PIP) {
+ mLastPackagesResourceGranted = packageNames;
+ } else {
+ boolean requestedFromLastPackages = false;
+ if (mLastPackagesResourceGranted != null) {
+ for (String packageName : mLastPackagesResourceGranted) {
+ for (String newPackageName : packageNames) {
+ if (TextUtils.equals(newPackageName, packageName)) {
+ requestedFromLastPackages = true;
+ break;
+ }
}
}
}
- }
- if (wasGrantedInFullscreen && !wasGrantedInPip) {
- closePip();
+ mLastPackagesResourceGranted = packageNames;
+ if (!requestedFromLastPackages) {
+ closePip();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
index 854e09d..542a935 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
@@ -16,10 +16,14 @@
package com.android.systemui.tv.pip;
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
import android.app.Activity;
import android.os.Bundle;
+import android.view.View;
import com.android.systemui.R;
+import com.android.systemui.Interpolators;
/**
* Activity to show the PIP menu to control PIP.
@@ -29,7 +33,9 @@
private final PipManager mPipManager = PipManager.getInstance();
- private PipControlsView mPipControlsView;
+ private Animator mFadeInAnimation;
+ private Animator mFadeOutAnimation;
+ private View mPipControlsView;
private boolean mRestorePipSizeWhenClose;
@Override
@@ -38,8 +44,14 @@
setContentView(R.layout.tv_pip_menu);
mPipManager.addListener(this);
- mPipControlsView = (PipControlsView) findViewById(R.id.pip_controls);
mRestorePipSizeWhenClose = true;
+ mPipControlsView = (PipControlsView) findViewById(R.id.pip_controls);
+ mFadeInAnimation = AnimatorInflater.loadAnimator(
+ this, R.anim.tv_pip_menu_fade_in_animation);
+ mFadeInAnimation.setTarget(mPipControlsView);
+ mFadeOutAnimation = AnimatorInflater.loadAnimator(
+ this, R.anim.tv_pip_menu_fade_out_animation);
+ mFadeOutAnimation.setTarget(mPipControlsView);
}
private void restorePipAndFinish() {
@@ -51,8 +63,15 @@
}
@Override
+ public void onResume() {
+ super.onResume();
+ mFadeInAnimation.start();
+ }
+
+ @Override
public void onPause() {
super.onPause();
+ mFadeOutAnimation.start();
restorePipAndFinish();
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
index 86ceff4..398572a 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
@@ -16,12 +16,15 @@
package com.android.systemui.tv.pip;
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
import android.app.Activity;
-import android.graphics.Rect;
+import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
-import android.util.Log;
import android.view.View;
-import android.view.ViewGroup.LayoutParams;
+import android.widget.ImageView;
import com.android.systemui.R;
@@ -35,29 +38,47 @@
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.tv_pip_onboarding);
- View pipOnboardingView = findViewById(R.id.pip_onboarding);
- View pipOutlineView = findViewById(R.id.pip_outline);
- mPipManager.addListener(this);
- findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
+ findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
- int pipOutlineSpace = getResources().getDimensionPixelSize(R.dimen.tv_pip_bounds_space);
- int screenWidth = getResources().getDisplayMetrics().widthPixels;
- Rect pipBounds = mPipManager.getPipBounds();
- pipOnboardingView.setPadding(
- pipBounds.left - pipOutlineSpace,
- pipBounds.top - pipOutlineSpace,
- screenWidth - pipBounds.right - pipOutlineSpace, 0);
+ mPipManager.addListener(this);
+ }
- // Set width and height for outline view to enclose the PIP.
- LayoutParams lp = pipOutlineView.getLayoutParams();
- lp.width = pipBounds.width() + pipOutlineSpace * 2;
- lp.height = pipBounds.height() + pipOutlineSpace * 2;
- pipOutlineView.setLayoutParams(lp);
+ @Override
+ public void onResume() {
+ super.onResume();
+ AnimatorSet enterAnimator = new AnimatorSet();
+ enterAnimator.playTogether(
+ loadAnimator(R.id.remote, R.anim.tv_pip_onboarding_image_enter_animation),
+ loadAnimator(R.id.remote_button, R.anim.tv_pip_onboarding_image_enter_animation),
+ loadAnimator(R.id.title, R.anim.tv_pip_onboarding_title_enter_animation),
+ loadAnimator(R.id.description,
+ R.anim.tv_pip_onboarding_description_enter_animation),
+ loadAnimator(R.id.button, R.anim.tv_pip_onboarding_button_enter_animation));
+ enterAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ ImageView button = (ImageView) findViewById(R.id.remote_button);
+ ((AnimationDrawable) button.getDrawable()).start();
+ }
+ });
+ enterAnimator.start();
+ }
+
+ private Animator loadAnimator(int viewResId, int animResId) {
+ Animator animator = AnimatorInflater.loadAnimator(this, animResId);
+ animator.setTarget(findViewById(viewResId));
+ return animator;
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ finish();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
index e205ff5..011e159 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
@@ -16,6 +16,8 @@
package com.android.systemui.tv.pip;
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Context;
@@ -50,9 +52,11 @@
private ImageView mGuideButtonPlayPauseImageView;
private final Runnable mHideGuideOverlayRunnable = new Runnable() {
public void run() {
- mGuideOverlayView.setVisibility(View.GONE);
+ mFadeOutAnimation.start();
}
};
+ private Animator mFadeInAnimation;
+ private Animator mFadeOutAnimation;
/**
* Shows PIP overlay UI only if it's not there.
@@ -74,11 +78,18 @@
setContentView(R.layout.tv_pip_overlay);
mGuideOverlayView = findViewById(R.id.guide_overlay);
mPipManager.addListener(this);
+ mFadeInAnimation = AnimatorInflater.loadAnimator(
+ this, R.anim.tv_pip_overlay_fade_in_animation);
+ mFadeInAnimation.setTarget(mGuideOverlayView);
+ mFadeOutAnimation = AnimatorInflater.loadAnimator(
+ this, R.anim.tv_pip_overlay_fade_out_animation);
+ mFadeOutAnimation.setTarget(mGuideOverlayView);
}
@Override
protected void onResume() {
super.onResume();
+ mFadeInAnimation.start();
mHandler.removeCallbacks(mHideGuideOverlayRunnable);
mHandler.postDelayed(mHideGuideOverlayRunnable, SHOW_GUIDE_OVERLAY_VIEW_DURATION_MS);
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java
index 8b8c105..9c806f7 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsControlsView.java
@@ -72,28 +72,20 @@
super.onFinishInflate();
int buttonsFocusGainAnim = R.anim.tv_pip_controls_buttons_in_recents_focus_gain_animation;
- int textFocusGainAnim = R.anim.tv_pip_controls_text_in_recents_focus_gain_animation;
mFocusGainAnimatorSet = new AnimatorSet();
mFocusGainAnimatorSet.playTogether(
loadAnimator(this, R.anim.tv_pip_controls_in_recents_focus_gain_animation),
loadAnimator(mFullButtonView,buttonsFocusGainAnim),
- loadAnimator(mPlayPauseButtonImageView, buttonsFocusGainAnim),
- loadAnimator(mCloseButtonView, buttonsFocusGainAnim),
- loadAnimator(mFullDescriptionView, textFocusGainAnim),
- loadAnimator(mPlayPauseDescriptionTextView, textFocusGainAnim),
- loadAnimator(mCloseDescriptionView, textFocusGainAnim));
+ loadAnimator(mPlayPauseButtonView, buttonsFocusGainAnim),
+ loadAnimator(mCloseButtonView, buttonsFocusGainAnim));
int buttonsFocusLoseAnim = R.anim.tv_pip_controls_buttons_in_recents_focus_lose_animation;
- int textFocusLoseAnim = R.anim.tv_pip_controls_text_in_recents_focus_lose_animation;
mFocusLoseAnimatorSet = new AnimatorSet();
mFocusLoseAnimatorSet.playTogether(
loadAnimator(this, R.anim.tv_pip_controls_in_recents_focus_lose_animation),
loadAnimator(mFullButtonView, buttonsFocusLoseAnim),
- loadAnimator(mPlayPauseButtonImageView, buttonsFocusLoseAnim),
- loadAnimator(mCloseButtonView, buttonsFocusLoseAnim),
- loadAnimator(mFullDescriptionView, textFocusLoseAnim),
- loadAnimator(mPlayPauseDescriptionTextView, textFocusLoseAnim),
- loadAnimator(mCloseDescriptionView, textFocusLoseAnim));
+ loadAnimator(mPlayPauseButtonView, buttonsFocusLoseAnim),
+ loadAnimator(mCloseButtonView, buttonsFocusLoseAnim));
Rect pipBounds = mPipManager.getRecentsFocusedPipBounds();
int pipControlsMarginTop = getContext().getResources().getDimensionPixelSize(
@@ -142,11 +134,8 @@
requestFocus();
setTranslationY(0);
setScaleXY(mFullButtonView, 1);
- setScaleXY(mPlayPauseButtonImageView, 1);
+ setScaleXY(mPlayPauseButtonView, 1);
setScaleXY(mCloseButtonView, 1);
- mFullDescriptionView.setAlpha(1);
- mPlayPauseDescriptionTextView.setAlpha(1);
- mCloseDescriptionView.setAlpha(1);
}
private void setScaleXY(View view, float scale) {
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
index 47cd8e5..d75561b 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipRecentsOverlayManager.java
@@ -16,8 +16,6 @@
package com.android.systemui.tv.pip;
-import android.animation.AnimatorInflater;
-import android.animation.AnimatorSet;
import android.content.Context;
import android.graphics.PixelFormat;
import android.util.Log;
@@ -134,6 +132,7 @@
* @param allowRecentsFocusable {@code true} if Recents can have focus. (i.e. Has a recent task)
*/
public void requestFocus(boolean allowRecentsFocusable) {
+ mRecentsView.setVisibility(allowRecentsFocusable ? View.VISIBLE : View.GONE);
if (!mIsRecentsShown || mIsPipFocusedInRecent) {
return;
}
@@ -143,7 +142,6 @@
mWindowManager.updateViewLayout(mOverlayView, mPipRecentsControlsViewFocusedLayoutParams);
mPipControlsView.requestFocus();
mPipControlsView.startFocusGainAnimation();
- mRecentsView.setVisibility(allowRecentsFocusable ? View.VISIBLE : View.GONE);
}
/**
@@ -152,10 +150,14 @@
* is focused.
* This should be called only by {@link com.android.systemui.recents.tv.RecentsTvActivity}.
*/
- private void clearFocus() {
+ public void clearFocus() {
if (!mIsRecentsShown || !mIsPipFocusedInRecent) {
return;
}
+ if (!mRecentsView.hasFocus()) {
+ // Let mRecentsView's focus listener handle clearFocus().
+ mRecentsView.requestFocus();
+ }
mIsPipFocusedInRecent = false;
mPipManager.resizePinnedStack(STATE_PIP_RECENTS);
mWindowManager.updateViewLayout(mOverlayView, mPipRecentsControlsViewLayoutParams);
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 180d918..2c53e29 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -16,6 +16,7 @@
package com.android.systemui.usb;
+import android.annotation.NonNull;
import android.app.Notification;
import android.app.Notification.Action;
import android.app.NotificationManager;
@@ -97,6 +98,11 @@
public void onDiskScanned(DiskInfo disk, int volumeCount) {
onDiskScannedInternal(disk, volumeCount);
}
+
+ @Override
+ public void onDiskDestroyed(DiskInfo disk) {
+ onDiskDestroyedInternal(disk);
+ }
};
private final BroadcastReceiver mSnoozeReceiver = new BroadcastReceiver() {
@@ -238,6 +244,15 @@
}
}
+ /**
+ * Remove all notifications for a disk when it goes away.
+ *
+ * @param disk The disk that went away.
+ */
+ private void onDiskDestroyedInternal(@NonNull DiskInfo disk) {
+ mNotificationManager.cancelAsUser(disk.getId(), DISK_ID, UserHandle.ALL);
+ }
+
private void onVolumeStateChangedInternal(VolumeInfo vol) {
switch (vol.getType()) {
case VolumeInfo.TYPE_PRIVATE:
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/preloaded-classes b/preloaded-classes
index be645d2..d854769 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -12,6 +12,7 @@
[Landroid.animation.Keyframe;
[Landroid.animation.PropertyValuesHolder;
[Landroid.app.LoaderManagerImpl;
+[Landroid.app.Notification$Action;
[Landroid.content.ContentProviderResult;
[Landroid.content.ContentValues;
[Landroid.content.Intent;
@@ -29,7 +30,6 @@
[Landroid.content.res.Configuration;
[Landroid.content.res.StringBlock;
[Landroid.content.res.XmlBlock;
-[Landroid.database.Cursor;
[Landroid.database.CursorWindow;
[Landroid.database.sqlite.SQLiteConnection$Operation;
[Landroid.database.sqlite.SQLiteConnectionPool$AcquiredConnectionStatus;
@@ -54,7 +54,6 @@
[Landroid.graphics.drawable.GradientDrawable$Orientation;
[Landroid.graphics.drawable.LayerDrawable$ChildDrawable;
[Landroid.graphics.drawable.RippleForeground;
-[Landroid.hardware.display.WifiDisplay;
[Landroid.hardware.soundtrigger.SoundTrigger$ConfidenceLevel;
[Landroid.hardware.soundtrigger.SoundTrigger$Keyphrase;
[Landroid.hardware.soundtrigger.SoundTrigger$KeyphraseRecognitionExtra;
@@ -83,6 +82,10 @@
[Landroid.icu.util.ULocale$Category;
[Landroid.icu.util.ULocale;
[Landroid.media.AudioGain;
+[Landroid.media.MediaCodecInfo$CodecCapabilities;
+[Landroid.media.MediaCodecInfo$CodecProfileLevel;
+[Landroid.media.MediaCodecInfo$Feature;
+[Landroid.media.MediaCodecInfo;
[Landroid.net.Network;
[Landroid.net.NetworkInfo$DetailedState;
[Landroid.net.NetworkInfo$State;
@@ -109,7 +112,6 @@
[Landroid.text.method.TextKeyListener;
[Landroid.text.style.AlignmentSpan;
[Landroid.text.style.CharacterStyle;
-[Landroid.text.style.ClickableSpan;
[Landroid.text.style.LeadingMarginSpan;
[Landroid.text.style.LineBackgroundSpan;
[Landroid.text.style.LineHeightSpan;
@@ -122,12 +124,11 @@
[Landroid.text.style.URLSpan;
[Landroid.text.style.WrapTogetherSpan;
[Landroid.util.LongSparseArray;
-[Landroid.util.Pair;
+[Landroid.util.Range;
[Landroid.util.Rational;
[Landroid.view.Choreographer$CallbackQueue;
[Landroid.view.Display$ColorTransform;
[Landroid.view.Display$Mode;
-[Landroid.view.Display;
[Landroid.view.HandlerActionQueue$HandlerAction;
[Landroid.view.MenuItem;
[Landroid.view.View;
@@ -198,11 +199,13 @@
[Ljava.text.DateFormat$Field;
[Ljava.text.Normalizer$Form;
[Ljava.util.ArrayList;
+[Ljava.util.Comparators$NaturalOrderComparator;
[Ljava.util.Enumeration;
[Ljava.util.Formatter$Flags;
[Ljava.util.Formatter$FormatString;
[Ljava.util.HashMap$HashMapEntry;
[Ljava.util.Hashtable$HashtableEntry;
+[Ljava.util.List;
[Ljava.util.Locale$Category;
[Ljava.util.Locale;
[Ljava.util.Map$Entry;
@@ -216,11 +219,8 @@
[Ljava.util.regex.Pattern;
[Ljavax.crypto.Cipher$InitType;
[Ljavax.crypto.Cipher$NeedToSet;
-[Ljavax.microedition.khronos.egl.EGLConfig;
[Ljavax.net.ssl.KeyManager;
-[Ljavax.net.ssl.SSLSession;
[Ljavax.net.ssl.TrustManager;
-[Ljavax.security.auth.x500.X500Principal;
[Ljavax.security.cert.X509Certificate;
[Llibcore.io.ClassPathURLStreamHandler;
[Llibcore.reflect.AnnotationMember$DefaultValues;
@@ -307,12 +307,10 @@
android.animation.PathKeyframes$1
android.animation.PathKeyframes$2
android.animation.PathKeyframes$FloatKeyframesBase
-android.animation.PathKeyframes$IntKeyframesBase
android.animation.PathKeyframes$SimpleKeyframes
android.animation.PropertyValuesHolder
android.animation.PropertyValuesHolder$FloatPropertyValuesHolder
android.animation.PropertyValuesHolder$IntPropertyValuesHolder
-android.animation.PropertyValuesHolder$PropertyValues
android.animation.RectEvaluator
android.animation.StateListAnimator
android.animation.StateListAnimator$1
@@ -328,7 +326,6 @@
android.app.Activity$HostCallbacks
android.app.ActivityManager
android.app.ActivityManager$MemoryInfo
-android.app.ActivityManager$RecentTaskInfo
android.app.ActivityManager$RunningAppProcessInfo
android.app.ActivityManager$RunningAppProcessInfo$1
android.app.ActivityManager$StackId
@@ -348,7 +345,6 @@
android.app.ActivityThread$ApplicationThread
android.app.ActivityThread$BindServiceData
android.app.ActivityThread$ContextCleanupInfo
-android.app.ActivityThread$CreateBackupAgentData
android.app.ActivityThread$CreateServiceData
android.app.ActivityThread$DropBoxReporter
android.app.ActivityThread$EventLoggingReporter
@@ -381,7 +377,7 @@
android.app.ContextImpl
android.app.ContextImpl$ApplicationContentResolver
android.app.Dialog
-android.app.Dialog$1
+android.app.Dialog$-void__init__android_content_Context_context_int_themeResId_boolean_createContextThemeWrapper_LambdaImpl0
android.app.Dialog$ListenersHandler
android.app.DialogFragment
android.app.DownloadManager
@@ -402,8 +398,6 @@
android.app.IAlarmManager$Stub
android.app.IAlarmManager$Stub$Proxy
android.app.IApplicationThread
-android.app.IBackupAgent
-android.app.IBackupAgent$Stub
android.app.IInstrumentationWatcher
android.app.IInstrumentationWatcher$Stub
android.app.INotificationManager
@@ -415,6 +409,9 @@
android.app.ITransientNotification$Stub
android.app.IUiAutomationConnection
android.app.IUiAutomationConnection$Stub
+android.app.IUiModeManager
+android.app.IUiModeManager$Stub
+android.app.IUiModeManager$Stub$Proxy
android.app.Instrumentation
android.app.IntentReceiverLeaked
android.app.IntentService
@@ -437,16 +434,21 @@
android.app.Notification
android.app.Notification$1
android.app.Notification$Action
+android.app.Notification$Action$1
android.app.Notification$BigTextStyle
android.app.Notification$Builder
+android.app.Notification$BuilderRemoteViews
android.app.Notification$Style
android.app.NotificationManager
+android.app.OnActivityPausedListener
android.app.PendingIntent
android.app.PendingIntent$1
android.app.PendingIntent$CanceledException
android.app.QueuedWork
android.app.ReceiverRestrictedContext
android.app.ResourcesManager
+android.app.ResourcesManager$1
+android.app.ResourcesManager$ActivityResources
android.app.ResultInfo
android.app.ResultInfo$1
android.app.Service
@@ -530,11 +532,15 @@
android.app.SystemServiceRegistry$69
android.app.SystemServiceRegistry$7
android.app.SystemServiceRegistry$70
+android.app.SystemServiceRegistry$71
+android.app.SystemServiceRegistry$72
+android.app.SystemServiceRegistry$73
+android.app.SystemServiceRegistry$74
android.app.SystemServiceRegistry$8
android.app.SystemServiceRegistry$9
android.app.SystemServiceRegistry$CachedServiceFetcher
android.app.SystemServiceRegistry$ServiceFetcher
-android.app.SystemServiceRegistry$StaticOuterContextServiceFetcher
+android.app.SystemServiceRegistry$StaticApplicationContextServiceFetcher
android.app.SystemServiceRegistry$StaticServiceFetcher
android.app.UiModeManager
android.app.WallpaperManager
@@ -542,10 +548,9 @@
android.app.admin.IDevicePolicyManager
android.app.admin.IDevicePolicyManager$Stub
android.app.admin.IDevicePolicyManager$Stub$Proxy
-android.app.backup.BackupAgent
-android.app.backup.BackupAgent$BackupServiceBinder
-android.app.backup.BackupAgent$SharedPrefsSynchronizer
-android.app.backup.BackupAgentHelper
+android.app.admin.SecurityLog
+android.app.admin.SecurityLog$SecurityEvent
+android.app.admin.SecurityLog$SecurityEvent$1
android.app.backup.BackupDataInput
android.app.backup.BackupDataInput$EntityHeader
android.app.backup.BackupDataOutput
@@ -554,9 +559,6 @@
android.app.backup.FileBackupHelperBase
android.app.backup.FullBackup
android.app.backup.FullBackupDataOutput
-android.app.backup.IBackupManager
-android.app.backup.IBackupManager$Stub
-android.app.backup.IBackupManager$Stub$Proxy
android.app.job.JobScheduler
android.app.trust.ITrustManager
android.app.trust.ITrustManager$Stub
@@ -566,9 +568,6 @@
android.app.usage.UsageStatsManager
android.appwidget.AppWidgetManager
android.appwidget.AppWidgetProvider
-android.auditing.SecurityLog
-android.auditing.SecurityLog$SecurityEvent
-android.auditing.SecurityLog$SecurityEvent$1
android.bluetooth.BluetoothAdapter
android.bluetooth.BluetoothAdapter$1
android.bluetooth.BluetoothManager
@@ -585,6 +584,7 @@
android.content.ActivityNotFoundException
android.content.BroadcastReceiver
android.content.BroadcastReceiver$PendingResult
+android.content.BroadcastReceiver$PendingResult$1
android.content.ClipData
android.content.ClipData$1
android.content.ClipData$Item
@@ -600,7 +600,6 @@
android.content.ContentProviderClient
android.content.ContentProviderNative
android.content.ContentProviderOperation
-android.content.ContentProviderOperation$Builder
android.content.ContentProviderProxy
android.content.ContentProviderResult
android.content.ContentResolver
@@ -637,7 +636,6 @@
android.content.IntentSender
android.content.IntentSender$SendIntentException
android.content.OperationApplicationException
-android.content.PeriodicSync
android.content.RestrictionsManager
android.content.ServiceConnection
android.content.SharedPreferences
@@ -646,7 +644,6 @@
android.content.SyncContext
android.content.SyncRequest
android.content.SyncRequest$1
-android.content.SyncRequest$Builder
android.content.SyncResult
android.content.SyncResult$1
android.content.SyncStats
@@ -693,6 +690,7 @@
android.content.pm.ResolveInfo$1
android.content.pm.ServiceInfo
android.content.pm.ServiceInfo$1
+android.content.pm.ShortcutManager
android.content.pm.Signature
android.content.pm.Signature$1
android.content.pm.UserInfo
@@ -721,6 +719,8 @@
android.content.res.Resources$NotFoundException
android.content.res.Resources$Theme
android.content.res.Resources$ThemeKey
+android.content.res.ResourcesImpl
+android.content.res.ResourcesImpl$ThemeImpl
android.content.res.ResourcesKey
android.content.res.StringBlock
android.content.res.StringBlock$StyleIDs
@@ -762,7 +762,6 @@
android.database.IContentObserver$Stub$Proxy
android.database.MatrixCursor
android.database.MatrixCursor$RowBuilder
-android.database.MergeCursor
android.database.Observable
android.database.SQLException
android.database.sqlite.DatabaseObjectNotClosedException
@@ -775,7 +774,6 @@
android.database.sqlite.SQLiteConnectionPool
android.database.sqlite.SQLiteConnectionPool$AcquiredConnectionStatus
android.database.sqlite.SQLiteConnectionPool$ConnectionWaiter
-android.database.sqlite.SQLiteConstraintException
android.database.sqlite.SQLiteCursor
android.database.sqlite.SQLiteCursorDriver
android.database.sqlite.SQLiteCustomFunction
@@ -807,7 +805,6 @@
android.ddm.DdmHandleThread
android.ddm.DdmHandleViewDebug
android.ddm.DdmRegister
-android.graphics.AvoidXfermode
android.graphics.Bitmap
android.graphics.Bitmap$1
android.graphics.Bitmap$CompressFormat
@@ -820,10 +817,10 @@
android.graphics.Camera
android.graphics.Canvas
android.graphics.Canvas$EdgeType
+android.graphics.Canvas$NoImagePreloadHolder
android.graphics.CanvasProperty
android.graphics.Color
android.graphics.ColorFilter
-android.graphics.ColorMatrix
android.graphics.ColorMatrixColorFilter
android.graphics.ComposePathEffect
android.graphics.ComposeShader
@@ -859,6 +856,7 @@
android.graphics.Paint$FontMetrics
android.graphics.Paint$FontMetricsInt
android.graphics.Paint$Join
+android.graphics.Paint$NoImagePreloadHolder
android.graphics.Paint$Style
android.graphics.PaintFlagsDrawFilter
android.graphics.Path
@@ -869,7 +867,6 @@
android.graphics.PathMeasure
android.graphics.Picture
android.graphics.PixelFormat
-android.graphics.PixelXorXfermode
android.graphics.Point
android.graphics.Point$1
android.graphics.PointF
@@ -903,11 +900,14 @@
android.graphics.drawable.Animatable2
android.graphics.drawable.AnimatedStateListDrawable
android.graphics.drawable.AnimatedStateListDrawable$AnimatedStateListState
+android.graphics.drawable.AnimatedStateListDrawable$Transition
android.graphics.drawable.AnimatedVectorDrawable
android.graphics.drawable.AnimatedVectorDrawable$1
android.graphics.drawable.AnimatedVectorDrawable$AnimatedVectorDrawableState
android.graphics.drawable.AnimatedVectorDrawable$AnimatedVectorDrawableState$PendingAnimator
+android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimator
android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT
+android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorUI
android.graphics.drawable.AnimationDrawable
android.graphics.drawable.AnimationDrawable$AnimationState
android.graphics.drawable.BitmapDrawable
@@ -976,12 +976,14 @@
android.hardware.Camera$Face
android.hardware.ConsumerIrManager
android.hardware.Sensor
+android.hardware.SensorEvent
android.hardware.SensorEventListener
android.hardware.SensorManager
android.hardware.SerialManager
android.hardware.SerialPort
android.hardware.SystemSensorManager
android.hardware.SystemSensorManager$BaseEventQueue
+android.hardware.SystemSensorManager$SensorEventQueue
android.hardware.camera2.CameraCharacteristics$Key
android.hardware.camera2.CameraManager
android.hardware.camera2.CaptureRequest$Key
@@ -1000,12 +1002,6 @@
android.hardware.display.IDisplayManager$Stub$Proxy
android.hardware.display.IDisplayManagerCallback
android.hardware.display.IDisplayManagerCallback$Stub
-android.hardware.display.WifiDisplay
-android.hardware.display.WifiDisplay$1
-android.hardware.display.WifiDisplaySessionInfo
-android.hardware.display.WifiDisplaySessionInfo$1
-android.hardware.display.WifiDisplayStatus
-android.hardware.display.WifiDisplayStatus$1
android.hardware.fingerprint.FingerprintManager
android.hardware.hdmi.HdmiControlManager
android.hardware.input.IInputDevicesChangedListener
@@ -1021,6 +1017,10 @@
# android.hardware.location.ActivityRecognitionHardware
# android.hardware.location.IActivityRecognitionHardware
# android.hardware.location.IActivityRecognitionHardware$Stub
+android.hardware.location.ContextHubManager
+android.hardware.location.ContextHubService
+android.hardware.location.IContextHubService
+android.hardware.location.IContextHubService$Stub
android.hardware.radio.RadioManager
android.hardware.radio.RadioManager$AmBandConfig
android.hardware.radio.RadioManager$AmBandConfig$1
@@ -1046,6 +1046,7 @@
android.hardware.soundtrigger.SoundTrigger$ConfidenceLevel
android.hardware.soundtrigger.SoundTrigger$ConfidenceLevel$1
android.hardware.soundtrigger.SoundTrigger$GenericRecognitionEvent
+android.hardware.soundtrigger.SoundTrigger$GenericRecognitionEvent$1
android.hardware.soundtrigger.SoundTrigger$GenericSoundModel
android.hardware.soundtrigger.SoundTrigger$Keyphrase
android.hardware.soundtrigger.SoundTrigger$Keyphrase$1
@@ -1070,7 +1071,6 @@
android.hardware.usb.IUsbManager$Stub$Proxy
android.hardware.usb.UsbDevice
android.hardware.usb.UsbDeviceConnection
-android.hardware.usb.UsbInterface
android.hardware.usb.UsbManager
android.hardware.usb.UsbRequest
android.icu.impl.BMPSet
@@ -1396,6 +1396,7 @@
android.media.AudioDevicePort
android.media.AudioDevicePortConfig
android.media.AudioFormat
+android.media.AudioFormat$1
android.media.AudioGain
android.media.AudioGainConfig
android.media.AudioHandle
@@ -1412,8 +1413,6 @@
android.media.AudioPortConfig
android.media.AudioPortEventHandler
android.media.AudioRecord
-android.media.AudioRoutesInfo
-android.media.AudioRoutesInfo$1
android.media.AudioRouting
android.media.AudioSystem
android.media.AudioTimestamp
@@ -1425,21 +1424,13 @@
android.media.ExifInterface
android.media.IAudioFocusDispatcher
android.media.IAudioFocusDispatcher$Stub
-android.media.IAudioRoutesObserver
-android.media.IAudioRoutesObserver$Stub
android.media.IAudioService
android.media.IAudioService$Stub
android.media.IAudioService$Stub$Proxy
android.media.IMediaHTTPConnection
android.media.IMediaHTTPConnection$Stub
-android.media.IMediaRouterClient
-android.media.IMediaRouterClient$Stub
-android.media.IMediaRouterService
-android.media.IMediaRouterService$Stub
android.media.IRecordingConfigDispatcher
android.media.IRecordingConfigDispatcher$Stub
-android.media.IRemoteVolumeObserver
-android.media.IRemoteVolumeObserver$Stub
android.media.Image
android.media.ImageReader
android.media.ImageReader$SurfaceImage
@@ -1447,10 +1438,18 @@
android.media.ImageWriter$WriterSurfaceImage
android.media.JetPlayer
android.media.MediaCodec
+android.media.MediaCodecInfo
+android.media.MediaCodecInfo$AudioCapabilities
+android.media.MediaCodecInfo$CodecCapabilities
+android.media.MediaCodecInfo$CodecProfileLevel
+android.media.MediaCodecInfo$EncoderCapabilities
+android.media.MediaCodecInfo$Feature
+android.media.MediaCodecInfo$VideoCapabilities
android.media.MediaCodecList
android.media.MediaCrypto
android.media.MediaDrm
android.media.MediaExtractor
+android.media.MediaFormat
android.media.MediaHTTPConnection
android.media.MediaMetadataRetriever
android.media.MediaMuxer
@@ -1461,17 +1460,6 @@
android.media.MediaPlayer$OnSeekCompleteListener
android.media.MediaRecorder
android.media.MediaRouter
-android.media.MediaRouter$Callback
-android.media.MediaRouter$RouteCategory
-android.media.MediaRouter$RouteInfo
-android.media.MediaRouter$RouteInfo$1
-android.media.MediaRouter$Static
-android.media.MediaRouter$Static$1
-android.media.MediaRouter$Static$Client
-android.media.MediaRouter$VolumeChangeReceiver
-android.media.MediaRouter$WifiDisplayStatusChangedReceiver
-android.media.MediaRouterClientState
-android.media.MediaRouterClientState$1
android.media.MediaScanner
android.media.MediaSync
android.media.PlaybackParams
@@ -1479,9 +1467,10 @@
android.media.RemoteDisplay
android.media.ResampleInputStream
android.media.SubtitleController$Listener
-android.media.ThumbnailUtils
android.media.ToneGenerator
-android.media.audiofx.AcousticEchoCanceler
+android.media.Utils
+android.media.Utils$1
+android.media.Utils$2
android.media.audiofx.AudioEffect
android.media.audiopolicy.AudioMix
android.media.audiopolicy.AudioMixingRule
@@ -1504,13 +1493,13 @@
android.net.ConnectivityManager
android.net.ConnectivityManager$CallbackHandler
android.net.ConnectivityManager$NetworkCallback
+android.net.ConnectivityThread
android.net.Credentials
-android.net.DhcpResults
-android.net.DhcpResults$1
android.net.EthernetManager
android.net.IConnectivityManager
android.net.IConnectivityManager$Stub
android.net.IConnectivityManager$Stub$Proxy
+android.net.INetworkPolicyManager
android.net.IpPrefix
android.net.IpPrefix$1
android.net.LinkAddress
@@ -1545,8 +1534,6 @@
android.net.SSLCertificateSocketFactory
android.net.SSLCertificateSocketFactory$1
android.net.SSLSessionCache
-android.net.StaticIpConfiguration
-android.net.StaticIpConfiguration$1
android.net.TrafficStats
android.net.Uri
android.net.Uri$1
@@ -1584,10 +1571,16 @@
android.nfc.INfcAdapter$Stub$Proxy
android.nfc.INfcCardEmulation
android.nfc.INfcCardEmulation$Stub
+android.nfc.INfcCardEmulation$Stub$Proxy
android.nfc.INfcFCardEmulation
android.nfc.INfcFCardEmulation$Stub
+android.nfc.INfcFCardEmulation$Stub$Proxy
android.nfc.INfcTag
android.nfc.INfcTag$Stub
+android.nfc.INfcTag$Stub$Proxy
+android.nfc.NfcActivityManager
+android.nfc.NfcAdapter
+android.nfc.NfcAdapter$1
android.nfc.NfcManager
android.opengl.EGL14
android.opengl.EGLConfig
@@ -1631,9 +1624,8 @@
android.os.CancellationSignal$OnCancelListener
android.os.CancellationSignal$Transport
android.os.ConditionVariable
-android.os.CpuUsageInfo
-android.os.CpuUsageInfo$1
android.os.DeadObjectException
+android.os.DeadSystemException
android.os.Debug
android.os.Debug$MemoryInfo
android.os.Debug$MemoryInfo$1
@@ -1665,6 +1657,8 @@
android.os.IUserManager
android.os.IUserManager$Stub
android.os.IUserManager$Stub$Proxy
+android.os.IVibratorService
+android.os.IVibratorService$Stub
android.os.Looper
android.os.MemoryFile
android.os.Message
@@ -1679,10 +1673,13 @@
android.os.ParcelFileDescriptor
android.os.ParcelFileDescriptor$1
android.os.ParcelFileDescriptor$AutoCloseInputStream
+android.os.ParcelFileDescriptor$AutoCloseOutputStream
android.os.ParcelUuid
android.os.Parcelable
android.os.Parcelable$ClassLoaderCreator
android.os.Parcelable$Creator
+android.os.ParcelableParcel
+android.os.ParcelableParcel$1
android.os.PatternMatcher
android.os.PatternMatcher$1
android.os.PersistableBundle
@@ -1691,6 +1688,7 @@
android.os.PowerManager$WakeLock
android.os.PowerManager$WakeLock$1
android.os.Process
+android.os.RecoverySystem
android.os.RemoteException
android.os.ResultReceiver
android.os.SELinux
@@ -1726,24 +1724,26 @@
android.os.StrictMode$VmPolicy$Builder
android.os.SystemClock
android.os.SystemProperties
+android.os.SystemVibrator
android.os.Trace
android.os.Trace$1
-android.os.TransactionTooLargeException
android.os.UEventObserver
android.os.UserHandle
android.os.UserHandle$1
android.os.UserManager
android.os.Vibrator
android.os.ZygoteStartFailedEx
+android.os.health.SystemHealthManager
android.os.storage.IMountService
android.os.storage.IMountService$Stub
android.os.storage.IMountService$Stub$Proxy
+android.os.storage.IObbActionListener
+android.os.storage.IObbActionListener$Stub
android.os.storage.StorageManager
+android.os.storage.StorageManager$ObbActionListener
android.os.storage.StorageVolume
android.os.storage.StorageVolume$1
-android.preference.Preference$OnPreferenceChangeListener
android.preference.PreferenceActivity
-android.preference.PreferenceFragment
android.preference.PreferenceFragment$OnPreferenceStartFragmentCallback
android.preference.PreferenceManager
android.preference.PreferenceManager$OnPreferenceTreeClickListener
@@ -1836,7 +1836,6 @@
android.system.UnixSocketAddress
android.telecom.TelecomManager
android.telephony.CarrierConfigManager
-android.telephony.PhoneNumberUtils
android.telephony.Rlog
android.telephony.SubscriptionManager
android.telephony.TelephonyManager
@@ -1852,12 +1851,15 @@
android.text.GetChars
android.text.GraphicsOperations
android.text.Html
+android.text.Html$HtmlParser
+android.text.HtmlToSpannedConverter
android.text.Hyphenator
android.text.InputFilter
android.text.InputType
android.text.Layout
android.text.Layout$Alignment
android.text.Layout$Directions
+android.text.Layout$Ellipsizer
android.text.MeasuredText
android.text.NoCopySpan
android.text.NoCopySpan$Concrete
@@ -1916,7 +1918,6 @@
android.text.method.SingleLineTransformationMethod
android.text.method.TextKeyListener
android.text.method.TextKeyListener$Capitalize
-android.text.method.Touch
android.text.method.TransformationMethod
android.text.method.TransformationMethod2
android.text.style.AlignmentSpan
@@ -1937,6 +1938,7 @@
android.text.style.StyleSpan
android.text.style.SuggestionSpan
android.text.style.TabStopSpan
+android.text.style.TextAppearanceSpan
android.text.style.URLSpan
android.text.style.UnderlineSpan
android.text.style.UpdateAppearance
@@ -1985,7 +1987,6 @@
android.util.EventLog$Event
android.util.FloatProperty
android.util.IntProperty
-android.util.JsonReader
android.util.LocaleList
android.util.LocaleList$1
android.util.Log
@@ -1993,7 +1994,6 @@
android.util.Log$ImmediateLogWriter
android.util.Log$TerribleFailureHandler
android.util.LogPrinter
-android.util.LongArray
android.util.LongSparseArray
android.util.LongSparseLongArray
android.util.LruCache
@@ -2006,15 +2006,16 @@
android.util.Pair
android.util.PathParser
android.util.PathParser$PathData
-android.util.Patterns
android.util.Pools$Pool
android.util.Pools$SimplePool
android.util.Pools$SynchronizedPool
android.util.Printer
android.util.Property
+android.util.Range
android.util.Rational
android.util.Singleton
android.util.Size
+android.util.SizeF
android.util.Slog
android.util.SparseArray
android.util.SparseBooleanArray
@@ -2031,6 +2032,7 @@
android.view.AbsSavedState$2
android.view.ActionMode
android.view.ActionMode$Callback
+android.view.ActionMode$Callback2
android.view.ActionProvider
android.view.ActionProvider$SubUiVisibilityListener
android.view.Choreographer
@@ -2135,7 +2137,6 @@
android.view.RenderNode
android.view.RenderNodeAnimator
android.view.RenderNodeAnimator$1
-android.view.RenderNodeAnimatorSetHelper
android.view.SearchEvent
android.view.SoundEffectConstants
android.view.SubMenu
@@ -2151,6 +2152,7 @@
android.view.SurfaceSession
android.view.SurfaceView
android.view.TextureView
+android.view.TextureView$SurfaceTextureListener
android.view.ThreadedRenderer
android.view.ThreadedRenderer$HardwareDrawCallbacks
android.view.ThreadedRenderer$ProcessInitializer
@@ -2174,6 +2176,7 @@
android.view.View$AttachInfo$Callbacks
android.view.View$BaseSavedState
android.view.View$BaseSavedState$1
+android.view.View$CheckForLongPress
android.view.View$CheckForTap
android.view.View$ForegroundInfo
android.view.View$ListenerInfo
@@ -2258,10 +2261,10 @@
android.view.WindowCallbacks
android.view.WindowContentFrameStats
android.view.WindowContentFrameStats$1
-android.view.WindowId
android.view.WindowInsets
android.view.WindowLeaked
android.view.WindowManager
+android.view.WindowManager$BadTokenException
android.view.WindowManager$LayoutParams
android.view.WindowManager$LayoutParams$1
android.view.WindowManagerGlobal
@@ -2280,6 +2283,7 @@
android.view.accessibility.AccessibilityRecord
android.view.accessibility.CaptioningManager
android.view.accessibility.CaptioningManager$1
+android.view.accessibility.CaptioningManager$CaptionStyle
android.view.accessibility.CaptioningManager$CaptioningChangeListener
android.view.accessibility.CaptioningManager$MyContentObserver
android.view.accessibility.IAccessibilityManager
@@ -2295,6 +2299,7 @@
android.view.animation.Animation$2
android.view.animation.Animation$3
android.view.animation.Animation$AnimationListener
+android.view.animation.Animation$Description
android.view.animation.AnimationSet
android.view.animation.AnimationUtils
android.view.animation.BaseInterpolator
@@ -2316,6 +2321,7 @@
android.view.inputmethod.ExtractedText
android.view.inputmethod.ExtractedText$1
android.view.inputmethod.InputConnection
+android.view.inputmethod.InputConnectionInspector
android.view.inputmethod.InputMethodManager
android.view.inputmethod.InputMethodManager$1
android.view.inputmethod.InputMethodManager$ControlledInputConnectionWrapper
@@ -2323,15 +2329,17 @@
android.view.inputmethod.InputMethodManager$H
android.view.inputmethod.InputMethodManager$ImeInputEventSender
android.view.inputmethod.InputMethodManager$PendingEvent
-android.view.inputmethod.InputMethodSubtype
android.view.textservice.SpellCheckerSession$SpellCheckerSessionListener
android.view.textservice.SpellCheckerSubtype
android.view.textservice.SpellCheckerSubtype$1
android.view.textservice.TextServicesManager
+android.webkit.IWebViewUpdateService
+android.webkit.IWebViewUpdateService$Stub
android.webkit.MimeTypeMap
android.webkit.URLUtil
android.webkit.WebSettings
android.webkit.WebView
+android.webkit.WebViewClient
android.webkit.WebViewFactory
android.webkit.WebViewFactory$MissingWebViewPackageException
android.widget.AbsListView
@@ -2348,6 +2356,7 @@
android.widget.AbsListView$WindowRunnnable
android.widget.AbsSeekBar
android.widget.AbsSpinner
+android.widget.AbsSpinner$RecycleBin
android.widget.AbsoluteLayout
android.widget.ActionMenuPresenter
android.widget.ActionMenuPresenter$1
@@ -2362,13 +2371,9 @@
android.widget.AdapterView
android.widget.AdapterView$AdapterDataSetObserver
android.widget.AdapterView$OnItemClickListener
-android.widget.AdapterView$OnItemLongClickListener
android.widget.AdapterView$OnItemSelectedListener
android.widget.ArrayAdapter
android.widget.AutoCompleteTextView
-android.widget.AutoCompleteTextView$DropDownItemClickListener
-android.widget.AutoCompleteTextView$MyWatcher
-android.widget.AutoCompleteTextView$PassThroughClickListener
android.widget.BaseAdapter
android.widget.Button
android.widget.CheckBox
@@ -2381,15 +2386,17 @@
android.widget.Editor
android.widget.Editor$1
android.widget.Editor$2
-android.widget.Editor$3
android.widget.Editor$Blink
android.widget.Editor$CursorAnchorInfoNotifier
+android.widget.Editor$CursorController
android.widget.Editor$EditOperation
android.widget.Editor$EditOperation$1
android.widget.Editor$InputContentType
android.widget.Editor$InputMethodState
+android.widget.Editor$InsertionPointCursorController
android.widget.Editor$PositionListener
android.widget.Editor$ProcessTextIntentActionsHandler
+android.widget.Editor$SelectionModifierCursorController
android.widget.Editor$SpanController
android.widget.Editor$SuggestionHelper
android.widget.Editor$SuggestionHelper$SuggestionSpanComparator
@@ -2439,6 +2446,19 @@
android.widget.RelativeLayout$DependencyGraph$Node
android.widget.RelativeLayout$LayoutParams
android.widget.RemoteViews
+android.widget.RemoteViews$1
+android.widget.RemoteViews$2
+android.widget.RemoteViews$3
+android.widget.RemoteViews$Action
+android.widget.RemoteViews$ActionException
+android.widget.RemoteViews$BitmapCache
+android.widget.RemoteViews$LayoutParamAction
+android.widget.RemoteViews$MemoryUsageCounter
+android.widget.RemoteViews$MutablePair
+android.widget.RemoteViews$OnClickHandler
+android.widget.RemoteViews$ReflectionAction
+android.widget.RemoteViews$RuntimeAction
+android.widget.RemoteViews$SetDrawableParameters
android.widget.RemoteViewsAdapter$RemoteAdapterConnectionCallback
android.widget.RtlSpacingHelper
android.widget.ScrollBarDrawable
@@ -2451,7 +2471,10 @@
android.widget.SpellChecker
android.widget.SpellChecker$SpellParser
android.widget.Spinner
+android.widget.Spinner$SpinnerPopup
android.widget.SpinnerAdapter
+android.widget.Switch
+android.widget.Switch$1
android.widget.TextView
android.widget.TextView$3
android.widget.TextView$BufferType
@@ -2460,6 +2483,7 @@
android.widget.TextView$Drawables
android.widget.TextView$OnEditorActionListener
android.widget.TextView$SavedState
+android.widget.TextView$SavedState$1
android.widget.ThemedSpinnerAdapter
android.widget.Toast
android.widget.Toast$TN
@@ -2470,7 +2494,6 @@
android.widget.Toolbar$2
android.widget.Toolbar$ExpandedActionViewMenuPresenter
android.widget.Toolbar$LayoutParams
-android.widget.ViewAnimator
android.widget.WrapperListAdapter
com.android.dex.Annotation
com.android.dex.ClassData
@@ -2511,9 +2534,10 @@
com.android.internal.app.IAppOpsService
com.android.internal.app.IAppOpsService$Stub
com.android.internal.app.IAppOpsService$Stub$Proxy
+com.android.internal.app.IBatteryStats
+com.android.internal.app.IBatteryStats$Stub
com.android.internal.app.IVoiceInteractor
com.android.internal.app.IVoiceInteractor$Stub
-com.android.internal.app.WindowDecorActionBar
com.android.internal.appwidget.IAppWidgetService
com.android.internal.appwidget.IAppWidgetService$Stub
com.android.internal.appwidget.IAppWidgetService$Stub$Proxy
@@ -2521,6 +2545,8 @@
com.android.internal.content.ReferrerIntent
com.android.internal.content.ReferrerIntent$1
com.android.internal.inputmethod.InputMethodUtils
+com.android.internal.inputmethod.InputMethodUtils$1
+com.android.internal.inputmethod.LocaleUtils$LocaleExtractor
com.android.internal.logging.AndroidConfig
com.android.internal.logging.AndroidHandler
com.android.internal.logging.AndroidHandler$1
@@ -2575,6 +2601,9 @@
com.android.internal.util.FastXmlSerializer
com.android.internal.util.GrowingArrayUtils
com.android.internal.util.LineBreakBufferedWriter
+com.android.internal.util.MessageUtils
+com.android.internal.util.NotificationColorUtil
+com.android.internal.util.NotificationColorUtil$ColorUtilsFromCompat
com.android.internal.util.Preconditions
com.android.internal.util.VirtualRefBasePtr
com.android.internal.util.XmlUtils
@@ -2613,13 +2642,9 @@
com.android.internal.view.menu.MenuPresenter$Callback
com.android.internal.view.menu.MenuView
com.android.internal.view.menu.ShowableListMenu
-com.android.internal.widget.ActionBarOverlayLayout$ActionBarVisibilityCallback
-com.android.internal.widget.AlertDialogLayout
com.android.internal.widget.BackgroundFallback
-com.android.internal.widget.ButtonBarLayout
com.android.internal.widget.DecorContentParent
com.android.internal.widget.DecorToolbar
-com.android.internal.widget.DialogTitle
com.android.internal.widget.EditableInputConnection
com.android.internal.widget.ScrollBarUtils
com.android.internal.widget.ToolbarWidgetWrapper
@@ -2884,7 +2909,6 @@
dalvik.system.CloseGuard$DefaultReporter
dalvik.system.CloseGuard$Reporter
dalvik.system.DalvikLogHandler
-dalvik.system.DalvikLogging
dalvik.system.DexClassLoader
dalvik.system.DexFile
dalvik.system.DexFile$DFEnum
@@ -2911,6 +2935,7 @@
java.io.ByteArrayOutputStream
java.io.CharArrayWriter
java.io.Closeable
+java.io.Console
java.io.DataInput
java.io.DataInputStream
java.io.DataOutput
@@ -2922,15 +2947,14 @@
java.io.Externalizable
java.io.File
java.io.File$PathStatus
-java.io.File$TempDirectory
java.io.FileDescriptor
+java.io.FileFilter
java.io.FileInputStream
java.io.FileInputStream$UseManualSkipException
java.io.FileNotFoundException
java.io.FileOutputStream
java.io.FileReader
java.io.FileSystem
-java.io.FileWriter
java.io.FilenameFilter
java.io.FilterInputStream
java.io.FilterOutputStream
@@ -2941,7 +2965,6 @@
java.io.InputStreamReader
java.io.InterruptedIOException
java.io.InvalidObjectException
-java.io.NotSerializableException
java.io.ObjectInput
java.io.ObjectInputStream
java.io.ObjectInputStream$BlockDataInputStream
@@ -3013,6 +3036,7 @@
java.lang.EnumConstantNotPresentException
java.lang.Error
java.lang.Exception
+java.lang.ExceptionInInitializerError
java.lang.Float
java.lang.FloatingDecimal
java.lang.FloatingDecimal$1
@@ -3056,7 +3080,6 @@
java.lang.RuntimeException
java.lang.RuntimePermission
java.lang.SecurityException
-java.lang.SecurityManager
java.lang.Short
java.lang.Short$ShortCache
java.lang.Shutdown
@@ -3133,7 +3156,6 @@
java.math.BigInt
java.math.BigInteger
java.math.BitLevel
-java.math.Multiplication
java.math.NativeBN
java.math.RoundingMode
java.net.AbstractPlainDatagramSocketImpl
@@ -3260,22 +3282,18 @@
java.security.AlgorithmParameters
java.security.AlgorithmParametersSpi
java.security.BasicPermission
-java.security.BasicPermissionCollection
java.security.CryptoPrimitive
java.security.GeneralSecurityException
java.security.Guard
java.security.InvalidAlgorithmParameterException
java.security.InvalidKeyException
-java.security.InvalidParameterException
java.security.Key
java.security.KeyException
java.security.KeyFactory
java.security.KeyFactorySpi
java.security.KeyManagementException
-java.security.KeyPair
java.security.KeyStore
java.security.KeyStore$1
-java.security.KeyStore$LoadStoreParameter
java.security.KeyStoreException
java.security.KeyStoreSpi
java.security.MessageDigest
@@ -3285,6 +3303,7 @@
java.security.NoSuchProviderException
java.security.Permission
java.security.PermissionCollection
+java.security.Permissions
java.security.Principal
java.security.PrivateKey
java.security.PrivilegedAction
@@ -3332,7 +3351,6 @@
java.security.cert.PKIXRevocationChecker
java.security.cert.PolicyNode
java.security.cert.TrustAnchor
-java.security.cert.X509CRL
java.security.cert.X509CertSelector
java.security.cert.X509Certificate
java.security.cert.X509Extension
@@ -3342,7 +3360,6 @@
java.security.interfaces.ECPrivateKey
java.security.interfaces.ECPublicKey
java.security.interfaces.RSAKey
-java.security.interfaces.RSAPrivateCrtKey
java.security.interfaces.RSAPrivateKey
java.security.interfaces.RSAPublicKey
java.security.spec.AlgorithmParameterSpec
@@ -3351,19 +3368,14 @@
java.security.spec.ECFieldFp
java.security.spec.ECParameterSpec
java.security.spec.ECPoint
-java.security.spec.ECPrivateKeySpec
java.security.spec.ECPublicKeySpec
java.security.spec.EllipticCurve
java.security.spec.EncodedKeySpec
java.security.spec.InvalidKeySpecException
java.security.spec.InvalidParameterSpecException
java.security.spec.KeySpec
-java.security.spec.PKCS8EncodedKeySpec
-java.security.spec.RSAPrivateCrtKeySpec
-java.security.spec.RSAPrivateKeySpec
java.security.spec.RSAPublicKeySpec
java.security.spec.X509EncodedKeySpec
-java.sql.Timestamp
java.text.AttributedCharacterIterator$Attribute
java.text.CalendarBuilder
java.text.Collator
@@ -3401,7 +3413,9 @@
java.util.AbstractSequentialList
java.util.AbstractSet
java.util.ArrayDeque
+java.util.ArrayDeque$DeqIterator
java.util.ArrayList
+java.util.ArrayList$ArrayListSpliterator
java.util.ArrayList$Itr
java.util.ArrayList$ListItr
java.util.ArrayList$SubList
@@ -3414,6 +3428,7 @@
java.util.Collections
java.util.Collections$1
java.util.Collections$2
+java.util.Collections$3
java.util.Collections$AsLIFOQueue
java.util.Collections$CheckedCollection
java.util.Collections$CheckedList
@@ -3456,6 +3471,14 @@
java.util.Collections$UnmodifiableSortedSet
java.util.ComparableTimSort
java.util.Comparator
+java.util.Comparator$-java_util_Comparator_comparingDouble_java_util_function_ToDoubleFunction_keyExtractor_LambdaImpl0
+java.util.Comparator$-java_util_Comparator_comparingInt_java_util_function_ToIntFunction_keyExtractor_LambdaImpl0
+java.util.Comparator$-java_util_Comparator_comparingLong_java_util_function_ToLongFunction_keyExtractor_LambdaImpl0
+java.util.Comparator$-java_util_Comparator_comparing_java_util_function_Function_keyExtractor_LambdaImpl0
+java.util.Comparator$-java_util_Comparator_comparing_java_util_function_Function_keyExtractor_java_util_Comparator_keyComparator_LambdaImpl0
+java.util.Comparator$-java_util_Comparator_thenComparing_java_util_Comparator_other_LambdaImpl0
+java.util.Comparators$NaturalOrderComparator
+java.util.Comparators$NullComparator
java.util.ConcurrentModificationException
java.util.Currency
java.util.Date
@@ -3464,7 +3487,6 @@
java.util.DualPivotQuicksort
java.util.EnumMap
java.util.EnumMap$1
-java.util.EnumMap$EnumMapIterator
java.util.EnumSet
java.util.Enumeration
java.util.EventListener
@@ -3497,8 +3519,6 @@
java.util.Hashtable$KeySet
java.util.Hashtable$ValueCollection
java.util.IdentityHashMap
-java.util.IdentityHashMap$EntryIterator
-java.util.IdentityHashMap$EntrySet
java.util.IdentityHashMap$IdentityHashMapIterator
java.util.IdentityHashMap$KeySet
java.util.IllegalFormatException
@@ -3538,7 +3558,6 @@
java.util.RandomAccess
java.util.RandomAccessSubList
java.util.RegularEnumSet
-java.util.RegularEnumSet$EnumSetIterator
java.util.ResourceBundle
java.util.ResourceBundle$1
java.util.ResourceBundle$BundleReference
@@ -3550,7 +3569,6 @@
java.util.ResourceBundle$LoaderReference
java.util.ResourceBundle$RBClassLoader
java.util.ResourceBundle$RBClassLoader$1
-java.util.Scanner
java.util.ServiceLoader
java.util.ServiceLoader$1
java.util.ServiceLoader$LazyIterator
@@ -3558,6 +3576,17 @@
java.util.SimpleTimeZone
java.util.SortedMap
java.util.SortedSet
+java.util.Spliterator
+java.util.Spliterator$OfDouble
+java.util.Spliterator$OfInt
+java.util.Spliterator$OfLong
+java.util.Spliterator$OfPrimitive
+java.util.Spliterators
+java.util.Spliterators$EmptySpliterator
+java.util.Spliterators$EmptySpliterator$OfDouble
+java.util.Spliterators$EmptySpliterator$OfInt
+java.util.Spliterators$EmptySpliterator$OfLong
+java.util.Spliterators$EmptySpliterator$OfRef
java.util.Stack
java.util.StringTokenizer
java.util.SubList
@@ -3569,12 +3598,10 @@
java.util.TimerTask
java.util.TimerThread
java.util.TreeMap
-java.util.TreeMap$AscendingSubMap
java.util.TreeMap$EntryIterator
java.util.TreeMap$EntrySet
java.util.TreeMap$KeyIterator
java.util.TreeMap$KeySet
-java.util.TreeMap$NavigableSubMap
java.util.TreeMap$PrivateEntryIterator
java.util.TreeMap$TreeMapEntry
java.util.TreeMap$ValueIterator
@@ -3595,14 +3622,12 @@
java.util.WeakHashMap$Values
java.util.XMLUtils
java.util.concurrent.AbstractExecutorService
-java.util.concurrent.ArrayBlockingQueue
java.util.concurrent.BlockingQueue
java.util.concurrent.Callable
java.util.concurrent.CancellationException
java.util.concurrent.ConcurrentHashMap
java.util.concurrent.ConcurrentHashMap$BaseIterator
java.util.concurrent.ConcurrentHashMap$CollectionView
-java.util.concurrent.ConcurrentHashMap$CounterCell
java.util.concurrent.ConcurrentHashMap$ForwardingNode
java.util.concurrent.ConcurrentHashMap$KeyIterator
java.util.concurrent.ConcurrentHashMap$KeySetView
@@ -3611,8 +3636,6 @@
java.util.concurrent.ConcurrentHashMap$Traverser
java.util.concurrent.ConcurrentHashMap$TreeBin
java.util.concurrent.ConcurrentHashMap$TreeNode
-java.util.concurrent.ConcurrentHashMap$ValueIterator
-java.util.concurrent.ConcurrentHashMap$ValuesView
java.util.concurrent.ConcurrentLinkedQueue
java.util.concurrent.ConcurrentLinkedQueue$Node
java.util.concurrent.ConcurrentMap
@@ -3689,6 +3712,16 @@
java.util.concurrent.locks.ReentrantReadWriteLock$Sync
java.util.concurrent.locks.ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter
java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock
+java.util.function.BiConsumer
+java.util.function.BiFunction
+java.util.function.Consumer
+java.util.function.Function
+java.util.function.Predicate
+java.util.function.Supplier
+java.util.function.ToDoubleFunction
+java.util.function.ToIntFunction
+java.util.function.ToLongFunction
+java.util.function.UnaryOperator
java.util.jar.JarEntry
java.util.jar.JarFile
java.util.jar.JarFile$1
@@ -3709,15 +3742,19 @@
java.util.logging.LogManager$LoggerWeakRef
java.util.logging.LogManager$RootLogger
java.util.logging.LogManager$SystemLoggerContext
-java.util.logging.LogRecord
java.util.logging.Logger
java.util.logging.LoggingPermission
java.util.logging.LoggingProxyImpl
+java.util.prefs.AbstractPreferences
+java.util.prefs.Preferences
java.util.regex.MatchResult
java.util.regex.Matcher
java.util.regex.Pattern
java.util.regex.PatternSyntaxException
java.util.spi.LocaleServiceProvider
+java.util.stream.BaseStream
+java.util.stream.Stream
+java.util.stream.StreamSupport
java.util.zip.Adler32
java.util.zip.CRC32
java.util.zip.CheckedInputStream
@@ -3748,7 +3785,6 @@
javax.crypto.CipherSpi
javax.crypto.IllegalBlockSizeException
javax.crypto.JceSecurity
-javax.crypto.Mac
javax.crypto.NoSuchPaddingException
javax.crypto.NullCipher
javax.crypto.SecretKey
@@ -3757,10 +3793,6 @@
javax.crypto.spec.SecretKeySpec
javax.microedition.khronos.egl.EGL
javax.microedition.khronos.egl.EGL10
-javax.microedition.khronos.egl.EGLConfig
-javax.microedition.khronos.egl.EGLContext
-javax.microedition.khronos.egl.EGLDisplay
-javax.microedition.khronos.egl.EGLSurface
javax.microedition.khronos.opengles.GL
javax.microedition.khronos.opengles.GL10
javax.microedition.khronos.opengles.GL10Ext
@@ -3771,7 +3803,6 @@
javax.net.ServerSocketFactory
javax.net.SocketFactory
javax.net.ssl.ExtendedSSLSession
-javax.net.ssl.HandshakeCompletedEvent
javax.net.ssl.HandshakeCompletedListener
javax.net.ssl.HostnameVerifier
javax.net.ssl.HttpsURLConnection
@@ -3779,23 +3810,20 @@
javax.net.ssl.KeyManagerFactory
javax.net.ssl.KeyManagerFactory$1
javax.net.ssl.KeyManagerFactorySpi
+javax.net.ssl.SNIHostName
+javax.net.ssl.SNIServerName
javax.net.ssl.SSLContext
javax.net.ssl.SSLContextSpi
javax.net.ssl.SSLEngine
javax.net.ssl.SSLException
-javax.net.ssl.SSLHandshakeException
javax.net.ssl.SSLParameters
javax.net.ssl.SSLPeerUnverifiedException
javax.net.ssl.SSLProtocolException
-javax.net.ssl.SSLServerSocket
javax.net.ssl.SSLServerSocketFactory
javax.net.ssl.SSLSession
-javax.net.ssl.SSLSessionBindingEvent
-javax.net.ssl.SSLSessionBindingListener
javax.net.ssl.SSLSessionContext
javax.net.ssl.SSLSocket
javax.net.ssl.SSLSocketFactory
-javax.net.ssl.SSLSocketFactory$1
javax.net.ssl.TrustManager
javax.net.ssl.TrustManagerFactory
javax.net.ssl.TrustManagerFactory$1
@@ -3841,7 +3869,6 @@
libcore.io.NioBufferIterator
libcore.io.Os
libcore.io.Posix
-libcore.math.MathUtils
libcore.net.NetworkSecurityPolicy
libcore.net.NetworkSecurityPolicy$DefaultNetworkSecurityPolicy
libcore.net.UriCodec
@@ -3857,7 +3884,6 @@
libcore.reflect.ListOfTypes
libcore.reflect.ListOfVariables
libcore.reflect.ParameterizedTypeImpl
-libcore.reflect.TypeVariableImpl
libcore.reflect.Types
libcore.util.BasicLruCache
libcore.util.CharsetUtils
@@ -3866,7 +3892,6 @@
libcore.util.NativeAllocationRegistry
libcore.util.NativeAllocationRegistry$CleanerRunner
libcore.util.NativeAllocationRegistry$CleanerThunk
-libcore.util.Objects
libcore.util.ZoneInfo
libcore.util.ZoneInfo$CheckedArithmeticException
libcore.util.ZoneInfo$WallTime
@@ -3892,11 +3917,8 @@
org.apache.http.HttpResponse
org.apache.http.HttpVersion
org.apache.http.NameValuePair
-org.apache.http.ProtocolException
org.apache.http.ProtocolVersion
-org.apache.http.ReasonPhraseCatalog
org.apache.http.StatusLine
-org.apache.http.client.ClientProtocolException
org.apache.http.client.HttpClient
org.apache.http.client.ResponseHandler
org.apache.http.client.methods.AbortableHttpRequest
@@ -3905,26 +3927,15 @@
org.apache.http.client.methods.HttpPost
org.apache.http.client.methods.HttpRequestBase
org.apache.http.client.methods.HttpUriRequest
-org.apache.http.client.utils.URLEncodedUtils
org.apache.http.conn.ClientConnectionManager
org.apache.http.conn.ConnectTimeoutException
-org.apache.http.conn.params.ConnManagerPNames
-org.apache.http.conn.params.ConnManagerParams
-org.apache.http.conn.params.ConnManagerParams$1
-org.apache.http.conn.params.ConnPerRoute
-org.apache.http.conn.scheme.LayeredSocketFactory
-org.apache.http.conn.scheme.SocketFactory
org.apache.http.entity.AbstractHttpEntity
-org.apache.http.entity.BasicHttpEntity
org.apache.http.entity.ByteArrayEntity
-org.apache.http.impl.client.EntityEnclosingRequestWrapper
-org.apache.http.impl.client.RequestWrapper
org.apache.http.impl.cookie.DateParseException
org.apache.http.impl.cookie.DateUtils
org.apache.http.message.AbstractHttpMessage
org.apache.http.message.BasicHeader
org.apache.http.message.BasicHttpResponse
-org.apache.http.message.BasicNameValuePair
org.apache.http.message.BasicStatusLine
org.apache.http.message.HeaderGroup
org.apache.http.params.AbstractHttpParams
@@ -3933,6 +3944,18 @@
org.apache.http.params.HttpConnectionParams
org.apache.http.params.HttpParams
org.apache.http.protocol.HttpContext
+org.ccil.cowan.tagsoup.AttributesImpl
+org.ccil.cowan.tagsoup.AutoDetector
+org.ccil.cowan.tagsoup.Element
+org.ccil.cowan.tagsoup.ElementType
+org.ccil.cowan.tagsoup.HTMLModels
+org.ccil.cowan.tagsoup.HTMLScanner
+org.ccil.cowan.tagsoup.HTMLSchema
+org.ccil.cowan.tagsoup.Parser
+org.ccil.cowan.tagsoup.Parser$1
+org.ccil.cowan.tagsoup.ScanHandler
+org.ccil.cowan.tagsoup.Scanner
+org.ccil.cowan.tagsoup.Schema
org.json.JSON
org.json.JSONArray
org.json.JSONException
@@ -3954,6 +3977,7 @@
org.xml.sax.SAXNotRecognizedException
org.xml.sax.SAXNotSupportedException
org.xml.sax.XMLReader
+org.xml.sax.ext.LexicalHandler
org.xml.sax.helpers.DefaultHandler
org.xmlpull.v1.XmlPullParser
org.xmlpull.v1.XmlPullParserException
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index ea3cffe..afea7f3 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2138,6 +2138,20 @@
// Settings > Apps > Gear > Special Access > Premium SMS access
PREMIUM_SMS_ACCESS = 388;
+ // Logged when the user resizes the docked stack. Arguments:
+ // 0: Split 50:50
+ // 1: Docked smaller
+ // 2: Docked larger
+ ACTION_WINDOW_DOCK_RESIZE = 389;
+
+ // User exits split-screen by dragging the divider to the side of the screen. Arguments
+ // 0: Docked gets maximized
+ // 1: Fullscreen gets maximized
+ ACTION_WINDOW_UNDOCK_MAX = 390;
+
+ // User tried to dock an unresizable app.
+ ACTION_WINDOW_DOCK_UNRESIZABLE = 391;
+
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
}
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index 9ec6e8d..04ea8e5 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -58,6 +58,7 @@
private static final int MAX_NUMBER_IO_INPUT_ALLOC = 16;
Type mType;
+ boolean mOwningType = false;
Bitmap mBitmap;
int mUsage;
Allocation mAdaptedAllocation;
@@ -383,13 +384,16 @@
guard.open("destroy");
}
- Allocation(long id, RenderScript rs, Type t, int usage, MipmapControl mips) {
+ Allocation(long id, RenderScript rs, Type t, boolean owningType, int usage, MipmapControl mips) {
this(id, rs, t, usage);
+ mOwningType = owningType;
mMipmapControl = mips;
}
protected void finalize() throws Throwable {
RenderScript.registerNativeFree.invoke(RenderScript.sRuntime, mSize);
+ // Set mType null to avoid double-destroying it in case its finalizer races ahead
+ mType = null;
super.finalize();
}
@@ -1578,6 +1582,9 @@
mRS.finish(); // Necessary because resize is fifoed and update is async.
long typeID = mRS.nAllocationGetType(getID(mRS));
+ // Sets zero the mID so that the finalizer of the old mType value won't
+ // destroy the native object that is being reused.
+ mType.setID(0);
mType = new Type(typeID, mRS);
mType.updateFromNative();
updateCacheInfo(mType);
@@ -1921,7 +1928,7 @@
if (id == 0) {
throw new RSRuntimeException("Allocation creation failed.");
}
- return new Allocation(id, rs, type, usage, mips);
+ return new Allocation(id, rs, type, false, usage, mips);
} finally {
Trace.traceEnd(RenderScript.TRACE_TAG);
}
@@ -1979,7 +1986,7 @@
if (id == 0) {
throw new RSRuntimeException("Allocation creation failed.");
}
- return new Allocation(id, rs, t, usage, MipmapControl.MIPMAP_NONE);
+ return new Allocation(id, rs, t, true, usage, MipmapControl.MIPMAP_NONE);
} finally {
Trace.traceEnd(RenderScript.TRACE_TAG);
}
@@ -2068,7 +2075,7 @@
}
// keep a reference to the Bitmap around to prevent GC
- Allocation alloc = new Allocation(id, rs, t, usage, mips);
+ Allocation alloc = new Allocation(id, rs, t, true, usage, mips);
alloc.setBitmap(b);
return alloc;
}
@@ -2078,7 +2085,7 @@
if (id == 0) {
throw new RSRuntimeException("Load failed.");
}
- return new Allocation(id, rs, t, usage, mips);
+ return new Allocation(id, rs, t, true, usage, mips);
} finally {
Trace.traceEnd(RenderScript.TRACE_TAG);
}
@@ -2150,7 +2157,7 @@
}
for (int i=1; i<numAlloc; i++) {
- mAllocationArray[i] = createFromAllcation(rs, mAllocationArray[0]);
+ mAllocationArray[i] = createFromAllocation(rs, mAllocationArray[0]);
}
return mAllocationArray;
} finally {
@@ -2169,7 +2176,7 @@
* @param alloc RenderScript Allocation describing data layout.
* @return Allocation sharing the same data structure.
*/
- static Allocation createFromAllcation(RenderScript rs, Allocation alloc) {
+ static Allocation createFromAllocation(RenderScript rs, Allocation alloc) {
try {
Trace.traceBegin(RenderScript.TRACE_TAG, "createFromAllcation");
rs.validate();
@@ -2184,7 +2191,7 @@
if (id == 0) {
throw new RSRuntimeException("Allocation creation failed.");
}
- Allocation outAlloc = new Allocation(id, rs, type, usage, mips);
+ Allocation outAlloc = new Allocation(id, rs, type, false, usage, mips);
if ((usage & USAGE_IO_INPUT) != 0) {
outAlloc.shareBufferQueue(alloc);
}
@@ -2360,7 +2367,7 @@
if(id == 0) {
throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
}
- return new Allocation(id, rs, t, usage, mips);
+ return new Allocation(id, rs, t, true, usage, mips);
}
/**
@@ -2605,6 +2612,13 @@
if((mUsage & USAGE_IO_OUTPUT) != 0) {
setSurface(null);
}
+
+ if (mType != null && mOwningType) {
+ mType.destroy();
+ mType = null;
+ }
+
super.destroy();
}
+
}
diff --git a/rs/java/android/renderscript/ScriptGroup.java b/rs/java/android/renderscript/ScriptGroup.java
index 219f16b..35ae8b4 100644
--- a/rs/java/android/renderscript/ScriptGroup.java
+++ b/rs/java/android/renderscript/ScriptGroup.java
@@ -187,6 +187,23 @@
guard.open("destroy");
}
+ /**
+ * Destroys this Closure and the Allocation for its return value
+ */
+ public void destroy() {
+ super.destroy();
+ if (mReturnValue != null) {
+ mReturnValue.destroy();
+ }
+ }
+
+ protected void finalize() throws Throwable {
+ // Set null mReturnValue to avoid double-destroying it, in case its
+ // finalizer races ahead.
+ mReturnValue = null;
+ super.finalize();
+ }
+
private void retrieveValueAndDependenceInfo(RenderScript rs,
int index, Script.FieldID fid, Object obj,
long[] values, int[] sizes,
@@ -1015,6 +1032,8 @@
throw new RSIllegalArgumentException("invalid script group name");
}
ScriptGroup ret = new ScriptGroup(mRS, name, mClosures, mInputs, outputs);
+ mClosures = new ArrayList<Closure>();
+ mInputs = new ArrayList<Input>();
return ret;
}
@@ -1042,4 +1061,20 @@
}
+ /**
+ * Destroy this ScriptGroup and all Closures in it
+ */
+ public void destroy() {
+ super.destroy();
+ for(Closure c : mClosures) {
+ c.destroy();
+ }
+ }
+
+ protected void finalize() throws Throwable {
+ // Clear out the list mClosures to avoid double-destroying the closures,
+ // in case their finalizers race ahead.
+ mClosures.clear();
+ super.finalize();
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 613f890..4d7f82d 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -70,12 +70,22 @@
static final int FLAG_FEATURE_AUTOCLICK = 0x00000008;
/**
- * Flag for enabling motion event injectsion
+ * Flag for enabling motion event injection.
*
* @see #setUserAndEnabledFeatures(int, int)
*/
static final int FLAG_FEATURE_INJECT_MOTION_EVENTS = 0x00000010;
+ /**
+ * Flag for enabling the feature to control the screen magnifier. If
+ * {@link #FLAG_FEATURE_SCREEN_MAGNIFIER} is set this flag is ignored
+ * as the screen magnifier feature performs a super set of the work
+ * performed by this feature.
+ *
+ * @see #setUserAndEnabledFeatures(int, int)
+ */
+ static final int FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER = 0x00000020;
+
private final Runnable mProcessBatchedEventsRunnable = new Runnable() {
@Override
public void run() {
@@ -373,8 +383,12 @@
addFirstEventHandler(mTouchExplorer);
}
- if ((mEnabledFeatures & FLAG_FEATURE_SCREEN_MAGNIFIER) != 0) {
- mMagnificationGestureHandler = new MagnificationGestureHandler(mContext, mAms);
+ if ((mEnabledFeatures & FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER) != 0
+ || (mEnabledFeatures & FLAG_FEATURE_SCREEN_MAGNIFIER) != 0) {
+ final boolean detectControlGestures = (mEnabledFeatures
+ & FLAG_FEATURE_SCREEN_MAGNIFIER) != 0;
+ mMagnificationGestureHandler = new MagnificationGestureHandler(
+ mContext, mAms, detectControlGestures);
addFirstEventHandler(mMagnificationGestureHandler);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index ca17c43..d900b37 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1311,6 +1311,9 @@
if (userState.mIsDisplayMagnificationEnabled) {
flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
}
+ if (userHasMagnificationServicesLocked(userState)) {
+ flags |= AccessibilityInputFilter.FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER;
+ }
// Touch exploration without accessibility makes no sense.
if (userState.isHandlingAccessibilityEvents()
&& userState.mIsTouchExplorationEnabled) {
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
index fb1ef37..b2196bf 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 - offsetX) / scale
- + mMagnifiedBounds.left;
- final float centerY = (mMagnifiedBounds.height() / 2.0f - offsetY) / scale
- + mMagnifiedBounds.top;
+ final float centerX = (mMagnifiedBounds.width() / 2.0f
+ + mMagnifiedBounds.left - offsetX) / scale;
+ final float centerY = (mMagnifiedBounds.height() / 2.0f
+ + mMagnifiedBounds.top - offsetY) / scale;
if (updateSpec) {
setScaleAndCenter(scale, centerX, centerY, false);
} else {
@@ -256,7 +256,7 @@
public float getCenterX() {
synchronized (mLock) {
return (mMagnifiedBounds.width() / 2.0f
- - getOffsetX()) / getScale() + mMagnifiedBounds.left;
+ + mMagnifiedBounds.left - getOffsetX()) / getScale();
}
}
@@ -279,7 +279,7 @@
public float getCenterY() {
synchronized (mLock) {
return (mMagnifiedBounds.height() / 2.0f
- - getOffsetY()) / getScale() + mMagnifiedBounds.top;
+ + mMagnifiedBounds.top - getOffsetY()) / getScale();
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
index 51c8ab5..818ac81 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
@@ -80,7 +80,6 @@
private static final boolean DEBUG_STATE_TRANSITIONS = false;
private static final boolean DEBUG_DETECTING = false;
private static final boolean DEBUG_PANNING = false;
- private static final boolean DEBUG_SCALING = false;
private static final int STATE_DELEGATING = 1;
private static final int STATE_DETECTING = 2;
@@ -95,6 +94,9 @@
private final MagnifiedContentInteractionStateHandler mMagnifiedContentInteractionStateHandler;
private final StateViewportDraggingHandler mStateViewportDraggingHandler;
+
+ private final boolean mDetectControlGestures;
+
private EventStreamTransformation mNext;
private int mCurrentState;
@@ -107,12 +109,14 @@
private long mDelegatingStateDownTime;
- public MagnificationGestureHandler(Context context, AccessibilityManagerService ams) {
+ public MagnificationGestureHandler(Context context, AccessibilityManagerService ams,
+ boolean detectControlGestures) {
mMagnificationController = ams.getMagnificationController();
mDetectingStateHandler = new DetectingStateHandler(context);
mStateViewportDraggingHandler = new StateViewportDraggingHandler();
mMagnifiedContentInteractionStateHandler =
new MagnifiedContentInteractionStateHandler(context);
+ mDetectControlGestures = detectControlGestures;
transitionToState(STATE_DETECTING);
}
@@ -125,6 +129,12 @@
}
return;
}
+ if (!mDetectControlGestures) {
+ if (mNext != null) {
+ dispatchTransformedEvent(event, rawEvent, policyFlags);
+ }
+ return;
+ }
mMagnifiedContentInteractionStateHandler.onMotionEvent(event, rawEvent, policyFlags);
switch (mCurrentState) {
case STATE_DELEGATING: {
@@ -140,7 +150,7 @@
}
break;
case STATE_MAGNIFIED_INTERACTION: {
- // mMagnifiedContentInteractonStateHandler handles events only
+ // mMagnifiedContentInteractionStateHandler handles events only
// if this is the current state since it uses ScaleGestureDetecotr
// and a GestureDetector which need well formed event stream.
}
@@ -208,31 +218,6 @@
break;
}
if (mNext != null) {
- // If the event is within the magnified portion of the screen we have
- // to change its location to be where the user thinks he is poking the
- // UI which may have been magnified and panned.
- final float eventX = event.getX();
- final float eventY = event.getY();
- if (mMagnificationController.isMagnifying()
- && mMagnificationController.magnifiedRegionContains(eventX, eventY)) {
- final float scale = mMagnificationController.getScale();
- final float scaledOffsetX = mMagnificationController.getOffsetX();
- final float scaledOffsetY = mMagnificationController.getOffsetY();
- final int pointerCount = event.getPointerCount();
- PointerCoords[] coords = getTempPointerCoordsWithMinSize(pointerCount);
- PointerProperties[] properties = getTempPointerPropertiesWithMinSize(
- pointerCount);
- for (int i = 0; i < pointerCount; i++) {
- event.getPointerCoords(i, coords[i]);
- coords[i].x = (coords[i].x - scaledOffsetX) / scale;
- coords[i].y = (coords[i].y - scaledOffsetY) / scale;
- event.getPointerProperties(i, properties[i]);
- }
- event = MotionEvent.obtain(event.getDownTime(),
- event.getEventTime(), event.getAction(), pointerCount, properties,
- coords, 0, 0, 1.0f, 1.0f, event.getDeviceId(), 0, event.getSource(),
- event.getFlags());
- }
// We cache some events to see if the user wants to trigger magnification.
// If no magnification is triggered we inject these events with adjusted
// time and down time to prevent subsequent transformations being confused
@@ -240,10 +225,40 @@
// injected we need to also update the down time of all subsequent non cached
// events. All delegated events cached and non-cached are delivered here.
event.setDownTime(mDelegatingStateDownTime);
- mNext.onMotionEvent(event, rawEvent, policyFlags);
+ dispatchTransformedEvent(event, rawEvent, policyFlags);
}
}
+ private void dispatchTransformedEvent(MotionEvent event, MotionEvent rawEvent,
+ int policyFlags) {
+ // If the event is within the magnified portion of the screen we have
+ // to change its location to be where the user thinks he is poking the
+ // UI which may have been magnified and panned.
+ final float eventX = event.getX();
+ final float eventY = event.getY();
+ if (mMagnificationController.isMagnifying()
+ && mMagnificationController.magnifiedRegionContains(eventX, eventY)) {
+ final float scale = mMagnificationController.getScale();
+ final float scaledOffsetX = mMagnificationController.getOffsetX();
+ final float scaledOffsetY = mMagnificationController.getOffsetY();
+ final int pointerCount = event.getPointerCount();
+ PointerCoords[] coords = getTempPointerCoordsWithMinSize(pointerCount);
+ PointerProperties[] properties = getTempPointerPropertiesWithMinSize(
+ pointerCount);
+ for (int i = 0; i < pointerCount; i++) {
+ event.getPointerCoords(i, coords[i]);
+ coords[i].x = (coords[i].x - scaledOffsetX) / scale;
+ coords[i].y = (coords[i].y - scaledOffsetY) / scale;
+ event.getPointerProperties(i, properties[i]);
+ }
+ event = MotionEvent.obtain(event.getDownTime(),
+ event.getEventTime(), event.getAction(), pointerCount, properties,
+ coords, 0, 0, 1.0f, 1.0f, event.getDeviceId(), 0, event.getSource(),
+ event.getFlags());
+ }
+ mNext.onMotionEvent(event, rawEvent, policyFlags);
+ }
+
private PointerCoords[] getTempPointerCoordsWithMinSize(int size) {
final int oldSize = (mTempPointerCoords != null) ? mTempPointerCoords.length : 0;
if (oldSize < size) {
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index f93fb1b..0428ecf 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);
}
}
}
@@ -616,23 +613,22 @@
| FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
}
}
+ for (int j = 0; j < widgetCount; j++) {
+ Widget widget = provider.widgets.get(j);
+ if (targetWidget != null && targetWidget != widget) continue;
+ PendingIntent intent = null;
+ if (onClickIntent != null) {
+ intent = PendingIntent.getActivity(mContext, widget.appWidgetId,
+ onClickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ }
+ RemoteViews views = createMaskedWidgetRemoteViews(iconBitmap, showBadge, intent);
+ if (widget.replaceWithMaskedViewsLocked(views)) {
+ scheduleNotifyUpdateAppWidgetLocked(widget, widget.getEffectiveViewsLocked());
+ }
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
-
- for (int j = 0; j < widgetCount; j++) {
- Widget widget = provider.widgets.get(j);
- if (targetWidget != null && targetWidget != widget) continue;
- PendingIntent intent = null;
- if (onClickIntent != null) {
- intent = PendingIntent.getActivity(mContext, widget.appWidgetId,
- onClickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
- }
- RemoteViews views = createMaskedWidgetRemoteViews(iconBitmap, showBadge, intent);
- if (widget.replaceWithMaskedViewsLocked(views)) {
- scheduleNotifyUpdateAppWidgetLocked(widget, widget.getEffectiveViewsLocked());
- }
- }
}
private void unmaskWidgetsViewsLocked(Provider provider) {
@@ -1065,8 +1061,6 @@
widget.provider = provider;
widget.options = (options != null) ? cloneIfLocalBinder(options) : new Bundle();
- onWidgetProviderAddedOrChangedLocked(widget);
-
// We need to provide a default value for the widget category if it is not specified
if (!widget.options.containsKey(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)) {
widget.options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
@@ -1075,6 +1069,8 @@
provider.widgets.add(widget);
+ onWidgetProviderAddedOrChangedLocked(widget);
+
final int widgetCount = provider.widgets.size();
if (widgetCount == 1) {
// Tell the provider that it's ready.
@@ -3458,33 +3454,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/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 966deb6..e5fe03a 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();
@@ -1528,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());
}
@@ -1656,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;
}
@@ -1667,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);
@@ -1703,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]);
@@ -1900,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);
}
@@ -1921,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;
@@ -1938,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) {
@@ -2010,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) {
@@ -2024,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.");
}
@@ -2037,20 +2014,26 @@
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")) {
+ final NetworkAgentInfo nai;
+ synchronized (mNetworkForNetId) {
+ nai = mNetworkForNetId.get(msg.arg2);
+ }
+ if (nai != null) {
final boolean valid =
(msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
- if (DBG) log(nai.name() + " validation " + (valid ? " passed" : "failed"));
+ if (DBG) log(nai.name() + " validation " + (valid ? "passed" : "failed") +
+ (msg.obj == null ? "" : " with redirect to " + (String)msg.obj));
if (valid != nai.lastValidated) {
final int oldScore = nai.getCurrentScore();
nai.lastValidated = valid;
@@ -2061,16 +2044,18 @@
}
updateInetCondition(nai);
// Let the NetworkAgent know the state of its network
+ Bundle redirectUrlBundle = new Bundle();
+ redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, (String)msg.obj);
nai.asyncChannel.sendMessage(
- android.net.NetworkAgent.CMD_REPORT_NETWORK_STATUS,
+ NetworkAgent.CMD_REPORT_NETWORK_STATUS,
(valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
- 0, null);
+ 0, redirectUrlBundle);
}
break;
}
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;
@@ -2102,6 +2087,14 @@
break;
}
}
+ return true;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (!maybeHandleAsyncChannelMessage(msg) && !maybeHandleNetworkMonitorMessage(msg)) {
+ maybeHandleNetworkAgentMessage(msg);
+ }
}
}
@@ -2213,6 +2206,10 @@
}
mLegacyTypeTracker.remove(nai, wasDefault);
rematchAllNetworksAndRequests(null, 0);
+ if (wasDefault && getDefaultNetwork() == null) {
+ // Log that we lost the default network and there is no replacement.
+ logConnectivityServiceChangeEvent(null, nai);
+ }
if (nai.created) {
// Tell netd to clean up the configuration for this network
// (routing rules, DNS, etc).
@@ -2321,7 +2318,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);
@@ -2334,7 +2331,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.");
@@ -2445,14 +2442,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
@@ -2495,11 +2492,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;
}
@@ -3353,10 +3353,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.
@@ -3383,7 +3379,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);
@@ -3826,8 +3822,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();
@@ -3992,7 +3987,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;
@@ -4010,7 +4005,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));
}
@@ -4215,7 +4210,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) {
@@ -4226,7 +4221,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) {
@@ -4237,7 +4232,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) {
@@ -4253,7 +4248,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());
@@ -4436,9 +4431,8 @@
teardownUnneededNetwork(oldNetwork);
}
- private void makeDefault(NetworkAgentInfo newNetwork) {
+ private void makeDefault(NetworkAgentInfo newNetwork, NetworkAgentInfo prevNetwork) {
if (DBG) log("Switching to new default network: " + newNetwork);
- ConnectivityServiceChangeEvent.logEvent(newNetwork.network.netId);
setupDataActivityTracking(newNetwork);
try {
mNetd.setDefaultNetId(newNetwork.network.netId);
@@ -4449,6 +4443,8 @@
handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
updateTcpBufferSizes(newNetwork);
setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
+
+ logConnectivityServiceChangeEvent(newNetwork, prevNetwork);
}
// Handles a network appearing or improving its score.
@@ -4521,14 +4517,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);
@@ -4599,7 +4595,7 @@
}
if (isNewDefault) {
// Notify system services that this network is up.
- makeDefault(newNetwork);
+ makeDefault(newNetwork, oldDefaultNetwork);
synchronized (ConnectivityService.this) {
// have a new default network, release the transition wakelock in
// a second if it's held. The second pause is to allow apps
@@ -4858,7 +4854,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");
@@ -4936,7 +4932,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);
@@ -5069,4 +5065,22 @@
NetworkAgentInfo nai, NetworkRequest defaultRequest) {
return new NetworkMonitor(context, handler, nai, defaultRequest);
}
+
+ private static void logConnectivityServiceChangeEvent(
+ NetworkAgentInfo next, NetworkAgentInfo prev) {
+ final int newNetId = (next == null) ? NETID_UNSET : next.network.netId;
+ final int[] newTransportTypes = (next == null)
+ ? new int[0]
+ : next.networkCapabilities.getTransportTypes();
+
+ final int oldNetId = (prev == null) ? NETID_UNSET : prev.network.netId;
+ final boolean hadIPv4 = (prev != null) &&
+ prev.linkProperties.hasIPv4Address() &&
+ prev.linkProperties.hasIPv4DefaultRoute();
+ final boolean hadIPv6 = (prev != null) &&
+ prev.linkProperties.hasGlobalIPv6Address() &&
+ prev.linkProperties.hasIPv6DefaultRoute();
+ ConnectivityServiceChangeEvent.logEvent(newNetId, newTransportTypes,
+ oldNetId, hadIPv4, hadIPv6);
+ }
}
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index aa98648..5a90488 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -58,7 +58,6 @@
* as a camera launch.
*/
private static final long CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS = 300;
- private static final long CAMERA_POWER_DOUBLE_TAP_MIN_TIME_MS = 120;
/** The listener that receives the gesture event. */
private final GestureEventListener mGestureListener = new GestureEventListener();
@@ -260,8 +259,7 @@
synchronized (this) {
doubleTapInterval = event.getEventTime() - mLastPowerDown;
if (mCameraDoubleTapPowerEnabled
- && doubleTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS
- && doubleTapInterval > CAMERA_POWER_DOUBLE_TAP_MIN_TIME_MS) {
+ && doubleTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS) {
launched = true;
intercept = interactive;
}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index ac7872a..544e645 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,23 +2960,12 @@
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;
}
setInputMethodLocked(nextSubtype.mImi.getId(), nextSubtype.mSubtypeId);
- if (mSubtypeSwitchedByShortCutToast != null) {
- mSubtypeSwitchedByShortCutToast.cancel();
- mSubtypeSwitchedByShortCutToast = null;
- }
- if ((mImeWindowVis & InputMethodService.IME_VISIBLE) != 0) {
- // IME window is shown. The user should be able to visually understand that the
- // subtype is changed in most of cases. To avoid UI overlap, we do not show a toast
- // in this case.
- return;
- }
final InputMethodInfo newInputMethodInfo = mMethodMap.get(mCurMethodId);
if (newInputMethodInfo == null) {
return;
@@ -2987,8 +2973,12 @@
final CharSequence toastText = InputMethodUtils.getImeAndSubtypeDisplayName(mContext,
newInputMethodInfo, mCurrentSubtype);
if (!TextUtils.isEmpty(toastText)) {
- mSubtypeSwitchedByShortCutToast = Toast.makeText(mContext, toastText.toString(),
- Toast.LENGTH_SHORT);
+ if (mSubtypeSwitchedByShortCutToast == null) {
+ mSubtypeSwitchedByShortCutToast = Toast.makeText(mContext, toastText,
+ Toast.LENGTH_SHORT);
+ } else {
+ mSubtypeSwitchedByShortCutToast.setText(toastText);
+ }
mSubtypeSwitchedByShortCutToast.show();
}
}
@@ -3648,6 +3638,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 +3732,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 +3814,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 +3822,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/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 4ac75ca..f2b4e52 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -229,7 +229,6 @@
filter.addAction(Intent.ACTION_USER_ADDED);
filter.addAction(Intent.ACTION_USER_STARTING);
filter.addAction(Intent.ACTION_USER_REMOVED);
- filter.addAction(Intent.ACTION_USER_PRESENT);
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
mStorage = new LockSettingsStorage(context, new LockSettingsStorage.Callback() {
@@ -369,8 +368,6 @@
} else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
mStorage.prefetchUser(userHandle);
- } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
- mStrongAuth.reportUnlock(getSendingUserId());
} else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
if (userHandle > 0) {
@@ -1347,6 +1344,12 @@
mStrongAuth.requireStrongAuth(strongAuthReason, userId);
}
+ @Override
+ public void userPresent(int userId) {
+ checkWritePermission(userId);
+ mStrongAuth.reportUnlock(userId);
+ }
+
private static final String[] VALID_SETTINGS = new String[] {
LockPatternUtils.LOCKOUT_PERMANENT_KEY,
LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
index d136f1a..9ab6300 100644
--- a/services/core/java/com/android/server/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -401,7 +401,8 @@
return getLockCredentialFilePathForUser(userId, BASE_ZERO_LOCK_PATTERN_FILE);
}
- private String getChildProfileLockFile(int userId) {
+ @VisibleForTesting
+ String getChildProfileLockFile(int userId) {
return getLockCredentialFilePathForUser(userId, CHILD_PROFILE_LOCK_FILE);
}
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index fd9a94d..229a3f4 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -1010,7 +1010,7 @@
Configuration config = new Configuration();
config.setLocale(locale);
try {
- ActivityManagerNative.getDefault().updateConfiguration(config);
+ ActivityManagerNative.getDefault().updatePersistentConfiguration(config);
} catch (RemoteException e) {
Slog.e(TAG, "Error setting system locale from mount service", e);
}
diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java
index d6dbad8..6009984 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 {
@@ -225,7 +243,7 @@
log("Problem parsing message " + e);
} finally {
if (releaseWl) {
- mWakeLock.acquire();
+ mWakeLock.release();
}
}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index bf4df94..fffd850 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -174,6 +174,16 @@
public static final int StrictCleartext = 617;
}
+ /**
+ * String indicating a softap command.
+ */
+ static final String SOFT_AP_COMMAND = "softap";
+
+ /**
+ * String passed back to netd connector indicating softap command success.
+ */
+ static final String SOFT_AP_COMMAND_SUCCESS = "Ok";
+
static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
/**
@@ -1426,20 +1436,48 @@
}
}
+ /**
+ * Private method used to call execute for a command given the provided arguments.
+ *
+ * This function checks the returned NativeDaemonEvent for the provided expected response code
+ * and message. If either of these is not correct, an error is logged.
+ *
+ * @param String command The command to execute.
+ * @param Object[] args If needed, arguments for the command to execute.
+ * @param int expectedResponseCode The code expected to be returned in the corresponding event.
+ * @param String expectedResponseMessage The message expected in the returned event.
+ * @param String logMsg The message to log as an error (TAG will be applied).
+ */
+ private void executeOrLogWithMessage(String command, Object[] args,
+ int expectedResponseCode, String expectedResponseMessage, String logMsg)
+ throws NativeDaemonConnectorException {
+ NativeDaemonEvent event = mConnector.execute(command, args);
+ if (event.getCode() != expectedResponseCode
+ || !event.getMessage().equals(expectedResponseMessage)) {
+ Log.e(TAG, logMsg + ": event = " + event);
+ }
+ }
+
@Override
- public void startAccessPoint(
- WifiConfiguration wifiConfig, String wlanIface) {
+ public void startAccessPoint(WifiConfiguration wifiConfig, String wlanIface) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+ Object[] args;
+ String logMsg = "startAccessPoint Error setting up softap";
try {
if (wifiConfig == null) {
- mConnector.execute("softap", "set", wlanIface);
+ args = new Object[] {"set", wlanIface};
} else {
- mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
- "broadcast", Integer.toString(wifiConfig.apChannel),
- getSecurityType(wifiConfig),
- new SensitiveArg(wifiConfig.preSharedKey));
+ args = new Object[] {"set", wlanIface, wifiConfig.SSID,
+ "broadcast", Integer.toString(wifiConfig.apChannel),
+ getSecurityType(wifiConfig), new SensitiveArg(wifiConfig.preSharedKey)};
}
- mConnector.execute("softap", "startap");
+ executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult,
+ SOFT_AP_COMMAND_SUCCESS, logMsg);
+
+ logMsg = "startAccessPoint Error starting softap";
+ args = new Object[] {"startap"};
+ executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult,
+ SOFT_AP_COMMAND_SUCCESS, logMsg);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
@@ -1460,8 +1498,12 @@
@Override
public void wifiFirmwareReload(String wlanIface, String mode) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+ Object[] args = {"fwreload", wlanIface, mode};
+ String logMsg = "wifiFirmwareReload Error reloading "
+ + wlanIface + " fw in " + mode + " mode";
try {
- mConnector.execute("softap", "fwreload", wlanIface, mode);
+ executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult,
+ SOFT_AP_COMMAND_SUCCESS, logMsg);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
@@ -1470,8 +1512,12 @@
@Override
public void stopAccessPoint(String wlanIface) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+ Object[] args = {"stopap"};
+ String logMsg = "stopAccessPoint Error stopping softap";
+
try {
- mConnector.execute("softap", "stopap");
+ executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult,
+ SOFT_AP_COMMAND_SUCCESS, logMsg);
wifiFirmwareReload(wlanIface, "STA");
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
@@ -1481,14 +1527,21 @@
@Override
public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+ Object[] args;
+ String logMsg = "startAccessPoint Error setting up softap";
try {
if (wifiConfig == null) {
- mConnector.execute("softap", "set", wlanIface);
+ args = new Object[] {"set", wlanIface};
} else {
- mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
- "broadcast", "6", getSecurityType(wifiConfig),
- new SensitiveArg(wifiConfig.preSharedKey));
+ // TODO: understand why this is set to "6" instead of
+ // Integer.toString(wifiConfig.apChannel) as in startAccessPoint
+ // TODO: should startAccessPoint call this instead of repeating code?
+ args = new Object[] {"set", wlanIface, wifiConfig.SSID,
+ "broadcast", "6",
+ getSecurityType(wifiConfig), new SensitiveArg(wifiConfig.preSharedKey)};
}
+ executeOrLogWithMessage(SOFT_AP_COMMAND, args, NetdResponseCode.SoftapStatusResult,
+ SOFT_AP_COMMAND_SUCCESS, logMsg);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
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/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 2924cef..5ba07cf 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -454,6 +454,12 @@
return;
}
+ if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE
+ && Settings.System.getInt(
+ mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0) == 0) {
+ return;
+ }
+
int mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE,
vib.mUsageHint, vib.mUid, vib.mOpPkg);
if (mode == AppOpsManager.MODE_ALLOWED) {
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 4198af9..be53cfc 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -65,10 +65,14 @@
// Which native processes to dump into dropbox's stack traces
public static final String[] NATIVE_STACKS_OF_INTEREST = new String[] {
"/system/bin/audioserver",
+ "/system/bin/cameraserver",
+ "/system/bin/drmserver",
+ "/system/bin/mediadrmserver",
"/system/bin/mediaserver",
"/system/bin/sdcard",
"/system/bin/surfaceflinger",
- "media.log"
+ "media.codec", // system/bin/mediacodec
+ "media.extractor", // system/bin/mediaextractor
};
static Watchdog sWatchdog;
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 810270d..4791818 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -85,10 +85,14 @@
import android.util.SparseBooleanArray;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
import com.android.server.FgThread;
import com.android.server.LocalServices;
+import com.android.server.SystemService;
+
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;
@@ -125,9 +129,34 @@
public class AccountManagerService
extends IAccountManager.Stub
implements RegisteredServicesCacheListener<AuthenticatorDescription> {
-
private static final String TAG = "AccountManagerService";
+ public static class Lifecycle extends SystemService {
+ private AccountManagerService mService;
+
+ public Lifecycle(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ mService = new AccountManagerService(getContext());
+ publishBinderService(Context.ACCOUNT_SERVICE, mService);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
+ mService.systemReady();
+ }
+ }
+
+ @Override
+ public void onUnlockUser(int userHandle) {
+ mService.onUnlockUser(userHandle);
+ }
+ }
+
private static final String DATABASE_NAME = "accounts.db";
private static final int PRE_N_DATABASE_VERSION = 9;
private static final int CE_DATABASE_VERSION = 10;
@@ -266,10 +295,10 @@
private int debugDbInsertionPoint = -1;
private SQLiteStatement statementForLogging;
- UserAccounts(Context context, int userId) {
+ UserAccounts(Context context, int userId, File preNDbFile, File deDbFile) {
this.userId = userId;
synchronized (cacheLock) {
- openHelper = DeDatabaseHelper.create(context, userId);
+ openHelper = DeDatabaseHelper.create(context, userId, preNDbFile, deDbFile);
}
}
}
@@ -338,15 +367,12 @@
IntentFilter userFilter = new IntentFilter();
userFilter.addAction(Intent.ACTION_USER_REMOVED);
- userFilter.addAction(Intent.ACTION_USER_UNLOCKED);
mContext.registerReceiverAsUser(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_USER_REMOVED.equals(action)) {
onUserRemoved(intent);
- } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
- onUserUnlocked(intent);
}
}
}, UserHandle.ALL, userFilter, null, null);
@@ -539,7 +565,9 @@
UserAccounts accounts = mUsers.get(userId);
boolean validateAccounts = false;
if (accounts == null) {
- accounts = new UserAccounts(mContext, userId);
+ File preNDbFile = new File(getPreNDatabaseName(userId));
+ File deDbFile = new File(getDeDatabaseName(userId));
+ accounts = new UserAccounts(mContext, userId, preNDbFile, deDbFile);
initializeDebugDbSizeAndCompileSqlStatementForLogging(
accounts.openHelper.getWritableDatabase(), accounts);
mUsers.append(userId, accounts);
@@ -550,10 +578,12 @@
if (!accounts.openHelper.isCeDatabaseAttached() && mUnlockedUsers.get(userId)) {
Log.i(TAG, "User " + userId + " is unlocked - opening CE database");
synchronized (accounts.cacheLock) {
- CeDatabaseHelper.create(mContext, userId);
- accounts.openHelper.attachCeDatabase();
+ File preNDatabaseFile = new File(getPreNDatabaseName(userId));
+ File ceDatabaseFile = new File(getCeDatabaseName(userId));
+ CeDatabaseHelper.create(mContext, userId, preNDatabaseFile, ceDatabaseFile);
+ accounts.openHelper.attachCeDatabase(ceDatabaseFile);
}
- // TODO Synchronize accounts by removing CE account not available in DE
+ syncDeCeAccountsLocked(accounts);
}
if (validateAccounts) {
validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */);
@@ -562,6 +592,21 @@
}
}
+ private void syncDeCeAccountsLocked(UserAccounts accounts) {
+ Preconditions.checkState(Thread.holdsLock(mUsers), "mUsers lock must be held");
+ final SQLiteDatabase db = accounts.openHelper.getReadableDatabaseUserIsUnlocked();
+ List<Account> accountsToRemove = CeDatabaseHelper.findCeAccountsNotInDe(db);
+ if (!accountsToRemove.isEmpty()) {
+ Slog.i(TAG, "Accounts " + accountsToRemove + " were previously deleted while user "
+ + accounts.userId + " was locked. Removing accounts from CE tables");
+ logRecord(accounts, DebugDbHelper.ACTION_SYNC_DE_CE_ACCOUNTS, TABLE_ACCOUNTS);
+
+ for (Account account : accountsToRemove) {
+ removeAccountInternal(accounts, account, Process.myUid());
+ }
+ }
+ }
+
private void purgeOldGrantsAll() {
synchronized (mUsers) {
for (int i = 0; i < mUsers.size(); i++) {
@@ -631,8 +676,12 @@
}
}
- private void onUserUnlocked(Intent intent) {
- int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+ @VisibleForTesting
+ void onUserUnlocked(Intent intent) {
+ onUnlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1));
+ }
+
+ void onUnlockUser(int userId) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "onUserUnlocked " + userId);
}
@@ -799,7 +848,7 @@
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAuthenticatorTypes: "
+ "for user id " + userId
- + "caller's uid " + callingUid
+ + " caller's uid " + callingUid
+ ", pid " + Binder.getCallingPid());
}
// Only allow the system process to read accounts of other users
@@ -1537,27 +1586,41 @@
}
}
- /* For testing */
+ @VisibleForTesting
protected void removeAccountInternal(Account account) {
removeAccountInternal(getUserAccountsForCaller(), account, getCallingUid());
}
private boolean removeAccountInternal(UserAccounts accounts, Account account, int callingUid) {
- // For now user is required to be unlocked. TODO: Handle both cases in the future
int deleted;
+ boolean userUnlocked = isUserUnlocked(accounts.userId);
+ if (!userUnlocked) {
+ Slog.i(TAG, "Removing account " + account + " while user "+ accounts.userId
+ + " is still locked. CE data will be removed later");
+ }
synchronized (accounts.cacheLock) {
- final SQLiteDatabase db = accounts.openHelper.getWritableDatabaseUserIsUnlocked();
+ final SQLiteDatabase db = userUnlocked
+ ? accounts.openHelper.getWritableDatabaseUserIsUnlocked()
+ : accounts.openHelper.getWritableDatabase();
final long accountId = getAccountIdLocked(db, account);
- deleted = db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE
- + "=?",
- new String[]{account.name, account.type});
- // Delete from CE table
- db.delete(CE_TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?",
- new String[]{account.name, account.type});
+ db.beginTransaction();
+ try {
+ deleted = db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE
+ + "=?", new String[]{account.name, account.type});
+ if (userUnlocked) {
+ // Delete from CE table
+ deleted = db.delete(CE_TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE
+ + "=?", new String[]{account.name, account.type});
+ }
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
removeAccountFromCacheLocked(accounts, account);
sendAccountsChangedBroadcast(accounts.userId);
-
- logRecord(db, DebugDbHelper.ACTION_ACCOUNT_REMOVE, TABLE_ACCOUNTS, accountId, accounts);
+ String action = userUnlocked ? DebugDbHelper.ACTION_ACCOUNT_REMOVE
+ : DebugDbHelper.ACTION_ACCOUNT_REMOVE_DE;
+ logRecord(db, action, TABLE_ACCOUNTS, accountId, accounts);
}
long id = Binder.clearCallingIdentity();
try {
@@ -4014,7 +4077,8 @@
}
}
- static String getPreNDatabaseName(int userId) {
+ @VisibleForTesting
+ String getPreNDatabaseName(int userId) {
File systemDir = Environment.getDataSystemDirectory();
File databaseFile = new File(Environment.getUserSystemDirectory(userId),
PRE_N_DATABASE_NAME);
@@ -4040,13 +4104,15 @@
return databaseFile.getPath();
}
- static String getDeDatabaseName(int userId) {
+ @VisibleForTesting
+ String getDeDatabaseName(int userId) {
File databaseFile = new File(Environment.getDataSystemDeDirectory(userId),
DE_DATABASE_NAME);
return databaseFile.getPath();
}
- static String getCeDatabaseName(int userId) {
+ @VisibleForTesting
+ String getCeDatabaseName(int userId) {
File databaseFile = new File(Environment.getDataSystemCeDirectory(userId),
CE_DATABASE_NAME);
return databaseFile.getPath();
@@ -4072,6 +4138,7 @@
private static String ACTION_CLEAR_PASSWORD = "action_clear_password";
private static String ACTION_ACCOUNT_ADD = "action_account_add";
private static String ACTION_ACCOUNT_REMOVE = "action_account_remove";
+ private static String ACTION_ACCOUNT_REMOVE_DE = "action_account_remove_de";
private static String ACTION_AUTHENTICATOR_REMOVE = "action_authenticator_remove";
private static String ACTION_ACCOUNT_RENAME = "action_account_rename";
@@ -4082,6 +4149,7 @@
// who called.
private static String ACTION_CALLED_ACCOUNT_ADD = "action_called_account_add";
private static String ACTION_CALLED_ACCOUNT_REMOVE = "action_called_account_remove";
+ private static String ACTION_SYNC_DE_CE_ACCOUNTS = "action_sync_de_ce_accounts";
//This action doesn't add account to accountdb. Account is only
// added in finishSession which may be in a different user profile.
@@ -4185,13 +4253,11 @@
}
static class PreNDatabaseHelper extends SQLiteOpenHelper {
-
private final Context mContext;
private final int mUserId;
- public PreNDatabaseHelper(Context context, int userId) {
- super(context, AccountManagerService.getPreNDatabaseName(userId), null,
- PRE_N_DATABASE_VERSION);
+ public PreNDatabaseHelper(Context context, int userId, String preNDatabaseName) {
+ super(context, preNDatabaseName, null, PRE_N_DATABASE_VERSION);
mContext = context;
mUserId = userId;
}
@@ -4328,8 +4394,8 @@
private final int mUserId;
private volatile boolean mCeAttached;
- private DeDatabaseHelper(Context context, int userId) {
- super(context, getDeDatabaseName(userId), null, DE_DATABASE_VERSION);
+ private DeDatabaseHelper(Context context, int userId, String deDatabaseName) {
+ super(context, deDatabaseName, null, DE_DATABASE_VERSION);
mUserId = userId;
}
@@ -4394,8 +4460,7 @@
}
}
- public void attachCeDatabase() {
- File ceDbFile = new File(getCeDatabaseName(mUserId));
+ public void attachCeDatabase(File ceDbFile) {
SQLiteDatabase db = getWritableDatabase();
db.execSQL("ATTACH DATABASE '" + ceDbFile.getPath()+ "' AS ceDb");
mCeAttached = true;
@@ -4408,8 +4473,8 @@
public SQLiteDatabase getReadableDatabaseUserIsUnlocked() {
if(!mCeAttached) {
- Log.wtf(TAG, "getReadableDatabaseUserIsUnlocked called while user "
- + mUserId + " is still locked ", new Throwable());
+ Log.wtf(TAG, "getReadableDatabaseUserIsUnlocked called while user " + mUserId
+ + " is still locked. CE database is not yet available.", new Throwable());
}
return super.getReadableDatabase();
}
@@ -4417,7 +4482,7 @@
public SQLiteDatabase getWritableDatabaseUserIsUnlocked() {
if(!mCeAttached) {
Log.wtf(TAG, "getWritableDatabaseUserIsUnlocked called while user " + mUserId
- + " is still locked ", new Throwable());
+ + " is still locked. CE database is not yet available.", new Throwable());
}
return super.getWritableDatabase();
}
@@ -4470,20 +4535,24 @@
db.execSQL("DETACH DATABASE preNDb");
}
- static DeDatabaseHelper create(Context context, int userId) {
- File oldDb = new File(getPreNDatabaseName(userId));
- File newDb = new File(getDeDatabaseName(userId));
- boolean newDbExists = newDb.exists();
- DeDatabaseHelper deDatabaseHelper = new DeDatabaseHelper(context, userId);
+ static DeDatabaseHelper create(
+ Context context,
+ int userId,
+ File preNDatabaseFile,
+ File deDatabaseFile) {
+ boolean newDbExists = deDatabaseFile.exists();
+ DeDatabaseHelper deDatabaseHelper = new DeDatabaseHelper(context, userId,
+ deDatabaseFile.getPath());
// If the db just created, and there is a legacy db, migrate it
- if (!newDbExists && oldDb.exists()) {
+ if (!newDbExists && preNDatabaseFile.exists()) {
// Migrate legacy db to the latest version - PRE_N_DATABASE_VERSION
- PreNDatabaseHelper preNDatabaseHelper = new PreNDatabaseHelper(context, userId);
+ PreNDatabaseHelper preNDatabaseHelper = new PreNDatabaseHelper(context, userId,
+ preNDatabaseFile.getPath());
// Open the database to force upgrade if required
preNDatabaseHelper.getWritableDatabase();
preNDatabaseHelper.close();
// Move data without SPII to DE
- deDatabaseHelper.migratePreNDbToDe(oldDb);
+ deDatabaseHelper.migratePreNDbToDe(preNDatabaseFile);
}
return deDatabaseHelper;
}
@@ -4491,8 +4560,8 @@
static class CeDatabaseHelper extends SQLiteOpenHelper {
- public CeDatabaseHelper(Context context, int userId) {
- super(context, getCeDatabaseName(userId), null, CE_DATABASE_VERSION);
+ public CeDatabaseHelper(Context context, String ceDatabaseName) {
+ super(context, ceDatabaseName, null, CE_DATABASE_VERSION);
}
/**
@@ -4580,33 +4649,56 @@
}
}
+ static List<Account> findCeAccountsNotInDe(SQLiteDatabase db) {
+ // Select accounts from CE that do not exist in DE
+ Cursor cursor = db.rawQuery(
+ "SELECT " + ACCOUNTS_NAME + "," + ACCOUNTS_TYPE
+ + " FROM " + CE_TABLE_ACCOUNTS
+ + " WHERE NOT EXISTS "
+ + " (SELECT " + ACCOUNTS_ID + " FROM " + TABLE_ACCOUNTS
+ + " WHERE " + ACCOUNTS_ID + "=" + CE_TABLE_ACCOUNTS + "." + ACCOUNTS_ID
+ + " )", null);
+ try {
+ List<Account> accounts = new ArrayList<>(cursor.getCount());
+ while (cursor.moveToNext()) {
+ String accountName = cursor.getString(0);
+ String accountType = cursor.getString(1);
+ accounts.add(new Account(accountName, accountType));
+ }
+ return accounts;
+ } finally {
+ cursor.close();
+ }
+ }
+
/**
* Creates a new {@code CeDatabaseHelper}. If pre-N db file is present at the old location,
* it also performs migration to the new CE database.
* @param context
* @param userId id of the user where the database is located
*/
- static CeDatabaseHelper create(Context context, int userId) {
-
- File oldDatabaseFile = new File(getPreNDatabaseName(userId));
- File ceDatabaseFile = new File(getCeDatabaseName(userId));
+ static CeDatabaseHelper create(
+ Context context,
+ int userId,
+ File preNDatabaseFile,
+ File ceDatabaseFile) {
boolean newDbExists = ceDatabaseFile.exists();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "CeDatabaseHelper.create userId=" + userId + " oldDbExists="
- + oldDatabaseFile.exists() + " newDbExists=" + newDbExists);
+ + preNDatabaseFile.exists() + " newDbExists=" + newDbExists);
}
boolean removeOldDb = false;
- if (!newDbExists && oldDatabaseFile.exists()) {
- removeOldDb = migratePreNDbToCe(oldDatabaseFile, ceDatabaseFile);
+ if (!newDbExists && preNDatabaseFile.exists()) {
+ removeOldDb = migratePreNDbToCe(preNDatabaseFile, ceDatabaseFile);
}
// Try to open and upgrade if necessary
- CeDatabaseHelper ceHelper = new CeDatabaseHelper(context, userId);
+ CeDatabaseHelper ceHelper = new CeDatabaseHelper(context, ceDatabaseFile.getPath());
ceHelper.getWritableDatabase();
ceHelper.close();
if (removeOldDb) {
// TODO STOPSHIP - backup file during testing. Remove file before the release
- Log.i(TAG, "Migration complete - creating backup of old db " + oldDatabaseFile);
- renameToBakFile(oldDatabaseFile);
+ Log.i(TAG, "Migration complete - creating backup of old db " + preNDatabaseFile);
+ renameToBakFile(preNDatabaseFile);
}
return ceHelper;
}
@@ -4771,12 +4863,14 @@
}
}
+ @VisibleForTesting
protected void installNotification(final int notificationId, final Notification n,
UserHandle user) {
((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
.notifyAsUser(null, notificationId, n, user);
}
+ @VisibleForTesting
protected void cancelNotification(int id, UserHandle user) {
long identityToken = clearCallingIdentity();
try {
@@ -5314,7 +5408,7 @@
HashMap<String, String> userDataForAccount = accounts.userDataCache.get(account);
if (userDataForAccount == null) {
// need to populate the cache for this account
- final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
+ final SQLiteDatabase db = accounts.openHelper.getReadableDatabaseUserIsUnlocked();
userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account);
accounts.userDataCache.put(account, userDataForAccount);
}
diff --git a/services/core/java/com/android/server/accounts/CryptoHelper.java b/services/core/java/com/android/server/accounts/CryptoHelper.java
index 2b59b74..2ade673 100644
--- a/services/core/java/com/android/server/accounts/CryptoHelper.java
+++ b/services/core/java/com/android/server/accounts/CryptoHelper.java
@@ -10,15 +10,12 @@
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
/**
* A crypto helper for encrypting and decrypting bundle with in-memory symmetric
@@ -30,15 +27,15 @@
private static final String KEY_CIPHER = "cipher";
private static final String KEY_MAC = "mac";
private static final String KEY_ALGORITHM = "AES";
+ private static final String KEY_IV = "iv";
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
private static final String MAC_ALGORITHM = "HMACSHA256";
private static final int IV_LENGTH = 16;
private static CryptoHelper sInstance;
// Keys used for encrypting and decrypting data returned in a Bundle.
- private final SecretKeySpec mCipherKeySpec;
- private final SecretKeySpec mMacKeySpec;
- private final IvParameterSpec mIv;
+ private final SecretKey mEncryptionKey;
+ private final SecretKey mMacKey;
/* default */ synchronized static CryptoHelper getInstance() throws NoSuchAlgorithmException {
if (sInstance == null) {
@@ -49,18 +46,10 @@
private CryptoHelper() throws NoSuchAlgorithmException {
KeyGenerator kgen = KeyGenerator.getInstance(KEY_ALGORITHM);
- SecretKey skey = kgen.generateKey();
- mCipherKeySpec = new SecretKeySpec(skey.getEncoded(), KEY_ALGORITHM);
-
+ mEncryptionKey = kgen.generateKey();
+ // Use a different key for mac-ing than encryption/decryption.
kgen = KeyGenerator.getInstance(MAC_ALGORITHM);
- skey = kgen.generateKey();
- mMacKeySpec = new SecretKeySpec(skey.getEncoded(), MAC_ALGORITHM);
-
- // Create random iv
- byte[] iv = new byte[IV_LENGTH];
- SecureRandom secureRandom = new SecureRandom();
- secureRandom.nextBytes(iv);
- mIv = new IvParameterSpec(iv);
+ mMacKey = kgen.generateKey();
}
@NonNull
@@ -68,16 +57,19 @@
Preconditions.checkNotNull(bundle, "Cannot encrypt null bundle.");
Parcel parcel = Parcel.obtain();
bundle.writeToParcel(parcel, 0);
- byte[] bytes = parcel.marshall();
+ byte[] clearBytes = parcel.marshall();
parcel.recycle();
+ Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
+ cipher.init(Cipher.ENCRYPT_MODE, mEncryptionKey);
+ byte[] encryptedBytes = cipher.doFinal(clearBytes);
+ byte[] iv = cipher.getIV();
+ byte[] mac = createMac(encryptedBytes, iv);
+
Bundle encryptedBundle = new Bundle();
-
- byte[] cipher = encrypt(bytes);
- byte[] mac = createMac(cipher);
-
- encryptedBundle.putByteArray(KEY_CIPHER, cipher);
+ encryptedBundle.putByteArray(KEY_CIPHER, encryptedBytes);
encryptedBundle.putByteArray(KEY_MAC, mac);
+ encryptedBundle.putByteArray(KEY_IV, iv);
return encryptedBundle;
}
@@ -85,19 +77,18 @@
@Nullable
/* default */ Bundle decryptBundle(@NonNull Bundle bundle) throws GeneralSecurityException {
Preconditions.checkNotNull(bundle, "Cannot decrypt null bundle.");
- byte[] cipherArray = bundle.getByteArray(KEY_CIPHER);
- byte[] macArray = bundle.getByteArray(KEY_MAC);
-
- if (!verifyMac(cipherArray, macArray)) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Escrow mac mismatched!");
- }
+ byte[] iv = bundle.getByteArray(KEY_IV);
+ byte[] encryptedBytes = bundle.getByteArray(KEY_CIPHER);
+ byte[] mac = bundle.getByteArray(KEY_MAC);
+ if (!verifyMac(encryptedBytes, iv, mac)) {
+ Log.w(TAG, "Escrow mac mismatched!");
return null;
}
+ IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
- cipher.init(Cipher.DECRYPT_MODE, mCipherKeySpec, mIv);
- byte[] decryptedBytes = cipher.doFinal(cipherArray);
+ cipher.init(Cipher.DECRYPT_MODE, mEncryptionKey, ivSpec);
+ byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
Parcel decryptedParcel = Parcel.obtain();
decryptedParcel.unmarshall(decryptedBytes, 0, decryptedBytes.length);
@@ -108,9 +99,8 @@
return decryptedBundle;
}
- private boolean verifyMac(@Nullable byte[] cipherArray, @Nullable byte[] macArray)
+ private boolean verifyMac(@Nullable byte[] cipherArray, @Nullable byte[] iv, @Nullable byte[] macArray)
throws GeneralSecurityException {
-
if (cipherArray == null || cipherArray.length == 0 || macArray == null
|| macArray.length == 0) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -118,23 +108,29 @@
}
return false;
}
- Mac mac = Mac.getInstance(MAC_ALGORITHM);
- mac.init(mMacKeySpec);
- mac.update(cipherArray);
- return Arrays.equals(macArray, mac.doFinal());
+ return constantTimeArrayEquals(macArray, createMac(cipherArray, iv));
}
@NonNull
- private byte[] encrypt(@NonNull byte[] data) throws GeneralSecurityException {
- Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
- cipher.init(Cipher.ENCRYPT_MODE, mCipherKeySpec, mIv);
- return cipher.doFinal(data);
+ private byte[] createMac(@NonNull byte[] cipher, @NonNull byte[] iv) throws GeneralSecurityException {
+ Mac mac = Mac.getInstance(MAC_ALGORITHM);
+ mac.init(mMacKey);
+ mac.update(cipher);
+ mac.update(iv);
+ return mac.doFinal();
}
- @NonNull
- private byte[] createMac(@NonNull byte[] cipher) throws GeneralSecurityException {
- Mac mac = Mac.getInstance(MAC_ALGORITHM);
- mac.init(mMacKeySpec);
- return mac.doFinal(cipher);
+ private static boolean constantTimeArrayEquals(byte[] a, byte[] b) {
+ if (a == null || b == null) {
+ return a == b;
+ }
+ if (a.length != b.length) {
+ return false;
+ }
+ boolean isEqual = true;
+ for (int i = 0; i < b.length; i++) {
+ isEqual &= (a[i] == b[i]);
+ }
+ return isEqual;
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0f48d21..9703d13 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -628,13 +628,16 @@
public Bundle result = null;
public AssistStructure structure = null;
public AssistContent content = null;
+ public Bundle receiverExtras;
+
public PendingAssistExtras(ActivityRecord _activity, Bundle _extras, Intent _intent,
- String _hint, IResultReceiver _receiver, int _userHandle) {
+ String _hint, IResultReceiver _receiver, Bundle _receiverExtras, int _userHandle) {
activity = _activity;
extras = _extras;
intent = _intent;
hint = _hint;
receiver = _receiver;
+ receiverExtras = _receiverExtras;
userHandle = _userHandle;
}
@Override
@@ -8792,6 +8795,7 @@
rti.bounds = new Rect(tr.mBounds);
}
rti.isDockable = tr.canGoInDockedStack();
+ rti.resizeMode = tr.mResizeMode;
ActivityRecord base = null;
ActivityRecord top = null;
@@ -9424,7 +9428,8 @@
if (prev != null && prev.isRecentsActivity()) {
task.setTaskToReturnTo(ActivityRecord.RECENTS_ACTIVITY_TYPE);
}
- mStackSupervisor.findTaskToMoveToFrontLocked(task, flags, options, "moveTaskToFront");
+ mStackSupervisor.findTaskToMoveToFrontLocked(task, flags, options, "moveTaskToFront",
+ false /* forceNonResizable */);
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -11804,7 +11809,7 @@
@Override
public Bundle getAssistContextExtras(int requestType) {
PendingAssistExtras pae = enqueueAssistContext(requestType, null, null, null,
- null, UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT);
+ null, null, true, UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT);
if (pae == null) {
return null;
}
@@ -11868,14 +11873,17 @@
@Override
public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver,
- IBinder activityToken) {
- return enqueueAssistContext(requestType, null, null, receiver, activityToken,
- UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_LONG_TIMEOUT) != null;
+ Bundle receiverExtras,
+ IBinder activityToken, boolean focused) {
+ return enqueueAssistContext(requestType, null, null, receiver, receiverExtras,
+ activityToken, focused,
+ UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_LONG_TIMEOUT)
+ != null;
}
private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint,
- IResultReceiver receiver, IBinder activityToken, int userHandle, Bundle args,
- long timeout) {
+ IResultReceiver receiver, Bundle receiverExtras, IBinder activityToken, boolean focused,
+ int userHandle, Bundle args, long timeout) {
enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
"enqueueAssistContext()");
synchronized (this) {
@@ -11888,14 +11896,24 @@
Slog.w(TAG, "getAssistContextExtras failed: no process for " + activity);
return null;
}
- if (activityToken != null) {
- ActivityRecord caller = ActivityRecord.forTokenLocked(activityToken);
- if (activity != caller) {
- Slog.w(TAG, "enqueueAssistContext failed: caller " + caller
- + " is not current top " + activity);
+ if (focused) {
+ if (activityToken != null) {
+ ActivityRecord caller = ActivityRecord.forTokenLocked(activityToken);
+ if (activity != caller) {
+ Slog.w(TAG, "enqueueAssistContext failed: caller " + caller
+ + " is not current top " + activity);
+ return null;
+ }
+ }
+ } else {
+ activity = ActivityRecord.forTokenLocked(activityToken);
+ if (activity == null) {
+ Slog.w(TAG, "enqueueAssistContext failed: activity for token=" + activityToken
+ + " couldn't be found");
return null;
}
}
+
PendingAssistExtras pae;
Bundle extras = new Bundle();
if (args != null) {
@@ -11903,7 +11921,8 @@
}
extras.putString(Intent.EXTRA_ASSIST_PACKAGE, activity.packageName);
extras.putInt(Intent.EXTRA_ASSIST_UID, activity.app.uid);
- pae = new PendingAssistExtras(activity, extras, intent, hint, receiver, userHandle);
+ pae = new PendingAssistExtras(activity, extras, intent, hint, receiver, receiverExtras,
+ userHandle);
try {
activity.app.thread.requestAssistContextExtras(activity.appToken, pae,
requestType);
@@ -11973,9 +11992,11 @@
if ((sendReceiver=pae.receiver) != null) {
// Caller wants result sent back to them.
sendBundle = new Bundle();
- sendBundle.putBundle("data", pae.extras);
- sendBundle.putParcelable("structure", pae.structure);
- sendBundle.putParcelable("content", pae.content);
+ sendBundle.putBundle(VoiceInteractionSession.KEY_DATA, pae.extras);
+ sendBundle.putParcelable(VoiceInteractionSession.KEY_STRUCTURE, pae.structure);
+ sendBundle.putParcelable(VoiceInteractionSession.KEY_CONTENT, pae.content);
+ sendBundle.putBundle(VoiceInteractionSession.KEY_RECEIVER_EXTRAS,
+ pae.receiverExtras);
}
}
if (sendReceiver != null) {
@@ -12005,8 +12026,8 @@
public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle,
Bundle args) {
- return enqueueAssistContext(requestType, intent, hint, null, null, userHandle, args,
- PENDING_ASSIST_EXTRAS_TIMEOUT) != null;
+ return enqueueAssistContext(requestType, intent, hint, null, null, null, true,
+ userHandle, args, PENDING_ASSIST_EXTRAS_TIMEOUT) != null;
}
public void registerProcessObserver(IProcessObserver observer) {
@@ -13164,6 +13185,9 @@
}
}
+ private volatile long mWtfClusterStart;
+ private volatile int mWtfClusterCount;
+
/**
* Write a description of an error (crash, WTF, ANR) to the drop box.
* @param eventType to include in the drop box tag ("crash", "wtf", etc.)
@@ -13190,6 +13214,16 @@
// Exit early if the dropbox isn't configured to accept this report type.
if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
+ // Rate-limit how often we're willing to do the heavy lifting below to
+ // collect and record logs; currently 5 logs per 10 second period.
+ final long now = SystemClock.elapsedRealtime();
+ if (now - mWtfClusterStart > 10 * DateUtils.SECOND_IN_MILLIS) {
+ mWtfClusterStart = now;
+ mWtfClusterCount = 1;
+ } else {
+ if (mWtfClusterCount++ >= 5) return;
+ }
+
final StringBuilder sb = new StringBuilder(1024);
appendDropBoxProcessHeaders(process, processName, sb);
if (process != null) {
@@ -17131,7 +17165,7 @@
// but historically it has not been protected and apps may be using it
// to poke their own app widget. So, instead of making it protected,
// just limit it to the caller.
- if (callerApp == null) {
+ if (callerPackage == null) {
String msg = "Permission Denial: not allowed to send broadcast "
+ action + " from unknown caller.";
Slog.w(TAG, msg);
@@ -17140,17 +17174,17 @@
// They are good enough to send to an explicit component... verify
// it is being sent to the calling app.
if (!intent.getComponent().getPackageName().equals(
- callerApp.info.packageName)) {
+ callerPackage)) {
String msg = "Permission Denial: not allowed to send broadcast "
+ action + " to "
+ intent.getComponent().getPackageName() + " from "
- + callerApp.info.packageName;
+ + callerPackage;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
} else {
// Limit broadcast to their own package.
- intent.setPackage(callerApp.info.packageName);
+ intent.setPackage(callerPackage);
}
}
}
@@ -17607,7 +17641,7 @@
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
- requiredPermissions, appOp, null, serialized, sticky,
+ requiredPermissions, appOp, bOptions, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
@@ -20947,6 +20981,13 @@
mStackSupervisor.notifyAppTransitionDone();
}
}
+
+ @Override
+ public List<IBinder> getTopVisibleActivities() {
+ synchronized (ActivityManagerService.this) {
+ return mStackSupervisor.getTopVisibleActivities();
+ }
+ }
}
private final class SleepTokenImpl extends SleepToken {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 2e9947a..837a1c1 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -4776,6 +4776,7 @@
ci.numActivities = numActivities;
ci.numRunning = numRunning;
ci.isDockable = task.canGoInDockedStack();
+ ci.resizeMode = task.mResizeMode;
list.add(ci);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 8395083..ab3a0b3 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -98,6 +98,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -1759,8 +1760,8 @@
}
}
- void findTaskToMoveToFrontLocked(
- TaskRecord task, int flags, ActivityOptions options, String reason) {
+ void findTaskToMoveToFrontLocked(TaskRecord task, int flags, ActivityOptions options,
+ String reason, boolean forceNonResizeable) {
if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
mUserLeaving = true;
}
@@ -1811,7 +1812,8 @@
if (DEBUG_STACK) Slog.d(TAG_STACK,
"findTaskToMoveToFront: moved to front of stack=" + task.stack);
- handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, task.stack.mStackId);
+ handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, task.stack.mStackId,
+ forceNonResizeable);
}
boolean canUseActivityOptionsLaunchBounds(ActivityOptions options, int launchStackId) {
@@ -3249,13 +3251,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) {
@@ -3364,19 +3362,25 @@
}
}
+ void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredStackId, int actualStackId) {
+ handleNonResizableTaskIfNeeded(task, preferredStackId, actualStackId,
+ false /* forceNonResizable */);
+ }
+
void handleNonResizableTaskIfNeeded(
- TaskRecord task, int preferredStackId, int actualStackId) {
+ TaskRecord task, int preferredStackId, int actualStackId, boolean forceNonResizable) {
if ((!isStackDockedInEffect(actualStackId) && preferredStackId != DOCKED_STACK_ID)
|| task.isHomeTask()) {
return;
}
- if (!task.canGoInDockedStack()) {
+ if (!task.canGoInDockedStack() || forceNonResizable) {
// Display a warning toast that we tried to put a non-dockable task in the docked stack.
mService.mHandler.sendEmptyMessage(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
- // Dismiss docked stack.
- mService.moveTasksToFullscreenStack(DOCKED_STACK_ID, false);
+ // Dismiss docked stack. If task appeared to be in docked stack but is not resizable -
+ // we need to move it to top of fullscreen stack, otherwise it will be covered.
+ mService.moveTasksToFullscreenStack(DOCKED_STACK_ID, actualStackId == DOCKED_STACK_ID);
} else if (task.mResizeMode == RESIZE_MODE_FORCE_RESIZEABLE) {
String packageName = task.getTopActivity() != null
? task.getTopActivity().appInfo.packageName : null;
@@ -3447,8 +3451,12 @@
}
if (andResume) {
- findTaskToMoveToFrontLocked(task, 0, null, reason);
+ findTaskToMoveToFrontLocked(task, 0, null, reason,
+ lockTaskModeState != LOCK_TASK_MODE_NONE);
resumeFocusedStackTopActivityLocked();
+ } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
+ handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, task.stack.mStackId,
+ true /* forceNonResizable */);
}
}
@@ -4252,6 +4260,7 @@
// Work Challenge is present) let startActivityInPackage handle the intercepting.
if (!mService.mUserController.shouldConfirmCredentials(task.userId)
&& task.getRootActivity() != null) {
+ mActivityMetricsLogger.notifyActivityLaunching();
mService.moveTaskToFrontLocked(task.taskId, 0, bOptions);
// If we are launching the task in the docked stack, put it into resizing mode so
@@ -4274,4 +4283,31 @@
}
return result;
}
+
+ /**
+ * @return a list of activities which are the top ones in each visible stack. The first
+ * entry will be the focused activity.
+ */
+ public List<IBinder> getTopVisibleActivities() {
+ final ActivityDisplay display = mActivityDisplays.get(Display.DEFAULT_DISPLAY);
+ if (display == null) {
+ return Collections.EMPTY_LIST;
+ }
+ ArrayList<IBinder> topActivityTokens = new ArrayList<>();
+ final ArrayList<ActivityStack> stacks = display.mStacks;
+ for (int i = stacks.size() - 1; i >= 0; i--) {
+ ActivityStack stack = stacks.get(i);
+ if (stack.getStackVisibilityLocked(null) == ActivityStack.STACK_VISIBLE) {
+ ActivityRecord top = stack.topActivity();
+ if (top != null) {
+ if (stack == mFocusedStack) {
+ topActivityTokens.add(0, top.appToken);
+ } else {
+ topActivityTokens.add(top.appToken);
+ }
+ }
+ }
+ }
+ return topActivityTokens;
+ }
}
diff --git a/services/core/java/com/android/server/am/PreBootBroadcaster.java b/services/core/java/com/android/server/am/PreBootBroadcaster.java
index 1825c88..0e192ea 100644
--- a/services/core/java/com/android/server/am/PreBootBroadcaster.java
+++ b/services/core/java/com/android/server/am/PreBootBroadcaster.java
@@ -69,6 +69,12 @@
return;
}
+ if (!mService.isUserRunning(mUserId, 0)) {
+ Slog.i(TAG, "User " + mUserId + " is no longer running; skipping remaining receivers");
+ onFinished();
+ return;
+ }
+
final ResolveInfo ri = mTargets.get(mIndex++);
final ComponentName componentName = ri.activityInfo.getComponentName();
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 bea26c7..5ebb9a7 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -278,6 +278,31 @@
// Dispatch unlocked to system services
mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0));
+ // Dispatch unlocked to external apps
+ final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED);
+ unlockedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ unlockedIntent.addFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+ mService.broadcastIntentLocked(null, null, unlockedIntent, null, null, 0, null,
+ null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
+ userId);
+
+ if (getUserInfo(userId).isManagedProfile()) {
+ UserInfo parent = getUserManager().getProfileParent(userId);
+ if (parent != null) {
+ final Intent profileUnlockedIntent = new Intent(
+ Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
+ profileUnlockedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId));
+ profileUnlockedIntent.addFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
+ mService.broadcastIntentLocked(null, null, profileUnlockedIntent,
+ null, null, 0, null, null, null, AppOpsManager.OP_NONE,
+ null, false, false, MY_PID, SYSTEM_UID,
+ parent.id);
+ }
+ }
+
// Send PRE_BOOT broadcasts if fingerprint changed
final UserInfo info = getUserInfo(userId);
if (!Objects.equals(info.lastLoggedInFingerprint, Build.FINGERPRINT)) {
@@ -320,31 +345,6 @@
// Remember that we logged in
mUserManager.onUserLoggedIn(userId);
- // Dispatch unlocked to external apps
- final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED);
- unlockedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
- unlockedIntent.addFlags(
- Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
- mService.broadcastIntentLocked(null, null, unlockedIntent, null, null, 0, null,
- null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
- userId);
-
- if (getUserInfo(userId).isManagedProfile()) {
- UserInfo parent = getUserManager().getProfileParent(userId);
- if (parent != null) {
- final Intent profileUnlockedIntent = new Intent(
- Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
- profileUnlockedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId));
- profileUnlockedIntent.addFlags(
- Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_FOREGROUND);
- mService.broadcastIntentLocked(null, null, profileUnlockedIntent,
- null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, MY_PID, SYSTEM_UID,
- parent.id);
- }
- }
-
final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
@@ -893,8 +893,9 @@
boolean unlockUserCleared(final int userId, byte[] token, byte[] secret,
ProgressReporter progress) {
synchronized (mService) {
- // Bail if already running unlocked
+ // Bail if already running unlocked, or if not running at all
final UserState uss = mStartedUsers.get(userId);
+ if (uss == null) return false;
switch (uss.state) {
case STATE_RUNNING_UNLOCKING:
case STATE_RUNNING_UNLOCKED:
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 58db985..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;
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/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index bbb162e..d330756 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -120,8 +120,9 @@
/**
* Inform ConnectivityService that the network has been tested.
- * obj = NetworkAgentInfo
+ * obj = String representing URL that Internet probe was redirect to, if it was redirected.
* arg1 = One of the NETWORK_TESTED_RESULT_* constants.
+ * arg2 = NetID.
*/
public static final int EVENT_NETWORK_TESTED = BASE + 2;
@@ -334,8 +335,8 @@
mDontDisplaySigninNotification = true;
mUserDoesNotWant = true;
mConnectivityServiceHandler.sendMessage(obtainMessage(
- EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID, 0,
- mNetworkAgentInfo));
+ EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID,
+ mNetworkAgentInfo.network.netId, null));
// TODO: Should teardown network.
mUidResponsibleForReeval = 0;
transitionTo(mEvaluatingState);
@@ -358,7 +359,7 @@
CaptivePortalStateChangeEvent.logEvent(
CaptivePortalStateChangeEvent.NETWORK_MONITOR_VALIDATED);
mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
- NETWORK_TEST_RESULT_VALID, 0, mNetworkAgentInfo));
+ NETWORK_TEST_RESULT_VALID, mNetworkAgentInfo.network.netId, null));
}
@Override
@@ -412,6 +413,21 @@
}
}
+ /**
+ * Result of calling isCaptivePortal().
+ * @hide
+ */
+ @VisibleForTesting
+ public static final class CaptivePortalProbeResult {
+ final int mHttpResponseCode; // HTTP response code returned from Internet probe.
+ final String mRedirectUrl; // Redirect destination returned from Internet probe.
+
+ public CaptivePortalProbeResult(int httpResponseCode, String redirectUrl) {
+ mHttpResponseCode = httpResponseCode;
+ mRedirectUrl = redirectUrl;
+ }
+ }
+
// Being in the EvaluatingState State indicates the Network is being evaluated for internet
// connectivity, or that the user has indicated that this network is unwanted.
private class EvaluatingState extends State {
@@ -464,19 +480,23 @@
// IPv6) could each take SOCKET_TIMEOUT_MS. During this time this StateMachine
// will be unresponsive. isCaptivePortal() could be executed on another Thread
// if this is found to cause problems.
- int httpResponseCode = isCaptivePortal();
+ CaptivePortalProbeResult probeResult = isCaptivePortal();
CaptivePortalCheckResultEvent.logEvent(mNetworkAgentInfo.network.netId,
- httpResponseCode);
- if (httpResponseCode == 204) {
+ probeResult.mHttpResponseCode);
+ if (probeResult.mHttpResponseCode == 204) {
transitionTo(mValidatedState);
- } else if (httpResponseCode >= 200 && httpResponseCode <= 399) {
+ } else if (probeResult.mHttpResponseCode >= 200 &&
+ probeResult.mHttpResponseCode <= 399) {
+ mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
+ NETWORK_TEST_RESULT_INVALID, mNetworkAgentInfo.network.netId,
+ probeResult.mRedirectUrl));
transitionTo(mCaptivePortalState);
} else {
final Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
sendMessageDelayed(msg, mReevaluateDelayMs);
mConnectivityServiceHandler.sendMessage(obtainMessage(
- EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID, 0,
- mNetworkAgentInfo));
+ EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID,
+ mNetworkAgentInfo.network.netId, probeResult.mRedirectUrl));
if (mAttempts >= BLAME_FOR_EVALUATION_ATTEMPTS) {
// Don't continue to blame UID forever.
TrafficStats.clearThreadStatsUid();
@@ -533,8 +553,6 @@
@Override
public void enter() {
- mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
- NETWORK_TEST_RESULT_INVALID, 0, mNetworkAgentInfo));
// Don't annoy user with sign-in notifications.
if (mDontDisplaySigninNotification) return;
// Create a CustomIntentReceiver that sends us a
@@ -639,11 +657,12 @@
* Returns HTTP response code.
*/
@VisibleForTesting
- protected int isCaptivePortal() {
- if (!mIsCaptivePortalCheckEnabled) return 204;
+ protected CaptivePortalProbeResult isCaptivePortal() {
+ if (!mIsCaptivePortalCheckEnabled) return new CaptivePortalProbeResult(204, null);
HttpURLConnection urlConnection = null;
int httpResponseCode = 599;
+ String redirectUrl = null;
try {
URL url = new URL(getCaptivePortalServerUrl(mContext));
// On networks with a PAC instead of fetching a URL that should result in a 204
@@ -699,6 +718,7 @@
long requestTimestamp = SystemClock.elapsedRealtime();
httpResponseCode = urlConnection.getResponseCode();
+ redirectUrl = urlConnection.getHeaderField("location");
// Time how long it takes to get a response to our request
long responseTimestamp = SystemClock.elapsedRealtime();
@@ -739,7 +759,7 @@
urlConnection.disconnect();
}
}
- return httpResponseCode;
+ return new CaptivePortalProbeResult(httpResponseCode, redirectUrl);
}
/**
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/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 6e7ea99..03eb019 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -77,7 +77,7 @@
static final boolean DEBUG = false;
public static class Lifecycle extends SystemService {
- private ContentService mContentService;
+ private ContentService mService;
public Lifecycle(Context context) {
super(context);
@@ -87,14 +87,21 @@
public void onStart() {
final boolean factoryTest = (FactoryTest
.getMode() == FactoryTest.FACTORY_TEST_LOW_LEVEL);
- mContentService = new ContentService(getContext(), factoryTest);
- publishBinderService(ContentResolver.CONTENT_SERVICE_NAME, mContentService);
+ mService = new ContentService(getContext(), factoryTest);
+ publishBinderService(ContentResolver.CONTENT_SERVICE_NAME, mService);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
+ mService.systemReady();
+ }
}
@Override
public void onCleanupUser(int userHandle) {
- synchronized (mContentService.mCache) {
- mContentService.mCache.remove(userHandle);
+ synchronized (mService.mCache) {
+ mService.mCache.remove(userHandle);
}
}
}
@@ -265,7 +272,7 @@
localeFilter, null, null);
}
- public void systemReady() {
+ void systemReady() {
getSyncManager();
}
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index db41a54..8af0af0 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1402,24 +1402,12 @@
}
}
- 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);
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index fb23265..bc3fc6a 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -826,35 +826,6 @@
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 3d8bf51..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;
}
}
diff --git a/services/core/java/com/android/server/job/JobPackageTracker.java b/services/core/java/com/android/server/job/JobPackageTracker.java
new file mode 100644
index 0000000..e5a2095
--- /dev/null
+++ b/services/core/java/com/android/server/job/JobPackageTracker.java
@@ -0,0 +1,361 @@
+/*
+ * 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.job;
+
+import android.app.job.JobInfo;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.text.format.DateFormat;
+import android.util.ArrayMap;
+import android.util.SparseArray;
+import android.util.TimeUtils;
+import com.android.server.job.controllers.JobStatus;
+
+import java.io.PrintWriter;
+
+public final class JobPackageTracker {
+ // We batch every 30 minutes.
+ static final long BATCHING_TIME = 30*60*1000;
+ // Number of historical data sets we keep.
+ static final int NUM_HISTORY = 5;
+
+ DataSet mCurDataSet = new DataSet();
+ DataSet[] mLastDataSets = new DataSet[NUM_HISTORY];
+
+ final static class PackageEntry {
+ long pastActiveTime;
+ long activeStartTime;
+ int activeCount;
+ boolean hadActive;
+ long pastActiveTopTime;
+ long activeTopStartTime;
+ int activeTopCount;
+ boolean hadActiveTop;
+ long pastPendingTime;
+ long pendingStartTime;
+ int pendingCount;
+ boolean hadPending;
+
+ public long getActiveTime(long now) {
+ long time = pastActiveTime;
+ if (activeCount > 0) {
+ time += now - activeStartTime;
+ }
+ return time;
+ }
+
+ public long getActiveTopTime(long now) {
+ long time = pastActiveTopTime;
+ if (activeTopCount > 0) {
+ time += now - activeTopStartTime;
+ }
+ return time;
+ }
+
+ public long getPendingTime(long now) {
+ long time = pastPendingTime;
+ if (pendingCount > 0) {
+ time += now - pendingStartTime;
+ }
+ return time;
+ }
+ }
+
+ final static class DataSet {
+ final SparseArray<ArrayMap<String, PackageEntry>> mEntries = new SparseArray<>();
+ final long mStartUptimeTime;
+ final long mStartElapsedTime;
+ final long mStartClockTime;
+ long mSummedTime;
+
+ public DataSet(DataSet otherTimes) {
+ mStartUptimeTime = otherTimes.mStartUptimeTime;
+ mStartElapsedTime = otherTimes.mStartElapsedTime;
+ mStartClockTime = otherTimes.mStartClockTime;
+ }
+
+ public DataSet() {
+ mStartUptimeTime = SystemClock.uptimeMillis();
+ mStartElapsedTime = SystemClock.elapsedRealtime();
+ mStartClockTime = System.currentTimeMillis();
+ }
+
+ private PackageEntry getOrCreateEntry(int uid, String pkg) {
+ ArrayMap<String, PackageEntry> uidMap = mEntries.get(uid);
+ if (uidMap == null) {
+ uidMap = new ArrayMap<>();
+ mEntries.put(uid, uidMap);
+ }
+ PackageEntry entry = uidMap.get(pkg);
+ if (entry == null) {
+ entry = new PackageEntry();
+ uidMap.put(pkg, entry);
+ }
+ return entry;
+ }
+
+ public PackageEntry getEntry(int uid, String pkg) {
+ ArrayMap<String, PackageEntry> uidMap = mEntries.get(uid);
+ if (uidMap == null) {
+ return null;
+ }
+ return uidMap.get(pkg);
+ }
+
+ long getTotalTime(long now) {
+ if (mSummedTime > 0) {
+ return mSummedTime;
+ }
+ return now - mStartUptimeTime;
+ }
+
+ void incPending(int uid, String pkg, long now) {
+ PackageEntry pe = getOrCreateEntry(uid, pkg);
+ if (pe.pendingCount == 0) {
+ pe.pendingStartTime = now;
+ }
+ pe.pendingCount++;
+ }
+
+ void decPending(int uid, String pkg, long now) {
+ PackageEntry pe = getOrCreateEntry(uid, pkg);
+ if (pe.pendingCount == 1) {
+ pe.pastPendingTime += now - pe.pendingStartTime;
+ }
+ pe.pendingCount--;
+ }
+
+ void incActive(int uid, String pkg, long now) {
+ PackageEntry pe = getOrCreateEntry(uid, pkg);
+ if (pe.activeCount == 0) {
+ pe.activeStartTime = now;
+ }
+ pe.activeCount++;
+ }
+
+ void decActive(int uid, String pkg, long now) {
+ PackageEntry pe = getOrCreateEntry(uid, pkg);
+ if (pe.activeCount == 1) {
+ pe.pastActiveTime += now - pe.activeStartTime;
+ }
+ pe.activeCount--;
+ }
+
+ void incActiveTop(int uid, String pkg, long now) {
+ PackageEntry pe = getOrCreateEntry(uid, pkg);
+ if (pe.activeTopCount == 0) {
+ pe.activeTopStartTime = now;
+ }
+ pe.activeTopCount++;
+ }
+
+ void decActiveTop(int uid, String pkg, long now) {
+ PackageEntry pe = getOrCreateEntry(uid, pkg);
+ if (pe.activeTopCount == 1) {
+ pe.pastActiveTopTime += now - pe.activeTopStartTime;
+ }
+ pe.activeTopCount--;
+ }
+
+ void finish(DataSet next, long now) {
+ for (int i = mEntries.size() - 1; i >= 0; i--) {
+ ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i);
+ for (int j = uidMap.size() - 1; j >= 0; j--) {
+ PackageEntry pe = uidMap.valueAt(j);
+ if (pe.activeCount > 0 || pe.activeTopCount > 0 || pe.pendingCount > 0) {
+ // Propagate existing activity in to next data set.
+ PackageEntry nextPe = next.getOrCreateEntry(mEntries.keyAt(i), uidMap.keyAt(j));
+ nextPe.activeStartTime = now;
+ nextPe.activeCount = pe.activeCount;
+ nextPe.activeTopStartTime = now;
+ nextPe.activeTopCount = pe.activeTopCount;
+ nextPe.pendingStartTime = now;
+ nextPe.pendingCount = pe.pendingCount;
+ // Finish it off.
+ if (pe.activeCount > 0) {
+ pe.pastActiveTime += now - pe.activeStartTime;
+ pe.activeCount = 0;
+ }
+ if (pe.activeTopCount > 0) {
+ pe.pastActiveTopTime += now - pe.activeTopStartTime;
+ pe.activeTopCount = 0;
+ }
+ if (pe.pendingCount > 0) {
+ pe.pastPendingTime += now - pe.pendingStartTime;
+ pe.pendingCount = 0;
+ }
+ }
+ }
+ }
+ }
+
+ void addTo(DataSet out, long now) {
+ out.mSummedTime += getTotalTime(now);
+ for (int i = mEntries.size() - 1; i >= 0; i--) {
+ ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i);
+ for (int j = uidMap.size() - 1; j >= 0; j--) {
+ PackageEntry pe = uidMap.valueAt(j);
+ PackageEntry outPe = out.getOrCreateEntry(mEntries.keyAt(i), uidMap.keyAt(j));
+ outPe.pastActiveTime += pe.pastActiveTime;
+ outPe.pastActiveTopTime += pe.pastActiveTopTime;
+ outPe.pastPendingTime += pe.pastPendingTime;
+ if (pe.activeCount > 0) {
+ outPe.pastActiveTime += now - pe.activeStartTime;
+ outPe.hadActive = true;
+ }
+ if (pe.activeTopCount > 0) {
+ outPe.pastActiveTopTime += now - pe.activeTopStartTime;
+ outPe.hadActiveTop = true;
+ }
+ if (pe.pendingCount > 0) {
+ outPe.pastPendingTime += now - pe.pendingStartTime;
+ outPe.hadPending = true;
+ }
+ }
+ }
+ }
+
+ void printDuration(PrintWriter pw, long period, long duration, String suffix) {
+ float fraction = duration / (float) period;
+ int percent = (int) ((fraction * 100) + .5f);
+ if (percent > 0) {
+ pw.print(" ");
+ pw.print(percent);
+ pw.print("% ");
+ pw.print(suffix);
+ }
+ }
+
+ void dump(PrintWriter pw, String header, String prefix, long now, long nowEllapsed) {
+ final long period = getTotalTime(now);
+ pw.print(prefix); pw.print(header); pw.print(" at ");
+ pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", mStartClockTime).toString());
+ pw.print(" (");
+ TimeUtils.formatDuration(mStartElapsedTime, nowEllapsed, pw);
+ pw.print(") over ");
+ TimeUtils.formatDuration(period, pw);
+ pw.println(":");
+ final int NE = mEntries.size();
+ for (int i = 0; i < NE; i++) {
+ ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i);
+ final int NP = uidMap.size();
+ for (int j = 0; j < NP; j++) {
+ PackageEntry pe = uidMap.valueAt(j);
+ pw.print(prefix); pw.print(" ");
+ UserHandle.formatUid(pw, mEntries.keyAt(i));
+ pw.print(" / "); pw.print(uidMap.keyAt(j));
+ pw.print(":");
+ printDuration(pw, period, pe.getPendingTime(now), "pending");
+ printDuration(pw, period, pe.getActiveTime(now), "active");
+ printDuration(pw, period, pe.getActiveTopTime(now), "active-top");
+ if (pe.pendingCount > 0 || pe.hadPending) {
+ pw.print(" (pending)");
+ }
+ if (pe.activeCount > 0 || pe.hadActive) {
+ pw.print(" (active)");
+ }
+ if (pe.activeTopCount > 0 || pe.hadActiveTop) {
+ pw.print(" (active-top)");
+ }
+ pw.println();
+ }
+ }
+ }
+ }
+
+ void rebatchIfNeeded(long now) {
+ long totalTime = mCurDataSet.getTotalTime(now);
+ if (totalTime > BATCHING_TIME) {
+ DataSet last = mCurDataSet;
+ last.mSummedTime = totalTime;
+ mCurDataSet = new DataSet();
+ last.finish(mCurDataSet, now);
+ System.arraycopy(mLastDataSets, 0, mLastDataSets, 1, mLastDataSets.length-1);
+ mLastDataSets[0] = last;
+ }
+ }
+
+ public void notePending(JobStatus job) {
+ final long now = SystemClock.uptimeMillis();
+ rebatchIfNeeded(now);
+ mCurDataSet.incPending(job.getSourceUid(), job.getSourcePackageName(), now);
+ }
+
+ public void noteNonpending(JobStatus job) {
+ final long now = SystemClock.uptimeMillis();
+ mCurDataSet.decPending(job.getSourceUid(), job.getSourcePackageName(), now);
+ rebatchIfNeeded(now);
+ }
+
+ public void noteActive(JobStatus job) {
+ final long now = SystemClock.uptimeMillis();
+ rebatchIfNeeded(now);
+ if (job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
+ mCurDataSet.incActiveTop(job.getSourceUid(), job.getSourcePackageName(), now);
+ } else {
+ mCurDataSet.incActive(job.getSourceUid(), job.getSourcePackageName(), now);
+ }
+ }
+
+ public void noteInactive(JobStatus job) {
+ final long now = SystemClock.uptimeMillis();
+ if (job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
+ mCurDataSet.decActiveTop(job.getSourceUid(), job.getSourcePackageName(), now);
+ } else {
+ mCurDataSet.decActive(job.getSourceUid(), job.getSourcePackageName(), now);
+ }
+ rebatchIfNeeded(now);
+ }
+
+ public float getLoadFactor(JobStatus job) {
+ final int uid = job.getSourceUid();
+ final String pkg = job.getSourcePackageName();
+ PackageEntry cur = mCurDataSet.getEntry(uid, pkg);
+ PackageEntry last = mLastDataSets[0] != null ? mLastDataSets[0].getEntry(uid, pkg) : null;
+ if (cur == null && last == null) {
+ return 0;
+ }
+ final long now = SystemClock.uptimeMillis();
+ long time = cur.getActiveTime(now) + cur.getPendingTime(now);
+ long period = mCurDataSet.getTotalTime(now);
+ if (last != null) {
+ time += last.getActiveTime(now) + last.getPendingTime(now);
+ period += mLastDataSets[0].getTotalTime(now);
+ }
+ return time / (float)period;
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ final long now = SystemClock.uptimeMillis();
+ final long nowEllapsed = SystemClock.elapsedRealtime();
+ final DataSet total;
+ if (mLastDataSets[0] != null) {
+ total = new DataSet(mLastDataSets[0]);
+ mLastDataSets[0].addTo(total, now);
+ } else {
+ total = new DataSet(mCurDataSet);
+ }
+ mCurDataSet.addTo(total, now);
+ for (int i = 1; i < mLastDataSets.length; i++) {
+ if (mLastDataSets[i] != null) {
+ mLastDataSets[i].dump(pw, "Historical stats", prefix, now, nowEllapsed);
+ pw.println();
+ }
+ }
+ total.dump(pw, "Current stats", prefix, now, nowEllapsed);
+ }
+}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index b235002..7df8ffd 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -93,16 +93,24 @@
public static final boolean DEBUG = false;
/** The maximum number of concurrent jobs we run at one time. */
- private static final int MAX_JOB_CONTEXTS_COUNT = 8;
+ private static final int MAX_JOB_CONTEXTS_COUNT = 12;
+ /** The number of MAX_JOB_CONTEXTS_COUNT we reserve for the foreground app. */
+ private static final int FG_JOB_CONTEXTS_COUNT = 4;
/** Enforce a per-app limit on scheduled jobs? */
private static final boolean ENFORCE_MAX_JOBS = true;
/** The maximum number of jobs that we allow an unprivileged app to schedule */
private static final int MAX_JOBS_PER_APP = 100;
+ /** This is the job execution factor that is considered to be heavy use of the system. */
+ private static final float HEAVY_USE_FACTOR = .9f;
+ /** This is the job execution factor that is considered to be moderate use of the system. */
+ private static final float MODERATE_USE_FACTOR = .5f;
/** Global local for all job scheduler state. */
final Object mLock = new Object();
/** Master list of jobs. */
final JobStore mJobs;
+ /** Tracking amount of time each package runs for. */
+ final JobPackageTracker mJobPackageTracker = new JobPackageTracker();
static final int MSG_JOB_EXPIRED = 0;
static final int MSG_CHECK_JOB = 1;
@@ -173,7 +181,7 @@
* Current limit on the number of concurrent JobServiceContext entries we want to
* keep actively running a job.
*/
- int mMaxActiveJobs = MAX_JOB_CONTEXTS_COUNT - 2;
+ int mMaxActiveJobs = MAX_JOB_CONTEXTS_COUNT - FG_JOB_CONTEXTS_COUNT;
/**
* Which uids are currently in the foreground.
@@ -249,6 +257,10 @@
return mLock;
}
+ public JobStore getJobStore() {
+ return mJobs;
+ }
+
@Override
public void onStartUser(int userHandle) {
mStartedUsers = ArrayUtils.appendInt(mStartedUsers, userHandle);
@@ -386,7 +398,9 @@
stopTrackingJob(cancelled, incomingJob, true /* writeBack */);
synchronized (mLock) {
// Remove from pending queue.
- mPendingJobs.remove(cancelled);
+ if (mPendingJobs.remove(cancelled)) {
+ mJobPackageTracker.noteNonpending(cancelled);
+ }
// Cancel if running.
stopJobOnServiceContextLocked(cancelled, JobParameters.REASON_CANCELED);
reportActive();
@@ -518,7 +532,7 @@
// Create the "runners".
for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) {
mActiveServices.add(
- new JobServiceContext(this, mBatteryStats,
+ new JobServiceContext(this, mBatteryStats, mJobPackageTracker,
getContext().getMainLooper()));
}
// Attach jobs to their controllers.
@@ -604,6 +618,20 @@
return false;
}
+ void noteJobsPending(List<JobStatus> jobs) {
+ for (int i = jobs.size() - 1; i >= 0; i--) {
+ JobStatus job = jobs.get(i);
+ mJobPackageTracker.notePending(job);
+ }
+ }
+
+ void noteJobsNonpending(List<JobStatus> jobs) {
+ for (int i = jobs.size() - 1; i >= 0; i--) {
+ JobStatus job = jobs.get(i);
+ mJobPackageTracker.noteNonpending(job);
+ }
+ }
+
/**
* Reschedules the given job based on the job's backoff policy. It doesn't make sense to
* specify an override deadline on a failed job (the failed job will run even though it's not
@@ -759,6 +787,7 @@
// state is such that all ready jobs should be run immediately.
if (runNow != null && !mPendingJobs.contains(runNow)
&& mJobs.containsJob(runNow)) {
+ mJobPackageTracker.notePending(runNow);
mPendingJobs.add(runNow);
}
queueReadyJobsForExecutionLockedH();
@@ -797,6 +826,7 @@
if (DEBUG) {
Slog.d(TAG, "queuing all ready jobs for execution:");
}
+ noteJobsNonpending(mPendingJobs);
mPendingJobs.clear();
mJobs.forEachJob(mReadyQueueFunctor);
mReadyQueueFunctor.postProcess();
@@ -832,6 +862,7 @@
public void postProcess() {
if (newReadyJobs != null) {
+ noteJobsPending(newReadyJobs);
mPendingJobs.addAll(newReadyJobs);
}
newReadyJobs = null;
@@ -910,6 +941,7 @@
if (DEBUG) {
Slog.d(TAG, "maybeQueueReadyJobsForExecutionLockedH: Running jobs.");
}
+ noteJobsPending(runnableJobs);
mPendingJobs.addAll(runnableJobs);
} else {
if (DEBUG) {
@@ -935,6 +967,7 @@
private void maybeQueueReadyJobsForExecutionLockedH() {
if (DEBUG) Slog.d(TAG, "Maybe queuing ready jobs...");
+ noteJobsNonpending(mPendingJobs);
mPendingJobs.clear();
mJobs.forEachJob(mMaybeQueueFunctor);
mMaybeQueueFunctor.postProcess();
@@ -998,16 +1031,28 @@
}
}
+ private int adjustJobPriority(int curPriority, JobStatus job) {
+ if (curPriority < JobInfo.PRIORITY_TOP_APP) {
+ float factor = mJobPackageTracker.getLoadFactor(job);
+ if (factor >= HEAVY_USE_FACTOR) {
+ curPriority += JobInfo.PRIORITY_ADJ_ALWAYS_RUNNING;
+ } else if (factor >= MODERATE_USE_FACTOR) {
+ curPriority += JobInfo.PRIORITY_ADJ_OFTEN_RUNNING;
+ }
+ }
+ return curPriority;
+ }
+
private int evaluateJobPriorityLocked(JobStatus job) {
int priority = job.getPriority();
if (priority >= JobInfo.PRIORITY_FOREGROUND_APP) {
- return priority;
+ return adjustJobPriority(priority, job);
}
int override = mUidPriorityOverride.get(job.getSourceUid(), 0);
if (override != 0) {
- return override;
+ return adjustJobPriority(override, job);
}
- return priority;
+ return adjustJobPriority(priority, job);
}
/**
@@ -1029,16 +1074,16 @@
}
switch (memLevel) {
case ProcessStats.ADJ_MEM_FACTOR_MODERATE:
- mMaxActiveJobs = ((MAX_JOB_CONTEXTS_COUNT - 2) * 2) / 3;
+ mMaxActiveJobs = ((MAX_JOB_CONTEXTS_COUNT - FG_JOB_CONTEXTS_COUNT) * 2) / 3;
break;
case ProcessStats.ADJ_MEM_FACTOR_LOW:
- mMaxActiveJobs = (MAX_JOB_CONTEXTS_COUNT - 2) / 3;
+ mMaxActiveJobs = (MAX_JOB_CONTEXTS_COUNT - FG_JOB_CONTEXTS_COUNT) / 3;
break;
case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
mMaxActiveJobs = 1;
break;
default:
- mMaxActiveJobs = MAX_JOB_CONTEXTS_COUNT - 2;
+ mMaxActiveJobs = MAX_JOB_CONTEXTS_COUNT - FG_JOB_CONTEXTS_COUNT;
break;
}
@@ -1134,7 +1179,9 @@
if (!mActiveServices.get(i).executeRunnableJob(pendingJob)) {
Slog.d(TAG, "Error executing " + pendingJob);
}
- mPendingJobs.remove(pendingJob);
+ if (mPendingJobs.remove(pendingJob)) {
+ mJobPackageTracker.noteNonpending(pendingJob);
+ }
}
}
if (!preservePreferredUid) {
@@ -1444,6 +1491,8 @@
pw.print(": "); pw.println(mUidPriorityOverride.valueAt(i));
}
pw.println();
+ mJobPackageTracker.dump(pw, "");
+ pw.println();
pw.println("Pending queue:");
for (int i=0; i<mPendingJobs.size(); i++) {
JobStatus job = mPendingJobs.get(i);
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 4239248..4fd1350 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -105,6 +105,7 @@
private final Context mContext;
private final Object mLock;
private final IBatteryStats mBatteryStats;
+ private final JobPackageTracker mJobPackageTracker;
private PowerManager.WakeLock mWakeLock;
// Execution state.
@@ -136,16 +137,18 @@
/** Track when job will timeout. */
private long mTimeoutElapsed;
- JobServiceContext(JobSchedulerService service, IBatteryStats batteryStats, Looper looper) {
- this(service.getContext(), service.getLock(), batteryStats, service, looper);
+ JobServiceContext(JobSchedulerService service, IBatteryStats batteryStats,
+ JobPackageTracker tracker, Looper looper) {
+ this(service.getContext(), service.getLock(), batteryStats, tracker, service, looper);
}
@VisibleForTesting
JobServiceContext(Context context, Object lock, IBatteryStats batteryStats,
- JobCompletedListener completedListener, Looper looper) {
+ JobPackageTracker tracker, JobCompletedListener completedListener, Looper looper) {
mContext = context;
mLock = lock;
mBatteryStats = batteryStats;
+ mJobPackageTracker = tracker;
mCallbackHandler = new JobServiceHandler(looper);
mCompletedListener = completedListener;
mAvailable = true;
@@ -208,6 +211,7 @@
} catch (RemoteException e) {
// Whatever.
}
+ mJobPackageTracker.noteActive(job);
mAvailable = false;
return true;
}
@@ -580,6 +584,7 @@
return;
}
completedJob = mRunningJob;
+ mJobPackageTracker.noteInactive(completedJob);
try {
mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(),
mRunningJob.getSourceUid());
diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java
index d8490d4..02bc36ca 100644
--- a/services/core/java/com/android/server/job/controllers/AppIdleController.java
+++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java
@@ -22,6 +22,7 @@
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerService;
+import com.android.server.job.JobStore;
import com.android.server.job.StateChangedListener;
import java.io.PrintWriter;
@@ -41,10 +42,52 @@
// Singleton factory
private static Object sCreationLock = new Object();
private static volatile AppIdleController sController;
- final ArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();
+ private final JobSchedulerService mJobSchedulerService;
private final UsageStatsManagerInternal mUsageStatsInternal;
boolean mAppIdleParoleOn;
+ final class GlobalUpdateFunc implements JobStore.JobStatusFunctor {
+ boolean mChanged;
+
+ @Override public void process(JobStatus jobStatus) {
+ String packageName = jobStatus.getSourcePackageName();
+ final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
+ jobStatus.getSourceUid(), jobStatus.getSourceUserId());
+ if (DEBUG) {
+ Slog.d(LOG_TAG, "Setting idle state of " + packageName + " to " + appIdle);
+ }
+ if (jobStatus.setAppNotIdleConstraintSatisfied(!appIdle)) {
+ mChanged = true;
+ }
+ }
+ };
+
+ final static class PackageUpdateFunc implements JobStore.JobStatusFunctor {
+ final int mUserId;
+ final String mPackage;
+ final boolean mIdle;
+ boolean mChanged;
+
+ PackageUpdateFunc(int userId, String pkg, boolean idle) {
+ mUserId = userId;
+ mPackage = pkg;
+ mIdle = idle;
+ }
+
+ @Override public void process(JobStatus jobStatus) {
+ if (jobStatus.getSourcePackageName().equals(mPackage)
+ && jobStatus.getSourceUserId() == mUserId) {
+ if (jobStatus.setAppNotIdleConstraintSatisfied(!mIdle)) {
+ if (DEBUG) {
+ Slog.d(LOG_TAG, "App Idle state changed, setting idle state of "
+ + mPackage + " to " + mIdle);
+ }
+ mChanged = true;
+ }
+ }
+ }
+ };
+
public static AppIdleController get(JobSchedulerService service) {
synchronized (sCreationLock) {
if (sController == null) {
@@ -55,9 +98,9 @@
}
}
- private AppIdleController(StateChangedListener stateChangedListener, Context context,
- Object lock) {
- super(stateChangedListener, context, lock);
+ private AppIdleController(JobSchedulerService service, Context context, Object lock) {
+ super(service, context, lock);
+ mJobSchedulerService = service;
mUsageStatsInternal = LocalServices.getService(UsageStatsManagerInternal.class);
mAppIdleParoleOn = mUsageStatsInternal.isAppIdleParoleOn();
mUsageStatsInternal.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
@@ -65,7 +108,6 @@
@Override
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
- mTrackedTasks.add(jobStatus);
String packageName = jobStatus.getSourcePackageName();
final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
jobStatus.getSourceUid(), jobStatus.getSourceUserId());
@@ -78,19 +120,20 @@
@Override
public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) {
- mTrackedTasks.remove(jobStatus);
}
@Override
- public void dumpControllerStateLocked(PrintWriter pw) {
+ public void dumpControllerStateLocked(final PrintWriter pw) {
pw.println("AppIdle");
pw.println("Parole On: " + mAppIdleParoleOn);
- for (JobStatus task : mTrackedTasks) {
- pw.print(task.getSourcePackageName());
- pw.print(":runnable="
- + ((task.satisfiedConstraints&JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0));
- pw.print(", ");
- }
+ mJobSchedulerService.getJobStore().forEachJob(new JobStore.JobStatusFunctor() {
+ @Override public void process(JobStatus jobStatus) {
+ pw.print(" ");
+ pw.print(jobStatus.getSourcePackageName());
+ pw.print(": runnable=");
+ pw.println((jobStatus.satisfiedConstraints&JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0);
+ }
+ });
pw.println();
}
@@ -102,16 +145,10 @@
return;
}
mAppIdleParoleOn = isAppIdleParoleOn;
- for (JobStatus task : mTrackedTasks) {
- String packageName = task.getSourcePackageName();
- final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
- task.getSourceUid(), task.getSourceUserId());
- if (DEBUG) {
- Slog.d(LOG_TAG, "Setting idle state of " + packageName + " to " + appIdle);
- }
- if (task.setAppNotIdleConstraintSatisfied(!appIdle)) {
- changed = true;
- }
+ GlobalUpdateFunc update = new GlobalUpdateFunc();
+ mJobSchedulerService.getJobStore().forEachJob(update);
+ if (update.mChanged) {
+ changed = true;
}
}
if (changed) {
@@ -128,17 +165,10 @@
if (mAppIdleParoleOn) {
return;
}
- for (JobStatus task : mTrackedTasks) {
- if (task.getSourcePackageName().equals(packageName)
- && task.getSourceUserId() == userId) {
- if (task.setAppNotIdleConstraintSatisfied(!idle)) {
- if (DEBUG) {
- Slog.d(LOG_TAG, "App Idle state changed, setting idle state of "
- + packageName + " to " + idle);
- }
- changed = true;
- }
- }
+ PackageUpdateFunc update = new PackageUpdateFunc(userId, packageName, idle);
+ mJobSchedulerService.getJobStore().forEachJob(update);
+ if (update.mChanged) {
+ changed = true;
}
}
if (changed) {
diff --git a/services/core/java/com/android/server/job/controllers/ContentObserverController.java b/services/core/java/com/android/server/job/controllers/ContentObserverController.java
index b2f1958..c5b1a3d 100644
--- a/services/core/java/com/android/server/job/controllers/ContentObserverController.java
+++ b/services/core/java/com/android/server/job/controllers/ContentObserverController.java
@@ -21,6 +21,7 @@
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
+import android.util.TimeUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -46,12 +47,17 @@
*/
private static final int MAX_URIS_REPORTED = 50;
+ /**
+ * At this point we consider it urgent to schedule the job ASAP.
+ */
+ private static final int URIS_URGENT_THRESHOLD = 40;
+
private static final Object sCreationLock = new Object();
private static volatile ContentObserverController sController;
final private List<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();
ArrayMap<Uri, ObserverInstance> mObservers = new ArrayMap<>();
- final Handler mHandler = new Handler();
+ final Handler mHandler;
public static ContentObserverController get(JobSchedulerService taskManagerService) {
synchronized (sCreationLock) {
@@ -72,6 +78,7 @@
private ContentObserverController(StateChangedListener stateChangedListener, Context context,
Object lock) {
super(stateChangedListener, context, lock);
+ mHandler = new Handler(context.getMainLooper());
}
@Override
@@ -113,6 +120,11 @@
taskStatus.changedUris = null;
taskStatus.setContentTriggerConstraintSatisfied(havePendingUris);
}
+ if (lastJob != null && lastJob.contentObserverJobInstance != null) {
+ // And now we can detach the instance state from the last job.
+ lastJob.contentObserverJobInstance.detachLocked();
+ lastJob.contentObserverJobInstance = null;
+ }
}
@Override
@@ -133,30 +145,33 @@
boolean forUpdate) {
if (taskStatus.hasContentTriggerConstraint()) {
if (taskStatus.contentObserverJobInstance != null) {
- if (incomingJob != null && taskStatus.contentObserverJobInstance != null
- && taskStatus.contentObserverJobInstance.mChangedAuthorities != null) {
- // We are stopping this job, but it is going to be replaced by this given
- // incoming job. We want to propagate our state over to it, so we don't
- // lose any content changes that had happend since the last one started.
- // If there is a previous job associated with the new job, propagate over
- // any pending content URI trigger reports.
- if (incomingJob.contentObserverJobInstance == null) {
- incomingJob.contentObserverJobInstance = new JobInstance(incomingJob);
+ taskStatus.contentObserverJobInstance.unscheduleLocked();
+ if (incomingJob != null) {
+ if (taskStatus.contentObserverJobInstance != null
+ && taskStatus.contentObserverJobInstance.mChangedAuthorities != null) {
+ // We are stopping this job, but it is going to be replaced by this given
+ // incoming job. We want to propagate our state over to it, so we don't
+ // lose any content changes that had happend since the last one started.
+ // If there is a previous job associated with the new job, propagate over
+ // any pending content URI trigger reports.
+ if (incomingJob.contentObserverJobInstance == null) {
+ incomingJob.contentObserverJobInstance = new JobInstance(incomingJob);
+ }
+ incomingJob.contentObserverJobInstance.mChangedAuthorities
+ = taskStatus.contentObserverJobInstance.mChangedAuthorities;
+ incomingJob.contentObserverJobInstance.mChangedUris
+ = taskStatus.contentObserverJobInstance.mChangedUris;
+ taskStatus.contentObserverJobInstance.mChangedAuthorities = null;
+ taskStatus.contentObserverJobInstance.mChangedUris = null;
}
- incomingJob.contentObserverJobInstance.mChangedAuthorities
- = taskStatus.contentObserverJobInstance.mChangedAuthorities;
- incomingJob.contentObserverJobInstance.mChangedUris
- = taskStatus.contentObserverJobInstance.mChangedUris;
- taskStatus.contentObserverJobInstance.mChangedAuthorities = null;
- taskStatus.contentObserverJobInstance.mChangedUris = null;
+ // We won't detach the content observers here, because we want to
+ // allow them to continue monitoring so we don't miss anything... and
+ // since we are giving an incomingJob here, we know this will be
+ // immediately followed by a start tracking of that job.
} else {
- // We won't do this reset if being called for an update, because
- // we know it will be immediately followed by maybeStartTrackingJobLocked...
- // and we don't want to lose any content changes in-between.
- if (taskStatus.contentObserverJobInstance != null) {
- taskStatus.contentObserverJobInstance.detach();
- taskStatus.contentObserverJobInstance = null;
- }
+ // But here there is no incomingJob, so nothing coming up, so time to detach.
+ taskStatus.contentObserverJobInstance.detachLocked();
+ taskStatus.contentObserverJobInstance = null;
}
}
mTrackedTasks.remove(taskStatus);
@@ -177,9 +192,9 @@
}
}
- class ObserverInstance extends ContentObserver {
+ final class ObserverInstance extends ContentObserver {
final Uri mUri;
- final ArrayList<JobInstance> mJobs = new ArrayList<>();
+ final ArraySet<JobInstance> mJobs = new ArraySet<>();
public ObserverInstance(Handler handler, Uri uri) {
super(handler);
@@ -188,11 +203,10 @@
@Override
public void onChange(boolean selfChange, Uri uri) {
- boolean reportChange = false;
synchronized (mLock) {
final int N = mJobs.size();
for (int i=0; i<N; i++) {
- JobInstance inst = mJobs.get(i);
+ JobInstance inst = mJobs.valueAt(i);
if (inst.mChangedUris == null) {
inst.mChangedUris = new ArraySet<>();
}
@@ -203,26 +217,38 @@
inst.mChangedAuthorities = new ArraySet<>();
}
inst.mChangedAuthorities.add(uri.getAuthority());
- if (inst.mJobStatus.setContentTriggerConstraintSatisfied(true)) {
- reportChange = true;
- }
+ inst.scheduleLocked();
}
}
- // Let the scheduler know that state has changed. This may or may not result in an
- // execution.
- if (reportChange) {
- mStateChangedListener.onControllerStateChanged();
- }
}
}
- class JobInstance extends ArrayList<ObserverInstance> {
- private final JobStatus mJobStatus;
- private ArraySet<Uri> mChangedUris;
- private ArraySet<String> mChangedAuthorities;
+ static final class TriggerRunnable implements Runnable {
+ final JobInstance mInstance;
+
+ TriggerRunnable(JobInstance instance) {
+ mInstance = instance;
+ }
+
+ @Override public void run() {
+ mInstance.trigger();
+ }
+ }
+
+ final class JobInstance {
+ final ArrayList<ObserverInstance> mMyObservers = new ArrayList<>();
+ final JobStatus mJobStatus;
+ final Runnable mExecuteRunner;
+ final Runnable mTimeoutRunner;
+ ArraySet<Uri> mChangedUris;
+ ArraySet<String> mChangedAuthorities;
+
+ boolean mTriggerPending;
JobInstance(JobStatus jobStatus) {
mJobStatus = jobStatus;
+ mExecuteRunner = new TriggerRunnable(this);
+ mTimeoutRunner = new TriggerRunnable(this);
final JobInfo.TriggerContentUri[] uris = jobStatus.getJob().getTriggerContentUris();
if (uris != null) {
for (JobInfo.TriggerContentUri uri : uris) {
@@ -238,15 +264,54 @@
obs);
}
obs.mJobs.add(this);
- add(obs);
+ mMyObservers.add(obs);
}
}
}
- void detach() {
- final int N = size();
+ void trigger() {
+ boolean reportChange = false;
+ synchronized (mLock) {
+ if (mTriggerPending) {
+ if (mJobStatus.setContentTriggerConstraintSatisfied(true)) {
+ reportChange = true;
+ }
+ unscheduleLocked();
+ }
+ }
+ // Let the scheduler know that state has changed. This may or may not result in an
+ // execution.
+ if (reportChange) {
+ mStateChangedListener.onControllerStateChanged();
+ }
+ }
+
+ void scheduleLocked() {
+ if (!mTriggerPending) {
+ mTriggerPending = true;
+ mHandler.postDelayed(mTimeoutRunner, mJobStatus.getTriggerContentMaxDelay());
+ }
+ mHandler.removeCallbacks(mExecuteRunner);
+ if (mChangedUris.size() >= URIS_URGENT_THRESHOLD) {
+ // If we start getting near the limit, GO NOW!
+ mHandler.post(mExecuteRunner);
+ } else {
+ mHandler.postDelayed(mExecuteRunner, mJobStatus.getTriggerContentUpdateDelay());
+ }
+ }
+
+ void unscheduleLocked() {
+ if (mTriggerPending) {
+ mHandler.removeCallbacks(mExecuteRunner);
+ mHandler.removeCallbacks(mTimeoutRunner);
+ mTriggerPending = false;
+ }
+ }
+
+ void detachLocked() {
+ final int N = mMyObservers.size();
for (int i=0; i<N; i++) {
- final ObserverInstance obs = get(i);
+ final ObserverInstance obs = mMyObservers.get(i);
obs.mJobs.remove(this);
if (obs.mJobs.size() == 0) {
mContext.getContentResolver().unregisterContentObserver(obs);
@@ -259,39 +324,54 @@
@Override
public void dumpControllerStateLocked(PrintWriter pw) {
pw.println("Content.");
+ boolean printed = false;
Iterator<JobStatus> it = mTrackedTasks.iterator();
- if (it.hasNext()) {
- pw.print(String.valueOf(it.next().hashCode()));
- }
while (it.hasNext()) {
- pw.print("," + String.valueOf(it.next().hashCode()));
+ if (!printed) {
+ pw.print(" ");
+ printed = true;
+ } else {
+ pw.print(",");
+ }
+ pw.print(System.identityHashCode(it.next()));
}
- pw.println();
+ if (printed) {
+ pw.println();
+ }
int N = mObservers.size();
if (N > 0) {
- pw.println("URIs:");
+ pw.println(" Observers:");
for (int i = 0; i < N; i++) {
ObserverInstance obs = mObservers.valueAt(i);
- pw.print(" ");
- pw.print(mObservers.keyAt(i));
- pw.println(":");
pw.print(" ");
- pw.println(obs);
- pw.println(" Jobs:");
+ pw.print(mObservers.keyAt(i));
+ pw.print(" (");
+ pw.print(System.identityHashCode(obs));
+ pw.println("):");
+ pw.println(" Jobs:");
int M = obs.mJobs.size();
for (int j=0; j<M; j++) {
- JobInstance inst = obs.mJobs.get(j);
- pw.print(" ");
- pw.print(inst.hashCode());
+ JobInstance inst = obs.mJobs.valueAt(j);
+ pw.print(" ");
+ pw.print(System.identityHashCode(inst.mJobStatus));
if (inst.mChangedAuthorities != null) {
pw.println(":");
- pw.println(" Changed Authorities:");
+ if (inst.mTriggerPending) {
+ pw.print(" Trigger pending: update=");
+ TimeUtils.formatDuration(
+ inst.mJobStatus.getTriggerContentUpdateDelay(), pw);
+ pw.print(", max=");
+ TimeUtils.formatDuration(
+ inst.mJobStatus.getTriggerContentMaxDelay(), pw);
+ pw.println();
+ }
+ pw.println(" Changed Authorities:");
for (int k=0; k<inst.mChangedAuthorities.size(); k++) {
pw.print(" ");
pw.println(inst.mChangedAuthorities.valueAt(k));
}
if (inst.mChangedUris != null) {
- pw.println(" Changed URIs:");
+ pw.println(" Changed URIs:");
for (int k = 0; k<inst.mChangedUris.size(); k++) {
pw.print(" ");
pw.println(inst.mChangedUris.valueAt(k));
diff --git a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
index 64887e8..fe563d2 100644
--- a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
+++ b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
@@ -28,6 +28,7 @@
import com.android.server.DeviceIdleController;
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerService;
+import com.android.server.job.JobStore;
import com.android.server.job.StateChangedListener;
import java.io.PrintWriter;
@@ -45,9 +46,9 @@
// Singleton factory
private static Object sCreationLock = new Object();
- final ArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();
private static DeviceIdleJobsController sController;
+ private final JobSchedulerService mJobSchedulerService;
private final PowerManager mPowerManager;
private final DeviceIdleController.LocalService mLocalDeviceIdleController;
@@ -57,6 +58,12 @@
private boolean mDeviceIdleMode;
private int[] mDeviceIdleWhitelistAppIds;
+ final JobStore.JobStatusFunctor mUpdateFunctor = new JobStore.JobStatusFunctor() {
+ @Override public void process(JobStatus jobStatus) {
+ updateTaskStateLocked(jobStatus);
+ }
+ };
+
/**
* Returns a singleton for the DeviceIdleJobsController
*/
@@ -87,10 +94,11 @@
}
};
- private DeviceIdleJobsController(StateChangedListener stateChangedListener, Context context,
+ private DeviceIdleJobsController(JobSchedulerService jobSchedulerService, Context context,
Object lock) {
- super(stateChangedListener, context, lock);
+ super(jobSchedulerService, context, lock);
+ mJobSchedulerService = jobSchedulerService;
// Register for device idle mode changes
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mLocalDeviceIdleController =
@@ -115,9 +123,7 @@
}
mDeviceIdleMode = enabled;
if (LOG_DEBUG) Slog.d(LOG_TAG, "mDeviceIdleMode=" + mDeviceIdleMode);
- for (JobStatus task : mTrackedTasks) {
- updateTaskStateLocked(task);
- }
+ mJobSchedulerService.getJobStore().forEachJob(mUpdateFunctor);
}
// Inform the job scheduler service about idle mode changes
if (changed) {
@@ -160,25 +166,26 @@
@Override
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
synchronized (mLock) {
- mTrackedTasks.add(jobStatus);
updateTaskStateLocked(jobStatus);
}
}
@Override
public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) {
- mTrackedTasks.remove(jobStatus);
}
@Override
- public void dumpControllerStateLocked(PrintWriter pw) {
+ public void dumpControllerStateLocked(final PrintWriter pw) {
pw.println("DeviceIdleJobsController");
- for (JobStatus task : mTrackedTasks) {
- pw.print(task.getSourcePackageName());
- pw.print(":runnable="
- + ((task.satisfiedConstraints & JobStatus.CONSTRAINT_DEVICE_NOT_DOZING) != 0));
- pw.print(", ");
- }
+ mJobSchedulerService.getJobStore().forEachJob(new JobStore.JobStatusFunctor() {
+ @Override public void process(JobStatus jobStatus) {
+ pw.print(" ");
+ pw.print(jobStatus.getSourcePackageName());
+ pw.print(": runnable=");
+ pw.println((jobStatus.satisfiedConstraints
+ & JobStatus.CONSTRAINT_DEVICE_NOT_DOZING) != 0);
+ }
+ });
pw.println();
}
}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 39905d8..dd70758 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -61,6 +61,18 @@
// Full override: ignore all constraints including API-affecting like connectivity
public static final int OVERRIDE_FULL = 2;
+ /** If not specified, trigger update delay is 10 seconds. */
+ public static final long DEFAULT_TRIGGER_UPDATE_DELAY = 10*1000;
+
+ /** The minimum possible update delay is 1/2 second. */
+ public static final long MIN_TRIGGER_UPDATE_DELAY = 500;
+
+ /** If not specified, trigger maxumum delay is 2 minutes. */
+ public static final long DEFAULT_TRIGGER_MAX_DELAY = 2*60*1000;
+
+ /** The minimum possible update delay is 1 second. */
+ public static final long MIN_TRIGGER_MAX_DELAY = 1000;
+
final JobInfo job;
/** Uid of the package requesting this job. */
final int callingUid;
@@ -320,6 +332,22 @@
return (requiredConstraints&CONSTRAINT_CONTENT_TRIGGER) != 0;
}
+ public long getTriggerContentUpdateDelay() {
+ long time = job.getTriggerContentUpdateDelay();
+ if (time < 0) {
+ return DEFAULT_TRIGGER_UPDATE_DELAY;
+ }
+ return Math.max(time, MIN_TRIGGER_UPDATE_DELAY);
+ }
+
+ public long getTriggerContentMaxDelay() {
+ long time = job.getTriggerContentMaxDelay();
+ if (time < 0) {
+ return DEFAULT_TRIGGER_MAX_DELAY;
+ }
+ return Math.max(time, MIN_TRIGGER_MAX_DELAY);
+ }
+
public boolean isPersisted() {
return job.isPersisted();
}
@@ -540,6 +568,16 @@
pw.print(Integer.toHexString(trig.getFlags()));
pw.print(' '); pw.println(trig.getUri());
}
+ if (job.getTriggerContentUpdateDelay() >= 0) {
+ pw.print(prefix); pw.print(" Trigger update delay: ");
+ TimeUtils.formatDuration(job.getTriggerContentUpdateDelay(), pw);
+ pw.println();
+ }
+ if (job.getTriggerContentMaxDelay() >= 0) {
+ pw.print(prefix); pw.print(" Trigger max delay: ");
+ TimeUtils.formatDuration(job.getTriggerContentMaxDelay(), pw);
+ pw.println();
+ }
}
if (job.getNetworkType() != JobInfo.NETWORK_TYPE_NONE) {
pw.print(prefix); pw.print(" Network type: "); pw.println(job.getNetworkType());
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
index d339f69..5e68f8e 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
@@ -329,6 +329,7 @@
final String ssid = removeDoubleQuotes(config.SSID);
if (id.equals(ssid)) {
final NetworkPolicy policy = newPolicy(ssid);
+ policy.metered = true;
Log.i(TAG, "Creating new policy for " + ssid + ": " + policy);
final NetworkPolicy[] newPolicies = new NetworkPolicy[policies.length + 1];
System.arraycopy(policies, 0, newPolicies, 0, policies.length);
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index c19b51f..62fe70c 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -16,7 +16,7 @@
package com.android.server.notification;
-import android.app.AutomaticZenRule;
+import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -29,7 +29,6 @@
import android.provider.Settings;
import android.service.notification.Condition;
import android.service.notification.ConditionProviderService;
-import android.service.notification.IConditionListener;
import android.service.notification.IConditionProvider;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -82,6 +81,7 @@
c.caption = "condition provider";
c.serviceInterface = ConditionProviderService.SERVICE_INTERFACE;
c.secureSettingName = Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES;
+ c.secondarySettingName = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS;
c.bindPermission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE;
c.settingsAction = Settings.ACTION_CONDITION_PROVIDER_SETTINGS;
c.clientLabel = R.string.condition_provider_service_binding_label;
@@ -257,7 +257,7 @@
}
@Override
- protected ArraySet<ComponentName> loadComponentNamesFromSetting(String settingName,
+ protected @NonNull ArraySet<ComponentName> loadComponentNamesFromSetting(String settingName,
int userId) {
final ContentResolver cr = mContext.getContentResolver();
String settingValue = Settings.Secure.getStringForUser(
@@ -265,12 +265,17 @@
settingName,
userId);
if (TextUtils.isEmpty(settingValue))
- return null;
+ return new ArraySet<>();
String[] packages = settingValue.split(ENABLED_SERVICES_SEPARATOR);
ArraySet<ComponentName> result = new ArraySet<>(packages.length);
for (int i = 0; i < packages.length; i++) {
if (!TextUtils.isEmpty(packages[i])) {
- result.addAll(queryPackageForServices(packages[i], userId));
+ final ComponentName component = ComponentName.unflattenFromString(packages[i]);
+ if (component != null) {
+ result.addAll(queryPackageForServices(component.getPackageName(), userId));
+ } else {
+ result.addAll(queryPackageForServices(packages[i], userId));
+ }
}
}
return result;
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 6d9fed4..29e2e44 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -97,8 +97,6 @@
// List of packages in restored setting across all mUserProfiles, for quick
// filtering upon package updates.
private ArraySet<String> mRestoredPackages = new ArraySet<>();
- // State of current service categories
- private ArrayMap<String, Boolean> mCategoryEnabled = new ArrayMap<>();
// List of enabled packages that have nevertheless asked not to be run
private ArraySet<ComponentName> mSnoozingForCurrentProfiles = new ArraySet<>();
@@ -128,7 +126,8 @@
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_SETTING_RESTORED.equals(intent.getAction())) {
String element = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
- if (Objects.equals(element, mConfig.secureSettingName)) {
+ if (Objects.equals(element, mConfig.secureSettingName)
+ || Objects.equals(element, mConfig.secondarySettingName)) {
String prevValue = intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE);
String newValue = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE);
settingRestored(element, prevValue, newValue, getSendingUserId());
@@ -188,8 +187,8 @@
// By convention, restored settings are replicated to another settings
// entry, named similarly but with a disambiguation suffix.
- public static String restoredSettingName(Config config) {
- return config.secureSettingName + ":restored";
+ public static String restoredSettingName(String setting) {
+ return setting + ":restored";
}
// The OS has done a restore of this service's saved state. We clone it to the
@@ -199,14 +198,14 @@
public void settingRestored(String element, String oldValue, String newValue, int userid) {
if (DEBUG) Slog.d(TAG, "Restored managed service setting: " + element
+ " ovalue=" + oldValue + " nvalue=" + newValue);
- if (mConfig.secureSettingName.equals(element)) {
+ if (mConfig.secureSettingName.equals(element) ||
+ mConfig.secondarySettingName.equals(element)) {
if (element != null) {
- mRestored = null;
Settings.Secure.putStringForUser(mContext.getContentResolver(),
- restoredSettingName(mConfig),
+ restoredSettingName(element),
newValue,
userid);
- updateSettingsAccordingToInstalledServices(userid);
+ updateSettingsAccordingToInstalledServices(element, userid);
rebuildRestoredPackages();
}
}
@@ -342,65 +341,28 @@
}
}
- public void setCategoryState(String category, boolean enabled) {
- synchronized (mMutex) {
- final Boolean previous = mCategoryEnabled.put(category, enabled);
- if (!(previous == null || previous != enabled)) {
- return;
- }
-
- // State changed
- if (DEBUG) {
- Slog.d(TAG, ((enabled) ? "Enabling " : "Disabling ") + "category " + category);
- }
-
- final int[] userIds = mUserProfiles.getCurrentProfileIds();
- for (int userId : userIds) {
- final Set<ComponentName> componentNames = queryPackageForServices(null,
- userId, category);
-
- // Disallow services not enabled in Settings
- final ArraySet<ComponentName> userComponents =
- loadComponentNamesFromSetting(mConfig.secureSettingName, userId);
- if (userComponents == null) {
- componentNames.clear();
- } else {
- componentNames.retainAll(userComponents);
- }
-
- if (DEBUG) {
- Slog.d(TAG, "Components for category " + category + ": " + componentNames);
- }
- for (ComponentName c : componentNames) {
- if (enabled) {
- registerServiceLocked(c, userId);
- } else {
- unregisterServiceLocked(c, userId);
- }
- }
- }
-
- }
- }
-
private void rebuildRestoredPackages() {
mRestoredPackages.clear();
mSnoozingForCurrentProfiles.clear();
- String settingName = restoredSettingName(mConfig);
+ String secureSettingName = restoredSettingName(mConfig.secureSettingName);
+ String secondarySettingName = mConfig.secondarySettingName == null
+ ? null : restoredSettingName(mConfig.secondarySettingName);
int[] userIds = mUserProfiles.getCurrentProfileIds();
final int N = userIds.length;
for (int i = 0; i < N; ++i) {
- ArraySet<ComponentName> names = loadComponentNamesFromSetting(settingName, userIds[i]);
- if (names == null)
- continue;
- for (ComponentName name: names) {
+ ArraySet<ComponentName> names =
+ loadComponentNamesFromSetting(secureSettingName, userIds[i]);
+ if (secondarySettingName != null) {
+ names.addAll(loadComponentNamesFromSetting(secondarySettingName, userIds[i]));
+ }
+ for (ComponentName name : names) {
mRestoredPackages.add(name.getPackageName());
}
}
}
- protected ArraySet<ComponentName> loadComponentNamesFromSetting(String settingName,
+ protected @NonNull ArraySet<ComponentName> loadComponentNamesFromSetting(String settingName,
int userId) {
final ContentResolver cr = mContext.getContentResolver();
String settingValue = Settings.Secure.getStringForUser(
@@ -408,7 +370,7 @@
settingName,
userId);
if (TextUtils.isEmpty(settingValue))
- return null;
+ return new ArraySet<>();
String[] restored = settingValue.split(ENABLED_SERVICES_SEPARATOR);
ArraySet<ComponentName> result = new ArraySet<>(restored.length);
for (int i = 0; i < restored.length; i++) {
@@ -448,26 +410,22 @@
int[] userIds = mUserProfiles.getCurrentProfileIds();
final int N = userIds.length;
for (int i = 0; i < N; ++i) {
- updateSettingsAccordingToInstalledServices(userIds[i]);
+ updateSettingsAccordingToInstalledServices(mConfig.secureSettingName, userIds[i]);
+ if (mConfig.secondarySettingName != null) {
+ updateSettingsAccordingToInstalledServices(
+ mConfig.secondarySettingName, userIds[i]);
+ }
}
rebuildRestoredPackages();
}
protected Set<ComponentName> queryPackageForServices(String packageName, int userId) {
- return queryPackageForServices(packageName, userId, null);
- }
-
- public Set<ComponentName> queryPackageForServices(String packageName, int userId,
- String category) {
Set<ComponentName> installed = new ArraySet<>();
final PackageManager pm = mContext.getPackageManager();
Intent queryIntent = new Intent(mConfig.serviceInterface);
if (!TextUtils.isEmpty(packageName)) {
queryIntent.setPackage(packageName);
}
- if (category != null) {
- queryIntent.addCategory(category);
- }
List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
queryIntent,
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
@@ -493,13 +451,13 @@
return installed;
}
- private void updateSettingsAccordingToInstalledServices(int userId) {
+ private void updateSettingsAccordingToInstalledServices(String setting, int userId) {
boolean restoredChanged = false;
boolean currentChanged = false;
Set<ComponentName> restored =
- loadComponentNamesFromSetting(restoredSettingName(mConfig), userId);
+ loadComponentNamesFromSetting(restoredSettingName(setting), userId);
Set<ComponentName> current =
- loadComponentNamesFromSetting(mConfig.secureSettingName, userId);
+ loadComponentNamesFromSetting(setting, userId);
// Load all services for all packages.
Set<ComponentName> installed = queryPackageForServices(null, userId);
@@ -529,13 +487,13 @@
if (currentChanged) {
if (DEBUG) Slog.v(TAG, "List of " + getCaption() + " services was updated " + current);
- storeComponentsToSetting(retained, mConfig.secureSettingName, userId);
+ storeComponentsToSetting(retained, setting, userId);
}
if (restoredChanged) {
if (DEBUG) Slog.v(TAG,
"List of " + getCaption() + " restored services was updated " + restored);
- storeComponentsToSetting(restored, restoredSettingName(mConfig), userId);
+ storeComponentsToSetting(restored, restoredSettingName(setting), userId);
}
}
@@ -553,6 +511,10 @@
for (int i = 0; i < nUserIds; ++i) {
componentsByUser.put(userIds[i],
loadComponentNamesFromSetting(mConfig.secureSettingName, userIds[i]));
+ if (mConfig.secondarySettingName != null) {
+ componentsByUser.get(userIds[i]).addAll(
+ loadComponentNamesFromSetting(mConfig.secondarySettingName, userIds[i]));
+ }
}
final ArrayList<ManagedServiceInfo> removableBoundServices = new ArrayList<>();
@@ -573,20 +535,11 @@
// decode the list of components
final ArraySet<ComponentName> userComponents = componentsByUser.get(userIds[i]);
if (null == userComponents) {
- toAdd.put(userIds[i], new HashSet<ComponentName>());
+ toAdd.put(userIds[i], new ArraySet<ComponentName>());
continue;
}
final Set<ComponentName> add = new HashSet<>(userComponents);
-
- // Remove components from disabled categories so that those services aren't run.
- for (Entry<String, Boolean> e : mCategoryEnabled.entrySet()) {
- if (!e.getValue()) {
- Set<ComponentName> c = queryPackageForServices(null, userIds[i],
- e.getKey());
- add.removeAll(c);
- }
- }
add.removeAll(mSnoozingForCurrentProfiles);
toAdd.put(userIds[i], add);
@@ -835,15 +788,25 @@
private class SettingsObserver extends ContentObserver {
private final Uri mSecureSettingsUri = Settings.Secure.getUriFor(mConfig.secureSettingName);
+ private final Uri mSecondarySettingsUri;
private SettingsObserver(Handler handler) {
super(handler);
+ if (mConfig.secondarySettingName != null) {
+ mSecondarySettingsUri = Settings.Secure.getUriFor(mConfig.secondarySettingName);
+ } else {
+ mSecondarySettingsUri = null;
+ }
}
private void observe() {
ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(mSecureSettingsUri,
false, this, UserHandle.USER_ALL);
+ if (mSecondarySettingsUri != null) {
+ resolver.registerContentObserver(mSecondarySettingsUri,
+ false, this, UserHandle.USER_ALL);
+ }
update(null);
}
@@ -853,9 +816,9 @@
}
private void update(Uri uri) {
- if (uri == null || mSecureSettingsUri.equals(uri)) {
- if (DEBUG) Slog.d(TAG, "Setting changed: mSecureSettingsUri=" + mSecureSettingsUri +
- " / uri=" + uri);
+ if (uri == null || mSecureSettingsUri.equals(uri)
+ || uri.equals(mSecondarySettingsUri)) {
+ if (DEBUG) Slog.d(TAG, "Setting changed: uri=" + uri);
rebindServices(false);
rebuildRestoredPackages();
}
@@ -977,6 +940,7 @@
public String caption;
public String serviceInterface;
public String secureSettingName;
+ public String secondarySettingName;
public String bindPermission;
public String settingsAction;
public int clientLabel;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f20d0a1..cabdced 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1496,7 +1496,7 @@
final StatusBarNotification sbn = mNotificationList.get(i).sbn;
if (sbn.getPackageName().equals(pkg) && sbn.getUserId() == userId
&& (sbn.getNotification().flags
- & Notification.FLAG_AUTOGROUP_SUMMARY) != 0) {
+ & 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.
@@ -2009,7 +2009,7 @@
@Override
public ComponentName getEffectsSuppressor() {
enforceSystemOrSystemUIOrVolume("INotificationManager.getEffectsSuppressor");
- return mEffectsSuppressors.get(0);
+ return !mEffectsSuppressors.isEmpty() ? mEffectsSuppressors.get(0) : null;
}
@Override
@@ -2186,16 +2186,18 @@
// Clears the 'fake' auto-bunding summary.
private void maybeClearAutobundleSummaryLocked(Adjustment adjustment) {
- if (adjustment.getSignals() != null
- && adjustment.getSignals().containsKey(Adjustment.NEEDS_AUTOGROUPING_KEY)
+ if (adjustment.getSignals() != null) {
+ Bundle.setDefusable(adjustment.getSignals(), true);
+ if (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);
+ 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);
+ }
}
}
}
@@ -2203,47 +2205,50 @@
// 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;
+ if (adjustment.getSignals() != null) {
+ Bundle.setDefusable(adjustment.getSignals(), true);
+ if (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();
+ 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));
+ if (summaryRecord != null) {
+ mHandler.post(new EnqueueNotificationRunnable(userId, summaryRecord));
+ }
}
}
}
@@ -2459,10 +2464,10 @@
// 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);
+ final ApplicationInfo ai = getContext().getPackageManager().getApplicationInfoAsUser(
+ pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+ (userId == UserHandle.USER_ALL) ? UserHandle.USER_SYSTEM : userId);
+ Notification.addFieldsFromContext(ai, userId, notification);
} catch (NameNotFoundException e) {
Slog.e(TAG, "Cannot create a context for sending app", e);
return;
@@ -2543,18 +2548,13 @@
// Handle grouped notifications and bail out early if we
// can to avoid extracting signals.
handleGroupedNotificationLocked(r, old, callingUid, callingPid);
- boolean ignoreNotification =
- removeUnusedGroupedNotificationLocked(r, old, callingUid, callingPid);
- if (DBG) Slog.d(TAG, "ignoreNotification is " + ignoreNotification);
// This conditional is a dirty hack to limit the logging done on
// behalf of the download manager without affecting other apps.
if (!pkg.equals("com.android.providers.downloads")
|| Log.isLoggable("DownloadManager", Log.VERBOSE)) {
int enqueueStatus = EVENTLOG_ENQUEUE_STATUS_NEW;
- if (ignoreNotification) {
- enqueueStatus = EVENTLOG_ENQUEUE_STATUS_IGNORED;
- } else if (old != null) {
+ if (old != null) {
enqueueStatus = EVENTLOG_ENQUEUE_STATUS_UPDATE;
}
EventLogTags.writeNotificationEnqueue(callingUid, callingPid,
@@ -2562,10 +2562,6 @@
enqueueStatus);
}
- if (ignoreNotification) {
- return;
- }
-
mRankingHelper.extractSignals(r);
final boolean isPackageSuspended = isPackageSuspendedForUser(pkg, callingUid);
@@ -2681,58 +2677,6 @@
}
}
- /**
- * Performs group notification optimizations if SysUI is the only active
- * notification listener and returns whether the given notification should
- * be ignored.
- *
- * <p>Returns true if the given notification is a child of a group with a
- * summary, which means that SysUI will never show it, and hence the new
- * notification can be safely ignored. Also cancels any previous instance
- * of the ignored notification.</p>
- *
- * <p>For summaries, cancels all children of that group, as SysUI will
- * never show them anymore.</p>
- *
- * @return true if the given notification can be ignored as an optimization
- */
- private boolean removeUnusedGroupedNotificationLocked(NotificationRecord r,
- NotificationRecord old, int callingUid, int callingPid) {
- if (!ENABLE_CHILD_NOTIFICATIONS) {
- // No optimizations are possible if listeners want groups.
- if (mListeners.notificationGroupsDesired()) {
- return false;
- }
-
- StatusBarNotification sbn = r.sbn;
- String group = sbn.getGroupKey();
- boolean isSummary = sbn.getNotification().isGroupSummary();
- boolean isChild = !isSummary && sbn.isGroup();
-
- NotificationRecord summary = mSummaryByGroupKey.get(group);
- if (isChild && summary != null) {
- // Child with an active summary -> ignore
- if (DBG) {
- Slog.d(TAG, "Ignoring group child " + sbn.getKey() + " due to existing summary "
- + summary.getKey());
- }
- // Make sure we don't leave an old version of the notification around.
- if (old != null) {
- if (DBG) {
- Slog.d(TAG, "Canceling old version of ignored group child " + sbn.getKey());
- }
- cancelNotificationLocked(old, false, REASON_GROUP_OPTIMIZATION);
- }
- return true;
- } else if (isSummary) {
- // Summary -> cancel children
- cancelGroupChildrenLocked(r, callingUid, callingPid, null,
- REASON_GROUP_OPTIMIZATION);
- }
- }
- return false;
- }
-
@VisibleForTesting
void buzzBeepBlinkLocked(NotificationRecord record) {
boolean buzz = false;
@@ -3851,7 +3795,7 @@
return;
}
Set<ComponentName> rankerComponents = queryPackageForServices(
- mRankerServicePackageName, UserHandle.USER_SYSTEM, null);
+ mRankerServicePackageName, UserHandle.USER_SYSTEM);
Iterator<ComponentName> iterator = rankerComponents.iterator();
if (iterator.hasNext()) {
ComponentName rankerComponent = iterator.next();
@@ -3869,7 +3813,6 @@
public class NotificationListeners extends ManagedServices {
private final ArraySet<ManagedServiceInfo> mLightTrimListeners = new ArraySet<>();
- private boolean mNotificationGroupsDesired;
public NotificationListeners() {
super(getContext(), mHandler, mNotificationList, mUserProfiles);
@@ -3902,7 +3845,6 @@
final INotificationListener listener = (INotificationListener) info.service;
final NotificationRankingUpdate update;
synchronized (mNotificationList) {
- updateNotificationGroupsDesiredLocked();
update = makeRankingUpdateLocked(info);
}
try {
@@ -3919,7 +3861,6 @@
updateEffectsSuppressorLocked();
}
mLightTrimListeners.remove(removed);
- updateNotificationGroupsDesiredLocked();
}
public void setOnNotificationPostedTrimLocked(ManagedServiceInfo info, int trim) {
@@ -4112,31 +4053,6 @@
}
return false;
}
-
- /**
- * Returns whether any of the currently registered listeners wants to receive notification
- * groups.
- *
- * <p>Currently we assume groups are desired by non-SystemUI listeners.</p>
- */
- public boolean notificationGroupsDesired() {
- return mNotificationGroupsDesired;
- }
-
- private void updateNotificationGroupsDesiredLocked() {
- mNotificationGroupsDesired = true;
- // No listeners, no groups.
- if (mServices.isEmpty()) {
- mNotificationGroupsDesired = false;
- return;
- }
- // One listener: Check whether it's SysUI.
- if (mServices.size() == 1 &&
- mServices.get(0).component.getPackageName().equals("com.android.systemui")) {
- mNotificationGroupsDesired = false;
- return;
- }
- }
}
public static final class DumpFilter {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index a89a422..f29970c 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -176,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/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..43a0b91 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -147,6 +147,7 @@
@Override
public void addOnAppsChangedListener(String callingPackage, IOnAppsChangedListener listener)
throws RemoteException {
+ verifyCallingPackage(callingPackage);
synchronized (mListeners) {
if (DEBUG) {
Log.d(TAG, "Adding listener from " + Binder.getCallingUserHandle());
@@ -213,8 +214,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 +257,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);
@@ -286,7 +294,7 @@
}
@Override
- public ResolveInfo resolveActivity(Intent intent, UserHandle user)
+ public ActivityInfo resolveActivity(ComponentName component, UserHandle user)
throws RemoteException {
ensureInUserProfiles(user, "Cannot resolve activity for unrelated profile " + user);
if (!isUserEnabled(user)) {
@@ -295,11 +303,11 @@
long ident = Binder.clearCallingIdentity();
try {
- ResolveInfo app = mPm.resolveActivityAsUser(intent,
+ IPackageManager pm = AppGlobals.getPackageManager();
+ return pm.getActivityInfo(component,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
user.getIdentifier());
- return app;
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -346,8 +354,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 +369,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 +400,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 +432,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 +459,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 +772,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/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e62450c..1fb260d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -229,6 +229,7 @@
import com.android.internal.os.InstallerConnection.InstallerException;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
+import com.android.internal.telephony.CarrierAppUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
@@ -247,6 +248,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;
@@ -298,14 +300,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";
@@ -367,6 +392,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;
@@ -570,7 +596,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.
@@ -2014,6 +2052,10 @@
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
+ // Disable any carrier apps. We do this very early in boot to prevent the apps from being
+ // disabled after already being started.
+ CarrierAppUtils.disableCarrierAppsUntilPrivileged(context.getOpPackageName(), m,
+ UserHandle.USER_SYSTEM);
ServiceManager.addService("package", m);
return m;
}
@@ -2351,8 +2393,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 +2407,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 +2447,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 +2595,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 +2605,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;
}
@@ -2941,22 +2994,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;
@@ -3006,7 +3043,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!");
}
@@ -4403,6 +4440,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 {
@@ -4677,27 +4721,39 @@
@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
- if (!sUserManager.exists(userId)) return null;
- flags = updateFlagsForResolve(flags, userId, intent);
- enforceCrossUserPermission(Binder.getCallingUid(), userId,
- false /* requireFullPermission */, false /* checkShell */, "resolve intent");
- final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
- userId);
- final ResolveInfo bestChoice =
- chooseBestActivity(intent, resolvedType, flags, query, userId);
+ try {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
- if (isEphemeralAllowed(intent, query, userId)) {
- final EphemeralResolveInfo ai =
- getEphemeralResolveInfo(intent, resolvedType, userId);
- if (ai != null) {
- if (DEBUG_EPHEMERAL) {
- Slog.v(TAG, "Returning an EphemeralResolveInfo");
+ if (!sUserManager.exists(userId)) return null;
+ flags = updateFlagsForResolve(flags, userId, intent);
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
+
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
+ final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
+ flags, userId);
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+
+ final ResolveInfo bestChoice =
+ chooseBestActivity(intent, resolvedType, flags, query, userId);
+
+ if (isEphemeralAllowed(intent, query, userId)) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral");
+ final EphemeralResolveInfo ai =
+ getEphemeralResolveInfo(intent, resolvedType, userId);
+ if (ai != null) {
+ if (DEBUG_EPHEMERAL) {
+ Slog.v(TAG, "Returning an EphemeralResolveInfo");
+ }
+ bestChoice.ephemeralInstaller = mEphemeralInstallerInfo;
+ bestChoice.ephemeralResolveInfo = ai;
}
- bestChoice.ephemeralInstaller = mEphemeralInstallerInfo;
- bestChoice.ephemeralResolveInfo = ai;
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
+ return bestChoice;
+ } finally {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
- return bestChoice;
}
@Override
@@ -4866,6 +4922,7 @@
}
ri = new ResolveInfo(mResolveInfo);
ri.activityInfo = new ActivityInfo(ri.activityInfo);
+ ri.activityInfo.labelRes = ResolverActivity.getLabelRes(intent.getAction());
ri.activityInfo.applicationInfo = new ApplicationInfo(
ri.activityInfo.applicationInfo);
if (userId != 0) {
@@ -5144,8 +5201,14 @@
@Override
public @NonNull ParceledListSlice<ResolveInfo> queryIntentActivities(Intent intent,
String resolvedType, int flags, int userId) {
- return new ParceledListSlice<>(
- queryIntentActivitiesInternal(intent, resolvedType, flags, userId));
+ try {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
+
+ return new ParceledListSlice<>(
+ queryIntentActivitiesInternal(intent, resolvedType, flags, userId));
+ } finally {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
@@ -6800,7 +6863,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 {
/*
@@ -7019,9 +7085,6 @@
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) {
@@ -7034,13 +7097,6 @@
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);
}
@@ -7105,6 +7161,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;
@@ -7125,7 +7183,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);
@@ -7269,23 +7327,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 {
@@ -7298,87 +7339,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
@@ -7564,7 +7624,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);
}
}
}
@@ -8121,20 +8184,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.
@@ -9001,27 +9061,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);
}
}
@@ -11205,7 +11259,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);
}
@@ -13330,7 +13387,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;
@@ -13475,7 +13538,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");
@@ -13511,12 +13574,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) {
@@ -13562,14 +13625,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) {
@@ -13600,34 +13662,20 @@
}
}
+ // Check for shared user id changes
+ String invalidPackageName =
+ getParentOrChildPackageChangedSharedUser(oldPackage, pkg);
+ if (invalidPackageName != null) {
+ res.setError(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
+ "Package " + invalidPackageName + " tried to change user "
+ + oldPackage.mSharedUserId);
+ return;
+ }
+
// 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;
@@ -13667,10 +13715,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);
}
}
@@ -13684,7 +13732,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="
@@ -13702,7 +13750,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");
@@ -13722,8 +13770,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,
@@ -13750,7 +13799,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);
@@ -13762,7 +13811,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);
}
@@ -13822,7 +13871,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
@@ -13837,9 +13886,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);
@@ -13857,8 +13903,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,
@@ -13874,15 +13921,6 @@
setInstallAndUpdateTime(newPackage, deletedPkgSetting.firstInstallTime,
System.currentTimeMillis());
- // Check for shared user id changes
- String invalidPackageName = getParentOrChildPackageChangedSharedUser(
- deletedPackage, newPackage);
- if (invalidPackageName != null) {
- res.setError(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
- "Forbidding shared user change from " + deletedPkgSetting.sharedUser
- + " to " + invalidPackageName);
- }
-
// Update the package dynamic state if succeeded
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
// Now that the install succeeded make sure we remove data
@@ -13907,14 +13945,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);
@@ -14493,7 +14531,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.
@@ -14501,10 +14538,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)) {
@@ -14514,12 +14556,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);
@@ -14767,13 +14812,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(
@@ -14809,15 +14854,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);
@@ -14908,11 +14953,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())) {
@@ -14937,8 +14982,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);
@@ -14947,7 +14995,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();
@@ -15057,15 +15105,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;
@@ -15074,13 +15123,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) {
@@ -15160,7 +15215,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) {
@@ -15225,7 +15280,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;
@@ -15255,7 +15310,7 @@
return false;
}
- prepareAppDataAfterInstall(newPkg);
+ prepareAppDataAfterInstallLIF(newPkg);
// writer
synchronized (mPackages) {
@@ -15293,7 +15348,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) {
@@ -15321,7 +15376,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;
@@ -15338,7 +15393,7 @@
&& (replacingPackage != null
&& !replacingPackage.hasChildPackage(childPs.name))
? flags & ~DELETE_KEEP_DATA : flags;
- removePackageDataLI(childPs, allUserHandles, childOutInfo,
+ removePackageDataLIF(childPs, allUserHandles, childOutInfo,
deleteFlags, writeSettings);
}
}
@@ -15415,7 +15470,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) {
@@ -15443,7 +15498,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);
@@ -15469,7 +15524,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);
@@ -15486,7 +15541,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);
@@ -15518,15 +15573,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);
}
@@ -15586,7 +15636,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*/,
@@ -15594,8 +15644,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) {
@@ -15603,13 +15658,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) {
@@ -15646,6 +15697,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;
@@ -15705,10 +15758,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);
+ }
}
}
@@ -15731,10 +15790,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
@@ -15754,7 +15816,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;
@@ -15780,35 +15842,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;
}
@@ -15974,60 +16023,47 @@
@Override
public void deleteApplicationCacheFiles(final String packageName,
final IPackageDataObserver observer) {
+ final int userId = UserHandle.getCallingUserId();
+ deleteApplicationCacheFilesAsUser(packageName, userId, observer);
+ }
+
+ @Override
+ public void deleteApplicationCacheFilesAsUser(final String packageName, final int userId,
+ final IPackageDataObserver observer) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DELETE_CACHE_FILES, null);
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ /* requireFullPermission= */ true, /* checkShell= */ false,
+ "delete application cache files");
+
+ final PackageParser.Package pkg;
+ synchronized (mPackages) {
+ pkg = mPackages.get(packageName);
+ }
+
// Queue up an async operation since the package deletion may take a little while.
- final int userId = UserHandle.getCallingUserId();
mHandler.post(new Runnable() {
public void run() {
- mHandler.removeCallbacks(this);
- final boolean succeded;
synchronized (mInstallLock) {
- succeded = deleteApplicationCacheFilesLI(packageName, userId);
+ final int flags = StorageManager.FLAG_STORAGE_DE
+ | StorageManager.FLAG_STORAGE_CE;
+ // We're only clearing cache files, so we don't care if the
+ // app is unfrozen and still able to run
+ clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CACHE_ONLY);
+ clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
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) {
@@ -16048,87 +16084,27 @@
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);
} 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;
+ // For now, ignore code size of packages on system partition
+ if (isSystemApp(ps) && !isUpdatedSystemApp(ps)) {
+ stats.codeSize = 0;
}
return true;
@@ -17091,8 +17067,13 @@
}
PackageSetting pkgSetting;
final int uid = Binder.getCallingUid();
- final int permission = mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
+ final int permission;
+ if (uid == Process.SYSTEM_UID) {
+ permission = PackageManager.PERMISSION_GRANTED;
+ } else {
+ permission = mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
+ }
enforceCrossUserPermission(uid, userId,
false /* requireFullPermission */, true /* checkShell */, "set enabled");
final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
@@ -17446,6 +17427,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;
@@ -17679,6 +17661,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();
@@ -18017,6 +18001,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);
@@ -18329,7 +18332,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());
}
@@ -18428,8 +18433,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 {
@@ -18484,6 +18494,7 @@
return;
}
+ final ArrayList<PackageFreezer> freezers = new ArrayList<>();
final ArrayList<ApplicationInfo> loaded = new ArrayList<>();
final int parseFlags = mDefParseFlags | PackageParser.PARSE_EXTERNAL_STORAGE;
@@ -18494,9 +18505,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 {
@@ -18508,7 +18518,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);
}
}
}
@@ -18527,7 +18539,9 @@
}
sm.prepareUserStorage(volumeUuid, user.id, user.serialNumber, flags);
- reconcileAppsData(volumeUuid, user.id, flags);
+ synchronized (mInstallLock) {
+ reconcileAppsDataLI(volumeUuid, user.id, flags);
+ }
}
synchronized (mPackages) {
@@ -18545,6 +18559,10 @@
mSettings.writeLPr();
}
+ for (PackageFreezer freezer : freezers) {
+ freezer.close();
+ }
+
if (DEBUG_INSTALL) Slog.d(TAG, "Loaded packages " + loaded);
sendResourcesChangedBroadcast(true, false, loaded, null);
}
@@ -18573,12 +18591,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);
+ }
}
}
@@ -18710,7 +18733,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);
+ }
}
}
@@ -18723,7 +18748,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));
@@ -18750,9 +18775,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);
}
}
}
@@ -18767,9 +18794,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);
}
}
}
@@ -18792,12 +18821,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++;
@@ -18829,16 +18858,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);
@@ -18859,7 +18879,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);
}
}
}
@@ -18872,57 +18892,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);
+ }
}
}
}
@@ -18932,18 +19007,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 {
@@ -18951,11 +19025,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());
}
}
}
@@ -18995,6 +19174,7 @@
final String seinfo;
final String label;
final int targetSdkVersion;
+ final PackageFreezer freezer;
// reader
synchronized (mPackages) {
@@ -19036,11 +19216,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;
@@ -19049,14 +19228,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();
@@ -19080,7 +19252,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");
}
@@ -19095,7 +19267,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");
}
@@ -19113,7 +19285,7 @@
}
if (sizeBytes > storage.getStorageBytesUntilLow(measurePath)) {
- unfreezePackage(packageName);
+ freezer.close();
throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR,
"Not enough free space to move");
}
@@ -19134,10 +19306,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) {
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/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index aa10c08..a6350fe 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -92,7 +92,7 @@
* MAC_PERMISSIONS class variable which is set at class load time which itself
* is based on the USE_OVERRIDE_POLICY class variable. For further guidance on
* the proper structure of a mac_permissions.xml file consult the source code
- * located at external/sepolicy/mac_permissions.xml.
+ * located at system/sepolicy/mac_permissions.xml.
*
* @return boolean indicating if policy was correctly loaded. A value of false
* typically indicates a structural problem with the xml or incorrectly
@@ -373,7 +373,7 @@
* {@link Policy#getMatchedSeinfo} method. To create an instance of this use the
* {@link PolicyBuilder} pattern class, where each instance is validated against a set
* of invariants before being built and returned. Each instance can be guaranteed to
- * hold one valid policy stanza as outlined in the external/sepolicy/mac_permissions.xml
+ * hold one valid policy stanza as outlined in the system/sepolicy/mac_permissions.xml
* file.
* <p>
* The following is an example of how to use {@link Policy.PolicyBuilder} to create a
@@ -519,7 +519,7 @@
* A nested builder class to create {@link Policy} instances. A {@link Policy}
* class instance represents one valid policy stanza found in a mac_permissions.xml
* file. A valid policy stanza is defined to be a signer stanza which obeys the rules
- * outlined in external/sepolicy/mac_permissions.xml. The {@link #build} method
+ * outlined in system/sepolicy/mac_permissions.xml. The {@link #build} method
* ensures a set of invariants are upheld enforcing the correct stanza structure
* before returning a valid Policy object.
*/
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 83cd978..7debf9b 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";
@@ -790,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
@@ -1574,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
@@ -1626,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);
@@ -1645,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;
}
@@ -1687,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);
@@ -1927,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);
@@ -2699,7 +2686,7 @@
void writePermissionLPr(XmlSerializer serializer, BasePermission bp)
throws XmlPullParserException, java.io.IOException {
- if (bp.type != BasePermission.TYPE_BUILTIN && bp.sourcePackage != null) {
+ if (bp.sourcePackage != null) {
serializer.startTag(null, TAG_ITEM);
serializer.attribute(null, ATTR_NAME, bp.name);
serializer.attribute(null, "package", bp.sourcePackage);
@@ -3361,8 +3348,12 @@
final String ptype = parser.getAttributeValue(null, "type");
if (name != null && sourcePackage != null) {
final boolean dynamic = "dynamic".equals(ptype);
- final BasePermission bp = new BasePermission(name.intern(), sourcePackage,
- dynamic ? BasePermission.TYPE_DYNAMIC : BasePermission.TYPE_NORMAL);
+ BasePermission bp = out.get(name);
+ // If the permission is builtin, do not clobber it.
+ if (bp == null || bp.type != BasePermission.TYPE_BUILTIN) {
+ bp = new BasePermission(name.intern(), sourcePackage,
+ dynamic ? BasePermission.TYPE_DYNAMIC : BasePermission.TYPE_NORMAL);
+ }
bp.protectionLevel = readInt(parser, null, "protection",
PermissionInfo.PROTECTION_NORMAL);
bp.protectionLevel = PermissionInfo.fixProtectionLevel(bp.protectionLevel);
@@ -4325,10 +4316,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);
@@ -4536,6 +4523,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..b9b65eb 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;
@@ -27,6 +28,7 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -36,7 +38,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Collection;
+import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
@@ -50,6 +52,7 @@
private static final String TAG_INTENT_EXTRAS = "intent-extras";
private static final String TAG_EXTRAS = "extras";
private static final String TAG_SHORTCUT = "shortcut";
+ private static final String TAG_CATEGORIES = "categories";
private static final String ATTR_NAME = "name";
private static final String ATTR_DYNAMIC_COUNT = "dynamic-count";
@@ -66,6 +69,11 @@
private static final String ATTR_ICON_RES = "icon-res";
private static final String ATTR_BITMAP_PATH = "bitmap-path";
+ private static final String NAME_CATEGORIES = "categories";
+
+ private static final String TAG_STRING_ARRAY_XMLUTILS = "string-array";
+ private static final String ATTR_NAME_XMLUTILS = "name";
+
/**
* All the shortcuts from the package, keyed on IDs.
*/
@@ -304,7 +312,7 @@
* and return true. Otherwise just return false.
*/
public boolean tryApiCall(@NonNull ShortcutService s) {
- if (getApiCallCount(s) >= s.mMaxDailyUpdates) {
+ if (getApiCallCount(s) >= s.mMaxUpdatesPerInterval) {
return false;
}
mApiCallCount++;
@@ -484,6 +492,16 @@
ShortcutService.writeAttr(out, ATTR_BITMAP_PATH, si.getBitmapPath());
}
+ {
+ final List<String> cat = si.getCategories();
+ if (cat != null && cat.size() > 0) {
+ out.startTag(null, TAG_CATEGORIES);
+ XmlUtils.writeStringArrayXml(cat.toArray(new String[cat.size()]),
+ NAME_CATEGORIES, out);
+ out.endTag(null, TAG_CATEGORIES);
+ }
+ }
+
ShortcutService.writeTagExtra(out, TAG_INTENT_EXTRAS,
si.getIntentPersistableExtras());
ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
@@ -522,7 +540,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 +552,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;
@@ -549,6 +567,7 @@
int flags;
int iconRes;
String bitmapPath;
+ String[] categories = null;
id = ShortcutService.parseStringAttribute(parser, ATTR_ID);
activityComponent = ShortcutService.parseComponentNameAttribute(parser,
@@ -582,11 +601,21 @@
case TAG_EXTRAS:
extras = PersistableBundle.restoreFromXml(parser);
continue;
+ case TAG_CATEGORIES:
+ // This just contains string-array.
+ continue;
+ case TAG_STRING_ARRAY_XMLUTILS:
+ if (NAME_CATEGORIES.equals(ShortcutService.parseStringAttribute(parser,
+ ATTR_NAME_XMLUTILS))) {
+ categories = XmlUtils.readThisStringArrayXml(parser, TAG_STRING_ARRAY_XMLUTILS, null);
+ }
+ continue;
}
throw ShortcutService.throwForInvalidTag(depth, tag);
}
return new ShortcutInfo(
- id, packageName, activityComponent, /* icon =*/ null, title, text, intent,
+ userId, id, packageName, activityComponent, /* icon =*/ null, title, text,
+ (categories == null ? null : Arrays.asList(categories)), 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..ac6510a 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -126,10 +126,10 @@
static final boolean DEBUG_LOAD = false; // STOPSHIP if true
@VisibleForTesting
- static final long DEFAULT_RESET_INTERVAL_SEC = 24 * 60 * 60; // 1 day
+ static final long DEFAULT_RESET_INTERVAL_SEC = 60 * 60; // 1 hour
@VisibleForTesting
- static final int DEFAULT_MAX_DAILY_UPDATES = 10;
+ static final int DEFAULT_MAX_UPDATES_PER_INTERVAL = 2;
@VisibleForTesting
static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 5;
@@ -180,7 +180,7 @@
/**
* Key name for the max number of modifying API calls per app for every interval. (int)
*/
- String KEY_MAX_DAILY_UPDATES = "max_daily_updates";
+ String KEY_MAX_UPDATES_PER_INTERVAL = "max_updates_per_interval";
/**
* Key name for the max icon dimensions in DP, for non-low-memory devices.
@@ -232,9 +232,9 @@
private int mMaxDynamicShortcuts;
/**
- * Max number of updating API calls that each application can make a day.
+ * Max number of updating API calls that each application can make during the interval.
*/
- int mMaxDailyUpdates;
+ int mMaxUpdatesPerInterval;
/**
* Actual throttling-reset interval. By default it's a day.
@@ -419,26 +419,26 @@
result = false;
}
- mSaveDelayMillis = (int) parser.getLong(ConfigConstants.KEY_SAVE_DELAY_MILLIS,
- DEFAULT_SAVE_DELAY_MS);
+ mSaveDelayMillis = Math.max(0, (int) parser.getLong(ConfigConstants.KEY_SAVE_DELAY_MILLIS,
+ DEFAULT_SAVE_DELAY_MS));
- mResetInterval = parser.getLong(
+ mResetInterval = Math.max(1, parser.getLong(
ConfigConstants.KEY_RESET_INTERVAL_SEC, DEFAULT_RESET_INTERVAL_SEC)
- * 1000L;
+ * 1000L);
- mMaxDailyUpdates = (int) parser.getLong(
- ConfigConstants.KEY_MAX_DAILY_UPDATES, DEFAULT_MAX_DAILY_UPDATES);
+ mMaxUpdatesPerInterval = Math.max(0, (int) parser.getLong(
+ ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL, DEFAULT_MAX_UPDATES_PER_INTERVAL));
- mMaxDynamicShortcuts = (int) parser.getLong(
- ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_APP);
+ mMaxDynamicShortcuts = Math.max(0, (int) parser.getLong(
+ ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_APP));
- final int iconDimensionDp = injectIsLowRamDevice()
+ final int iconDimensionDp = Math.max(1, injectIsLowRamDevice()
? (int) parser.getLong(
ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP)
: (int) parser.getLong(
ConfigConstants.KEY_MAX_ICON_DIMENSION_DP,
- DEFAULT_MAX_ICON_DIMENSION_DP);
+ DEFAULT_MAX_ICON_DIMENSION_DP));
mMaxIconDimension = injectDipToPixel(iconDimensionDp);
@@ -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;
}
@@ -1122,7 +1128,7 @@
if (injectGetPackageUid(packageName, userId) == injectBinderCallingUid()) {
return; // Caller is valid.
}
- throw new SecurityException("Caller UID= doesn't own " + packageName);
+ throw new SecurityException("Calling package name mismatch");
}
void postToHandler(Runnable r) {
@@ -1313,10 +1319,13 @@
}
@Override
- public boolean addDynamicShortcut(String packageName, ShortcutInfo newShortcut,
+ public boolean addDynamicShortcuts(String packageName, ParceledListSlice shortcutInfoList,
@UserIdInt int userId) {
verifyCaller(packageName, userId);
+ final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
+ final int size = newShortcuts.size();
+
synchronized (mLock) {
final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
@@ -1324,12 +1333,15 @@
if (!ps.tryApiCall(this)) {
return false;
}
+ for (int i = 0; i < size; i++) {
+ final ShortcutInfo newShortcut = newShortcuts.get(i);
- // Validate the shortcut.
- fixUpIncomingShortcutInfo(newShortcut, /* forUpdate= */ false);
+ // Validate the shortcut.
+ fixUpIncomingShortcutInfo(newShortcut, /* forUpdate= */ false);
- // Add it.
- ps.addDynamicShortcut(this, newShortcut);
+ // Add it.
+ ps.addDynamicShortcut(this, newShortcut);
+ }
}
userPackageChanged(packageName, userId);
@@ -1337,19 +1349,22 @@
}
@Override
- public void deleteDynamicShortcut(String packageName, String shortcutId,
+ public void removeDynamicShortcuts(String packageName, List shortcutIds,
@UserIdInt int userId) {
verifyCaller(packageName, userId);
- Preconditions.checkStringNotEmpty(shortcutId, "shortcutId must be provided");
+ Preconditions.checkNotNull(shortcutIds, "shortcutIds must be provided");
synchronized (mLock) {
- getPackageShortcutsLocked(packageName, userId).deleteDynamicWithId(this, shortcutId);
+ for (int i = shortcutIds.size() - 1; i >= 0; i--) {
+ getPackageShortcutsLocked(packageName, userId).deleteDynamicWithId(this,
+ Preconditions.checkStringNotEmpty((String) shortcutIds.get(i)));
+ }
}
userPackageChanged(packageName, userId);
}
@Override
- public void deleteAllDynamicShortcuts(String packageName, @UserIdInt int userId) {
+ public void removeAllDynamicShortcuts(String packageName, @UserIdInt int userId) {
verifyCaller(packageName, userId);
synchronized (mLock) {
@@ -1403,7 +1418,7 @@
verifyCaller(packageName, userId);
synchronized (mLock) {
- return mMaxDailyUpdates
+ return mMaxUpdatesPerInterval
- getPackageShortcutsLocked(packageName, userId).getApiCallCount(this);
}
}
@@ -1419,6 +1434,8 @@
@Override
public int getIconMaxDimensions(String packageName, int userId) throws RemoteException {
+ verifyCaller(packageName, userId);
+
synchronized (mLock) {
return mMaxIconDimension;
}
@@ -1439,7 +1456,15 @@
getUserShortcutsLocked(userId).resetThrottling();
}
scheduleSaveUser(userId);
- Slog.i(TAG, "ShortcutManager: throttling counter reset");
+ Slog.i(TAG, "ShortcutManager: throttling counter reset for user " + userId);
+ }
+
+ void resetAllThrottlingInner() {
+ synchronized (mLock) {
+ mRawLastResetTime = injectCurrentTimeMillis();
+ }
+ scheduleSaveBaseState();
+ Slog.i(TAG, "ShortcutManager: throttling counter reset for all users");
}
// We override this method in unit tests to do a simpler check.
@@ -1522,14 +1547,20 @@
// === House keeping ===
+ @VisibleForTesting
+ void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId) {
+ cleanUpPackageLocked(packageName, owningUserId, packageUserId,
+ /* forceForCommandLine= */ false);
+ }
+
/**
* Remove all the information associated with a package. This will really remove all the
* information, including the restore information (i.e. it'll remove packages even if they're
* shadow).
*/
- @VisibleForTesting
- void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId) {
- if (isPackageInstalled(packageName, packageUserId)) {
+ private void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId,
+ boolean forceForCommandLine) {
+ if (!forceForCommandLine && isPackageInstalled(packageName, packageUserId)) {
wtf("Package " + packageName + " is still installed for user " + packageUserId);
return;
}
@@ -1580,13 +1611,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 +1629,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 +1645,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 +1674,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 +1753,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 +1772,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;
}
@@ -1865,9 +1888,15 @@
Slog.d(TAG, String.format("handlePackageRemoved: %s user=%d", packageName,
packageUserId));
}
+ handlePackageRemovedInner(packageName, packageUserId, /* forceForCommandLine =*/ false);
+ }
+
+ private void handlePackageRemovedInner(String packageName, @UserIdInt int packageUserId,
+ boolean forceForCommandLine) {
synchronized (mLock) {
forEachLoadedUserLocked(user ->
- cleanUpPackageLocked(packageName, user.getUserId(), packageUserId));
+ cleanUpPackageLocked(packageName, user.getUserId(), packageUserId,
+ forceForCommandLine));
}
}
@@ -2048,17 +2077,26 @@
pw.print(formatTime(next));
pw.println();
- pw.print(" Max icon dim: ");
- pw.print(mMaxIconDimension);
- pw.print(" Icon format: ");
- pw.print(mIconPersistFormat);
- pw.print(" Icon quality: ");
+ pw.print(" Config:");
+ pw.print(" Max icon dim: ");
+ pw.println(mMaxIconDimension);
+ pw.print(" Icon format: ");
+ pw.println(mIconPersistFormat);
+ pw.print(" Icon quality: ");
pw.println(mIconPersistQuality);
+ pw.print(" saveDelayMillis:");
+ pw.println(mSaveDelayMillis);
+ pw.print(" resetInterval:");
+ pw.println(mResetInterval);
+ pw.print(" maxUpdatesPerInterval:");
+ pw.println(mMaxUpdatesPerInterval);
+ pw.print(" maxDynamicShortcuts:");
+ pw.println(mMaxDynamicShortcuts);
pw.println();
pw.println(" Stats:");
synchronized (mStatLock) {
- final String p = " ";
+ final String p = " ";
dumpStatLS(pw, p, Stats.GET_DEFAULT_HOME, "getHomeActivities()");
dumpStatLS(pw, p, Stats.LAUNCHER_PERMISSION_CHECK, "Launcher permission check");
@@ -2144,6 +2182,9 @@
case "reset-throttling":
handleResetThrottling();
break;
+ case "reset-all-throttling":
+ handleResetAllThrottling();
+ break;
case "override-config":
handleOverrideConfig();
break;
@@ -2162,6 +2203,9 @@
case "unload-user":
handleUnloadUser();
break;
+ case "clear-shortcuts":
+ handleClearShortcuts();
+ break;
default:
return handleDefaultCommands(cmd);
}
@@ -2181,9 +2225,12 @@
pw.println("cmd shortcut reset-package-throttling [--user USER_ID] PACKAGE");
pw.println(" Reset throttling for a package");
pw.println();
- pw.println("cmd shortcut reset-throttling");
+ pw.println("cmd shortcut reset-throttling [--user USER_ID]");
pw.println(" Reset throttling for all packages and users");
pw.println();
+ pw.println("cmd shortcut reset-all-throttling");
+ pw.println(" Reset the throttling state for all users");
+ pw.println();
pw.println("cmd shortcut override-config CONFIG");
pw.println(" Override the configuration for testing (will last until reboot)");
pw.println();
@@ -2203,13 +2250,23 @@
pw.println(" Unload a user from the memory");
pw.println(" (This should not affect any observable behavior)");
pw.println();
+ pw.println("cmd shortcut clear-shortcuts [--user USER_ID] PACKAGE");
+ pw.println(" Remove all shortcuts from a package, including pinned shortcuts");
+ pw.println();
}
- private int handleResetThrottling() throws CommandException {
+ private void handleResetThrottling() throws CommandException {
parseOptions(/* takeUser =*/ true);
+ Slog.i(TAG, "cmd: handleResetThrottling");
+
resetThrottlingInner(mUserId);
- return 0;
+ }
+
+ private void handleResetAllThrottling() {
+ Slog.i(TAG, "cmd: handleResetAllThrottling");
+
+ resetAllThrottlingInner();
}
private void handleResetPackageThrottling() throws CommandException {
@@ -2217,6 +2274,8 @@
final String packageName = getNextArgRequired();
+ Slog.i(TAG, "cmd: handleResetPackageThrottling: " + packageName);
+
synchronized (mLock) {
getPackageShortcutsLocked(packageName, mUserId).resetRateLimitingForCommandLine();
saveUserLocked(mUserId);
@@ -2226,6 +2285,8 @@
private void handleOverrideConfig() throws CommandException {
final String config = getNextArgRequired();
+ Slog.i(TAG, "cmd: handleOverrideConfig: " + config);
+
synchronized (mLock) {
if (!updateConfigurationLocked(config)) {
throw new CommandException("override-config failed. See logcat for details.");
@@ -2234,6 +2295,8 @@
}
private void handleResetConfig() {
+ Slog.i(TAG, "cmd: handleResetConfig");
+
synchronized (mLock) {
loadConfigurationLocked();
}
@@ -2278,8 +2341,20 @@
private void handleUnloadUser() throws CommandException {
parseOptions(/* takeUser =*/ true);
+ Slog.i(TAG, "cmd: handleUnloadUser: " + mUserId);
+
ShortcutService.this.handleCleanupUser(mUserId);
}
+
+ private void handleClearShortcuts() throws CommandException {
+ parseOptions(/* takeUser =*/ true);
+ final String packageName = getNextArgRequired();
+
+ Slog.i(TAG, "cmd: handleClearShortcuts: " + mUserId + ", " + packageName);
+
+ ShortcutService.this.handlePackageRemovedInner(packageName, mUserId,
+ /* forceForCommandLine= */ true);
+ }
}
// === Unit test support ===
@@ -2357,8 +2432,8 @@
}
@VisibleForTesting
- int getMaxDailyUpdatesForTest() {
- return mMaxDailyUpdates;
+ int getMaxUpdatesPerIntervalForTest() {
+ return mMaxUpdatesPerInterval;
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 60a0d62..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;
@@ -483,13 +484,50 @@
}
}
+ @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 getProfileIdsLU(userId, enabledOnly).toArray();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
/** Assume permissions already checked and caller's identity cleared */
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++) {
@@ -506,16 +544,9 @@
if (profile.partial) {
continue;
}
- UserInfo userInfo = userWithName(profile);
- // 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;
- }
- users.add(userInfo);
+ result.add(profile.id);
}
- return users;
+ return result;
}
@Override
diff --git a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
index 160d44c..553c5de 100644
--- a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
@@ -27,8 +27,11 @@
import android.graphics.drawable.ColorDrawable;
import android.os.Handler;
import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
+import android.service.vr.IVrManager;
import android.util.DisplayMetrics;
import android.util.Slog;
import android.util.SparseBooleanArray;
@@ -45,6 +48,7 @@
import android.widget.FrameLayout;
import com.android.internal.R;
+import com.android.server.vr.VrManagerService;
/**
* Helper to manage showing/hiding a confirmation prompt when the navigation bar is hidden
@@ -66,6 +70,7 @@
private long mPanicTime;
private WindowManager mWindowManager;
private int mCurrentUserId;
+ private IVrManager mVrManager;
public ImmersiveModeConfirmation(Context context) {
mContext = context;
@@ -112,6 +117,21 @@
}
}
+ private boolean getVrMode() {
+ boolean vrMode = false;
+ if (mVrManager == null) {
+ // lazily grab this service since it may not be available at construction time
+ mVrManager = (IVrManager) IVrManager.Stub.asInterface(
+ ServiceManager.getService(VrManagerService.VR_MANAGER_BINDER_SERVICE));
+ }
+ if (mVrManager != null) {
+ try {
+ vrMode = mVrManager.getVrModeState();
+ } catch (RemoteException ex) { }
+ }
+ return vrMode;
+ }
+
public void immersiveModeChanged(String pkg, boolean isImmersiveMode,
boolean userSetupComplete) {
mHandler.removeMessages(H.SHOW);
@@ -119,7 +139,10 @@
final boolean disabled = PolicyControl.disableImmersiveConfirmation(pkg);
if (DEBUG) Slog.d(TAG, String.format("immersiveModeChanged() disabled=%s mConfirmed=%s",
disabled, mConfirmed));
- if (!disabled && (DEBUG_SHOW_EVERY_TIME || !mConfirmed) && userSetupComplete) {
+ if (!disabled
+ && (DEBUG_SHOW_EVERY_TIME || !mConfirmed)
+ && userSetupComplete
+ && !getVrMode()) {
mHandler.sendEmptyMessageDelayed(H.SHOW, mShowDelayMs);
}
} else {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 5ce451f..2e81132 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -318,6 +318,7 @@
AccessibilityManager mAccessibilityManager;
BurnInProtectionHelper mBurnInProtectionHelper;
AppOpsManager mAppOpsManager;
+ private boolean mHasFeatureWatch;
// Vibrator pattern for haptic feedback of a long press.
long[] mLongPressVibePattern;
@@ -693,6 +694,7 @@
= new LogDecelerateInterpolator(100, 0);
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;
@@ -1501,6 +1503,7 @@
mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
+ mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
// Init display burn-in protection
boolean burnInProtectionEnabled = context.getResources().getBoolean(
@@ -3393,7 +3396,9 @@
IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode);
if (shortcutService != null) {
try {
- shortcutService.notifyShortcutKeyPressed(shortcutCode);
+ if (isUserSetupComplete()) {
+ shortcutService.notifyShortcutKeyPressed(shortcutCode);
+ }
} catch (RemoteException e) {
mShortcutKeyServices.delete(shortcutCode);
}
@@ -5780,9 +5785,14 @@
}
private boolean shouldDispatchInputWhenNonInteractive() {
- // Send events to keyguard while the screen is on.
- if (isKeyguardShowingAndNotOccluded() && mDisplay != null
- && mDisplay.getState() != Display.STATE_OFF) {
+ final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
+
+ if (displayOff && !mHasFeatureWatch) {
+ return false;
+ }
+
+ // Send events to keyguard while the screen is on and it's showing.
+ if (isKeyguardShowingAndNotOccluded() && !displayOff) {
return true;
}
@@ -6695,7 +6705,7 @@
@Override public void run() {
if (mBootMsgDialog == null) {
int theme;
- if (mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH)) {
+ if (mHasFeatureWatch) {
theme = com.android.internal.R.style.Theme_Micro_Dialog_Alert;
} else if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) {
theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert;
@@ -7180,10 +7190,6 @@
tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
}
- if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
- tmpVisibility |= StatusBarManager.DISABLE_RECENT;
- }
-
final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
diff --git a/services/core/java/com/android/server/policy/ShortcutManager.java b/services/core/java/com/android/server/policy/ShortcutManager.java
index a14c614..ab404db 100644
--- a/services/core/java/com/android/server/policy/ShortcutManager.java
+++ b/services/core/java/com/android/server/policy/ShortcutManager.java
@@ -27,7 +27,9 @@
import android.util.SparseArray;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
+
import com.android.internal.util.XmlUtils;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 984fb76..3c84fc2 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -974,7 +974,6 @@
public void register(Context context) {
IntentFilter filter = new IntentFilter();
filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
- filter.addAction(Intent.ACTION_USER_PRESENT);
filter.addAction(Intent.ACTION_USER_ADDED);
filter.addAction(Intent.ACTION_USER_REMOVED);
context.registerReceiverAsUser(this,
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 f004b45..49ff385 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -50,6 +50,8 @@
import com.android.server.utils.ManagedApplicationService;
import com.android.server.utils.ManagedApplicationService.BinderChecker;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.lang.StringBuilder;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -103,6 +105,7 @@
new RemoteCallbackList<>();
private final ArraySet<String> mPreviousToggledListenerSettings = new ArraySet<>();
private String mPreviousNotificationPolicyAccessPackage;
+ private String mPreviousCoarseLocationPackage;
private String mPreviousManageOverlayPackage;
private static final int MSG_VR_STATE_CHANGE = 0;
@@ -186,6 +189,32 @@
return VrManagerService.this.getVrMode();
}
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("permission denied: can't dump VrManagerService from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+ pw.print("mVrModeEnabled=");
+ pw.println(mVrModeEnabled);
+ pw.print("mCurrentVrModeUser=");
+ pw.println(mCurrentVrModeUser);
+ pw.print("mRemoteCallbacks=");
+ int i=mRemoteCallbacks.beginBroadcast(); // create the broadcast item array
+ while(i-->0) {
+ pw.print(mRemoteCallbacks.getBroadcastItem(i));
+ if (i>0) pw.print(", ");
+ }
+ mRemoteCallbacks.finishBroadcast();
+ pw.println();
+ pw.print("mCurrentVrService=");
+ pw.println(mCurrentVrService != null ? mCurrentVrService.getComponent() : "(none)");
+ pw.print("mCurrentVrModeComponent=");
+ pw.println(mCurrentVrModeComponent);
+ }
+
};
private void enforceCallerPermission(String permission) {
@@ -418,6 +447,7 @@
mWasDefaultGranted = true;
+ grantCoarseLocationAccess(pName, userId);
grantOverlayAccess(pName, userId);
grantNotificationPolicyAccess(pName);
grantNotificationListenerAccess(pName, userId);
@@ -447,6 +477,7 @@
String pName = component.getPackageName();
if (mWasDefaultGranted) {
+ revokeCoarseLocationAccess(userId);
revokeOverlayAccess(userId);
revokeNotificationPolicyAccess(pName);
revokeNotificiationListenerAccess();
@@ -455,6 +486,27 @@
}
+ private void grantCoarseLocationAccess(String pkg, UserHandle userId) {
+ PackageManager pm = mContext.getPackageManager();
+ boolean prev = (PackageManager.PERMISSION_GRANTED ==
+ pm.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION, pkg));
+ mPreviousCoarseLocationPackage = null;
+ if (!prev) {
+ pm.grantRuntimePermission(pkg, android.Manifest.permission.ACCESS_COARSE_LOCATION,
+ userId);
+ mPreviousCoarseLocationPackage = pkg;
+ }
+ }
+
+ private void revokeCoarseLocationAccess(UserHandle userId) {
+ PackageManager pm = mContext.getPackageManager();
+ if (mPreviousCoarseLocationPackage != null) {
+ pm.revokeRuntimePermission(mPreviousCoarseLocationPackage,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION, userId);
+ mPreviousCoarseLocationPackage = null;
+ }
+ }
+
private void grantOverlayAccess(String pkg, UserHandle userId) {
PackageManager pm = mContext.getPackageManager();
boolean prev = (PackageManager.PERMISSION_GRANTED ==
@@ -476,7 +528,6 @@
}
}
-
private void grantNotificationPolicyAccess(String pkg) {
NotificationManager nm = mContext.getSystemService(NotificationManager.class);
boolean prev = nm.isNotificationPolicyAccessGrantedForPackage(pkg);
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index fb3c6ec..91b6914 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -16,9 +16,12 @@
package com.android.server.wallpaper;
-import static android.app.WallpaperManager.FLAG_SYSTEM;
import static android.app.WallpaperManager.FLAG_LOCK;
-import static android.os.ParcelFileDescriptor.*;
+import static android.app.WallpaperManager.FLAG_SYSTEM;
+import static android.os.ParcelFileDescriptor.MODE_CREATE;
+import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
+import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
+import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
@@ -41,9 +44,9 @@
import android.content.ServiceConnection;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -54,13 +57,13 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
+import android.os.FileObserver;
import android.os.FileUtils;
import android.os.IBinder;
import android.os.IRemoteCallback;
-import android.os.RemoteException;
-import android.os.FileObserver;
import android.os.ParcelFileDescriptor;
import android.os.RemoteCallbackList;
+import android.os.RemoteException;
import android.os.SELinux;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -78,35 +81,64 @@
import android.view.IWindowManager;
import android.view.WindowManager;
-import java.io.BufferedOutputStream;
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.PrintWriter;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.List;
+import com.android.internal.R;
+import com.android.internal.content.PackageMonitor;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.JournaledFile;
+import com.android.server.EventLogTags;
+import com.android.server.SystemService;
+
+import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
-import com.android.internal.content.PackageMonitor;
-import com.android.internal.util.FastXmlSerializer;
-import com.android.internal.util.JournaledFile;
-import com.android.internal.R;
-import com.android.server.EventLogTags;
-
-import libcore.io.IoUtils;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.List;
public class WallpaperManagerService extends IWallpaperManager.Stub {
static final String TAG = "WallpaperManagerService";
static final boolean DEBUG = false;
+ public static class Lifecycle extends SystemService {
+ private WallpaperManagerService mService;
+
+ public Lifecycle(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ mService = new WallpaperManagerService(getContext());
+ publishBinderService(Context.WALLPAPER_SERVICE, mService);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
+ mService.systemReady();
+ } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
+ mService.switchUser(UserHandle.USER_SYSTEM, null);
+ }
+ }
+
+ @Override
+ public void onUnlockUser(int userHandle) {
+ mService.onUnlockUser(userHandle);
+ }
+ }
+
final Object mLock = new Object();
/**
@@ -265,70 +297,134 @@
*/
private void generateCrop(WallpaperData wallpaper) {
boolean success = false;
- boolean needCrop = false;
- boolean needScale = false;
+
+ Rect cropHint = new Rect(wallpaper.cropHint);
if (DEBUG) {
Slog.v(TAG, "Generating crop for new wallpaper(s): 0x"
+ Integer.toHexString(wallpaper.whichPending)
- + " to " + wallpaper.cropFile.getName());
+ + " to " + wallpaper.cropFile.getName()
+ + " crop=(" + cropHint.width() + 'x' + cropHint.height()
+ + ") dim=(" + wallpaper.width + 'x' + wallpaper.height + ')');
}
// Analyse the source; needed in multiple cases
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(wallpaper.wallpaperFile.getAbsolutePath(), options);
-
- // We'll need to scale if the crop is sufficiently bigger than the display
-
- // Legacy case uses an empty crop rect here, so we just preserve the
- // source image verbatim
- if (!wallpaper.cropHint.isEmpty()) {
- // ...clamp the crop rect to the measured bounds...
- wallpaper.cropHint.right = Math.min(wallpaper.cropHint.right, options.outWidth);
- wallpaper.cropHint.bottom = Math.min(wallpaper.cropHint.bottom, options.outHeight);
- // ...and don't bother cropping if what we're left with is identity
- needCrop = (options.outHeight >= wallpaper.cropHint.height()
- && options.outWidth >= wallpaper.cropHint.width());
- }
-
- if (!needCrop && !needScale) {
- // Simple case: the nominal crop is at least as big as the source image,
- // so we take the whole thing and just copy the image file directly.
- if (DEBUG) {
- Slog.v(TAG, "Null crop of new wallpaper; copying");
- }
- success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
- if (!success) {
- wallpaper.cropFile.delete();
- // TODO: fall back to default wallpaper in this case
- }
+ if (options.outWidth <= 0 || options.outHeight <= 0) {
+ Slog.e(TAG, "Invalid wallpaper data");
+ success = false;
} else {
- // Fancy case: crop and/or scale
- FileOutputStream f = null;
- BufferedOutputStream bos = null;
- try {
- BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(
- wallpaper.wallpaperFile.getAbsolutePath(), false);
- Bitmap cropped = decoder.decodeRegion(wallpaper.cropHint, null);
- decoder.recycle();
+ boolean needCrop = false;
+ boolean needScale = false;
- if (cropped == null) {
- Slog.e(TAG, "Could not decode new wallpaper");
- } else {
- f = new FileOutputStream(wallpaper.cropFile);
- bos = new BufferedOutputStream(f, 32*1024);
- cropped.compress(Bitmap.CompressFormat.PNG, 90, bos);
- bos.flush(); // don't rely on the implicit flush-at-close when noting success
- success = true;
- }
- } catch (IOException e) {
+ // Empty crop means use the full image
+ if (cropHint.isEmpty()) {
+ cropHint.left = cropHint.top = 0;
+ cropHint.right = options.outWidth;
+ cropHint.bottom = options.outHeight;
+ } else {
+ // force the crop rect to lie within the measured bounds
+ cropHint.offset(
+ (cropHint.right > options.outWidth ? options.outWidth - cropHint.right : 0),
+ (cropHint.bottom > options.outHeight ? options.outHeight - cropHint.bottom : 0));
+
+ // Don't bother cropping if what we're left with is identity
+ needCrop = (options.outHeight >= cropHint.height()
+ && options.outWidth >= cropHint.width());
+ }
+
+ // scale if the crop height winds up not matching the recommended metrics
+ needScale = (wallpaper.height != cropHint.height());
+
+ if (DEBUG) {
+ Slog.v(TAG, "crop: w=" + cropHint.width() + " h=" + cropHint.height());
+ Slog.v(TAG, "dims: w=" + wallpaper.width + " h=" + wallpaper.height);
+ Slog.v(TAG, "meas: w=" + options.outWidth + " h=" + options.outHeight);
+ Slog.v(TAG, "crop?=" + needCrop + " scale?=" + needScale);
+ }
+
+ if (!needCrop && !needScale) {
+ // Simple case: the nominal crop fits what we want, so we take
+ // the whole thing and just copy the image file directly.
if (DEBUG) {
- Slog.e(TAG, "I/O error decoding crop: " + e.getMessage());
+ Slog.v(TAG, "Null crop of new wallpaper; copying");
}
- } finally {
- IoUtils.closeQuietly(bos);
- IoUtils.closeQuietly(f);
+ success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
+ if (!success) {
+ wallpaper.cropFile.delete();
+ // TODO: fall back to default wallpaper in this case
+ }
+ } else {
+ // Fancy case: crop and scale. First, we decode and scale down if appropriate.
+ FileOutputStream f = null;
+ BufferedOutputStream bos = null;
+ try {
+ BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(
+ wallpaper.wallpaperFile.getAbsolutePath(), false);
+
+ // This actually downsamples only by powers of two, but that's okay; we do
+ // a proper scaling blit later. This is to minimize transient RAM use.
+ // We calculate the largest power-of-two under the actual ratio rather than
+ // just let the decode take care of it because we also want to remap where the
+ // cropHint rectangle lies in the decoded [super]rect.
+ final BitmapFactory.Options scaler;
+ final int actualScale = cropHint.height() / wallpaper.height;
+ int scale = 1;
+ while (2*scale < actualScale) {
+ scale *= 2;
+ }
+ if (scale > 1) {
+ scaler = new BitmapFactory.Options();
+ scaler.inSampleSize = scale;
+ if (DEBUG) {
+ Slog.v(TAG, "Downsampling cropped rect with scale " + scale);
+ }
+ } else {
+ scaler = null;
+ }
+ Bitmap cropped = decoder.decodeRegion(cropHint, scaler);
+ decoder.recycle();
+
+ if (cropped == null) {
+ Slog.e(TAG, "Could not decode new wallpaper");
+ } else {
+ // We've got the extracted crop; now we want to scale it properly to
+ // the desired rectangle. That's a height-biased operation: make it
+ // fit the hinted height, and accept whatever width we end up with.
+ cropHint.offsetTo(0, 0);
+ cropHint.right /= scale; // adjust by downsampling factor
+ cropHint.bottom /= scale;
+ final float heightR = ((float)wallpaper.height) / ((float)cropHint.height());
+ if (DEBUG) {
+ Slog.v(TAG, "scale " + heightR + ", extracting " + cropHint);
+ }
+ final int destWidth = (int)(cropHint.width() * heightR);
+ final Bitmap finalCrop = Bitmap.createScaledBitmap(cropped,
+ destWidth, wallpaper.height, true);
+ if (DEBUG) {
+ Slog.v(TAG, "Final extract:");
+ Slog.v(TAG, " dims: w=" + wallpaper.width
+ + " h=" + wallpaper.height);
+ Slog.v(TAG, " out: w=" + finalCrop.getWidth()
+ + " h=" + finalCrop.getHeight());
+ }
+
+ f = new FileOutputStream(wallpaper.cropFile);
+ bos = new BufferedOutputStream(f, 32*1024);
+ finalCrop.compress(Bitmap.CompressFormat.PNG, 90, bos);
+ bos.flush(); // don't rely on the implicit flush-at-close when noting success
+ success = true;
+ }
+ } catch (Exception e) {
+ if (DEBUG) {
+ Slog.e(TAG, "Error decoding crop", e);
+ }
+ } finally {
+ IoUtils.closeQuietly(bos);
+ IoUtils.closeQuietly(f);
+ }
}
}
@@ -352,6 +448,7 @@
final AppOpsManager mAppOpsManager;
WallpaperData mLastWallpaper;
IWallpaperManagerCallback mKeyguardListener;
+ boolean mWaitingForUnlock;
/**
* ID of the current wallpaper, changed every time anything sets a wallpaper.
@@ -679,8 +776,9 @@
if (wallpaper.wallpaperComponent != null
&& isPackageModified(wallpaper.wallpaperComponent.getPackageName())) {
try {
- mContext.getPackageManager().getServiceInfo(
- wallpaper.wallpaperComponent, 0);
+ mContext.getPackageManager().getServiceInfo(wallpaper.wallpaperComponent,
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
} catch (NameNotFoundException e) {
Slog.w(TAG, "Wallpaper component gone, removing: "
+ wallpaper.wallpaperComponent);
@@ -690,8 +788,9 @@
if (wallpaper.nextWallpaperComponent != null
&& isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) {
try {
- mContext.getPackageManager().getServiceInfo(
- wallpaper.nextWallpaperComponent, 0);
+ mContext.getPackageManager().getServiceInfo(wallpaper.nextWallpaperComponent,
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
} catch (NameNotFoundException e) {
wallpaper.nextWallpaperComponent = null;
}
@@ -728,7 +827,7 @@
}
}
- public void systemRunning() {
+ void systemReady() {
if (DEBUG) Slog.v(TAG, "systemReady");
WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
// If we think we're going to be using the system image wallpaper imagery, make
@@ -753,9 +852,6 @@
Slog.i(TAG, "Nondefault wallpaper component; gracefully ignoring");
}
}
- switchWallpaper(wallpaper, null);
- wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
- wallpaper.wallpaperObserver.startWatching();
IntentFilter userFilter = new IntentFilter();
userFilter.addAction(Intent.ACTION_USER_REMOVED);
@@ -763,7 +859,7 @@
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
+ final String action = intent.getAction();
if (Intent.ACTION_USER_REMOVED.equals(action)) {
onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
UserHandle.USER_NULL));
@@ -827,6 +923,14 @@
mLockWallpaperMap.remove(userId);
}
+ void onUnlockUser(int userId) {
+ synchronized (mLock) {
+ if (mCurrentUserId == userId && mWaitingForUnlock) {
+ switchUser(userId, null);
+ }
+ }
+ }
+
void onRemoveUser(int userId) {
if (userId < 1) return;
@@ -854,18 +958,35 @@
void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
synchronized (mLock) {
- RuntimeException e = null;
- try {
- ComponentName cname = wallpaper.wallpaperComponent != null ?
- wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
- if (bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
- return;
+ mWaitingForUnlock = false;
+ final ComponentName cname = wallpaper.wallpaperComponent != null ?
+ wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
+ if (!bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
+ // We failed to bind the desired wallpaper, but that might
+ // happen if the wallpaper isn't direct-boot aware
+ ServiceInfo si = null;
+ try {
+ si = mIPackageManager.getServiceInfo(cname,
+ PackageManager.MATCH_DIRECT_BOOT_UNAWARE, wallpaper.userId);
+ } catch (RemoteException ignored) {
}
- } catch (RuntimeException e1) {
- e = e1;
+
+ if (si == null) {
+ Slog.w(TAG, "Failure starting previous wallpaper; clearing");
+ clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, reply);
+ } else {
+ Slog.w(TAG, "Wallpaper isn't direct boot aware; using fallback until unlocked");
+ // We might end up persisting the current wallpaper data
+ // while locked, so pretend like the component was actually
+ // bound into place
+ wallpaper.wallpaperComponent = wallpaper.nextWallpaperComponent;
+ final WallpaperData fallback = new WallpaperData(wallpaper.userId,
+ WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
+ ensureSaneWallpaperData(fallback);
+ bindWallpaperComponentLocked(mImageWallpaper, true, false, fallback, reply);
+ mWaitingForUnlock = true;
+ }
}
- Slog.w(TAG, "Failure starting previous wallpaper", e);
- clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, reply);
}
}
@@ -1653,12 +1774,14 @@
wallpaper = new WallpaperData(userId,
WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
mLockWallpaperMap.put(userId, wallpaper);
+ ensureSaneWallpaperData(wallpaper);
} else {
// sanity fallback: we're in bad shape, but establishing a known
// valid system+lock WallpaperData will keep us from dying.
Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!");
wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
mWallpaperMap.put(userId, wallpaper);
+ ensureSaneWallpaperData(wallpaper);
}
}
}
@@ -1751,6 +1874,8 @@
wallpaper.cropHint.set(0, 0, 0, 0);
wallpaper.padding.set(0, 0, 0, 0);
wallpaper.name = "";
+
+ mLockWallpaperMap.remove(userId);
} else {
if (wallpaper.wallpaperId <= 0) {
wallpaper.wallpaperId = makeWallpaperIdLocked();
@@ -1761,6 +1886,14 @@
}
}
+ ensureSaneWallpaperData(wallpaper);
+ WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
+ if (lockWallpaper != null) {
+ ensureSaneWallpaperData(lockWallpaper);
+ }
+ }
+
+ private void ensureSaneWallpaperData(WallpaperData wallpaper) {
// We always want to have some reasonable width hint.
int baseSize = getMaximumSizeDimension();
if (wallpaper.width < baseSize) {
@@ -1952,11 +2085,11 @@
}
synchronized (mLock) {
- pw.println("Current Wallpaper Service state:");
+ pw.println("System wallpaper state:");
for (int i = 0; i < mWallpaperMap.size(); i++) {
WallpaperData wallpaper = mWallpaperMap.valueAt(i);
pw.print(" User "); pw.print(wallpaper.userId);
- pw.print(": id="); pw.println(wallpaper.wallpaperId);
+ pw.print(": id="); pw.println(wallpaper.wallpaperId);
pw.print(" mWidth=");
pw.print(wallpaper.width);
pw.print(" mHeight=");
@@ -1984,6 +2117,18 @@
pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
}
}
+ pw.println("Lock wallpaper state:");
+ for (int i = 0; i < mLockWallpaperMap.size(); i++) {
+ WallpaperData wallpaper = mLockWallpaperMap.valueAt(i);
+ pw.print(" User "); pw.print(wallpaper.userId);
+ pw.print(": id="); pw.println(wallpaper.wallpaperId);
+ pw.print(" mWidth="); pw.print(wallpaper.width);
+ pw.print(" mHeight="); pw.println(wallpaper.height);
+ pw.print(" mCropHint="); pw.println(wallpaper.cropHint);
+ pw.print(" mPadding="); pw.println(wallpaper.padding);
+ pw.print(" mName="); pw.println(wallpaper.name);
+ }
+
}
}
}
diff --git a/services/core/java/com/android/server/webkit/SystemImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java
index 9486cfd..361f0d4 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;
@@ -33,7 +34,6 @@
import android.provider.Settings;
import android.util.AndroidRuntimeException;
import android.util.Log;
-import android.webkit.WebViewFactory.MissingWebViewPackageException;
import android.webkit.WebViewFactory;
import android.webkit.WebViewProviderInfo;
@@ -59,14 +59,22 @@
private static final String TAG_AVAILABILITY = "availableByDefault";
private static final String TAG_SIGNATURE = "signature";
private static final String TAG_FALLBACK = "isFallback";
+ private final WebViewProviderInfo[] mWebViewProviderPackages;
- /**
- * Returns all packages declared in the framework resources as potential WebView providers.
- * @hide
- * */
- @Override
- public WebViewProviderInfo[] getWebViewPackages() {
+ // Initialization-on-demand holder idiom for getting the WebView provider packages once and
+ // for all in a thread-safe manner.
+ private static class LazyHolder {
+ private static final SystemImpl INSTANCE = new SystemImpl();
+ }
+
+ public static SystemImpl getInstance() {
+ return LazyHolder.INSTANCE;
+ }
+
+ private SystemImpl() {
int numFallbackPackages = 0;
+ int numAvailableByDefaultPackages = 0;
+ int numAvByDefaultAndNotFallback = 0;
XmlResourceParser parser = null;
List<WebViewProviderInfo> webViewProviders = new ArrayList<WebViewProviderInfo>();
try {
@@ -82,12 +90,12 @@
if (element.equals(TAG_WEBVIEW_PROVIDER)) {
String packageName = parser.getAttributeValue(null, TAG_PACKAGE_NAME);
if (packageName == null) {
- throw new MissingWebViewPackageException(
+ throw new AndroidRuntimeException(
"WebView provider in framework resources missing package name");
}
String description = parser.getAttributeValue(null, TAG_DESCRIPTION);
if (description == null) {
- throw new MissingWebViewPackageException(
+ throw new AndroidRuntimeException(
"WebView provider in framework resources missing description");
}
boolean availableByDefault = "true".equals(
@@ -99,23 +107,50 @@
readSignatures(parser));
if (currentProvider.isFallback) {
numFallbackPackages++;
+ if (!currentProvider.availableByDefault) {
+ throw new AndroidRuntimeException(
+ "Each WebView fallback package must be available by default.");
+ }
if (numFallbackPackages > 1) {
throw new AndroidRuntimeException(
- "There can be at most one webview fallback package.");
+ "There can be at most one WebView fallback package.");
+ }
+ }
+ if (currentProvider.availableByDefault) {
+ numAvailableByDefaultPackages++;
+ if (!currentProvider.isFallback) {
+ numAvByDefaultAndNotFallback++;
}
}
webViewProviders.add(currentProvider);
}
else {
- Log.e(TAG, "Found an element that is not a webview provider");
+ Log.e(TAG, "Found an element that is not a WebView provider");
}
}
} catch (XmlPullParserException | IOException e) {
- throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e);
+ throw new AndroidRuntimeException("Error when parsing WebView config " + e);
} finally {
if (parser != null) parser.close();
}
- return webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]);
+ if (numAvailableByDefaultPackages == 0) {
+ throw new AndroidRuntimeException("There must be at least one WebView package "
+ + "that is available by default");
+ }
+ if (numAvByDefaultAndNotFallback == 0) {
+ throw new AndroidRuntimeException("There must be at least one WebView package "
+ + "that is available by default and not a fallback");
+ }
+ mWebViewProviderPackages =
+ webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]);
+ }
+ /**
+ * Returns all packages declared in the framework resources as potential WebView providers.
+ * @hide
+ * */
+ @Override
+ public WebViewProviderInfo[] getWebViewPackages() {
+ return mWebViewProviderPackages;
}
public int getFactoryPackageVersion(String packageName) throws NameNotFoundException {
@@ -187,7 +222,8 @@
enablePackageForAllUsers(context, packageName, false);
try {
PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
- if (pm.getApplicationInfo(packageName, 0).isUpdatedSystemApp()) {
+ 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);
@@ -214,8 +250,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 1f6fb2a..9b971e0 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -55,7 +55,7 @@
public WebViewUpdateService(Context context) {
super(context);
- mImpl = new WebViewUpdateServiceImpl(context, new SystemImpl());
+ mImpl = new WebViewUpdateServiceImpl(context, SystemImpl.getInstance());
}
@Override
@@ -242,7 +242,12 @@
throw new SecurityException(msg);
}
- WebViewUpdateService.this.mImpl.enableFallbackLogic(enable);
+ long callingId = Binder.clearCallingIdentity();
+ try {
+ WebViewUpdateService.this.mImpl.enableFallbackLogic(enable);
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
index 32b195b..d90d922 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
@@ -119,6 +119,8 @@
}
private void updateFallbackStateOnBoot() {
+ if (!mSystemInterface.isFallbackLogicEnabled()) return;
+
WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
updateFallbackState(webviewProviders, true);
}
@@ -160,6 +162,8 @@
isFallbackEnabled = isEnabledPackage(
mSystemInterface.getPackageInfoForProvider(fallbackProvider));
} catch (NameNotFoundException e) {
+ // No fallback package installed -> early out.
+ return;
}
if (existsValidNonFallbackProvider
@@ -241,8 +245,16 @@
synchronized(mLock) {
try {
newPackage = findPreferredWebViewPackage();
- if (mCurrentWebViewPackage != null)
+ if (mCurrentWebViewPackage != null) {
oldProviderName = mCurrentWebViewPackage.packageName;
+ if (changedState == WebViewUpdateService.PACKAGE_CHANGED
+ && newPackage.packageName.equals(oldProviderName)) {
+ // If we don't change package name we should only rerun the
+ // preparation phase if the current package has been replaced
+ // (not if it has been enabled/disabled).
+ return;
+ }
+ }
// 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.
@@ -279,6 +291,13 @@
try {
synchronized(mLock) {
mCurrentWebViewPackage = findPreferredWebViewPackage();
+ // Don't persist the user-chosen setting across boots if the package being
+ // chosen is not used (could be disabled or uninstalled) so that the user won't
+ // be surprised by the device switching to using a certain webview package,
+ // that was uninstalled/disabled a long time ago, if it is installed/enabled
+ // again.
+ mSystemInterface.updateUserSetting(mContext,
+ mCurrentWebViewPackage.packageName);
onWebViewProviderChanged(mCurrentWebViewPackage);
}
} catch (Throwable t) {
@@ -289,38 +308,42 @@
/**
* 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).
+ * Return the new provider (in case we are in the middle of creating relro files, or
+ * replacing that provider it will not be in use directly, but will be used when the relros
+ * or the replacement are done).
*/
public String changeProviderAndSetting(String newProviderName) {
PackageInfo oldPackage = null;
PackageInfo newPackage = null;
+ boolean providerChanged = false;
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;
- }
+ providerChanged = (oldPackage == null)
+ || !newPackage.packageName.equals(oldPackage.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;
+ return "";
}
- onWebViewProviderChanged(newPackage);
+ // Perform the provider change if we chose a new provider
+ if (providerChanged) {
+ onWebViewProviderChanged(newPackage);
+ }
}
- // Kill apps using the old provider
- if (oldPackage != null) {
+ // Kill apps using the old provider only if we changed provider
+ if (providerChanged && oldPackage != null) {
mSystemInterface.killPackageDependents(oldPackage.packageName);
}
+ // Return the new provider, this is not necessarily the one we were asked to switch to
+ // But the persistent setting will now be pointing to the provider we were asked to
+ // switch to anyway
return newPackage.packageName;
}
@@ -333,7 +356,6 @@
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
@@ -382,7 +404,7 @@
}
- private class ProviderAndPackageInfo {
+ private static class ProviderAndPackageInfo {
public final WebViewProviderInfo provider;
public final PackageInfo packageInfo;
@@ -420,9 +442,12 @@
}
}
- // Could not find any enabled package either, use the most stable provider.
+ // Could not find any enabled package either, use the most stable and default-available
+ // provider.
for (ProviderAndPackageInfo providerAndPackage : providers) {
- return providerAndPackage.packageInfo;
+ if (providerAndPackage.provider.availableByDefault) {
+ return providerAndPackage.packageInfo;
+ }
}
mAnyWebViewInstalled = false;
@@ -495,8 +520,15 @@
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);
+ try {
+ PackageInfo newPackage = findPreferredWebViewPackage();
+ onWebViewProviderChanged(newPackage);
+ } catch (WebViewFactory.MissingWebViewPackageException e) {
+ // If we can't find any valid WebView package we are now in a state where
+ // mAnyWebViewInstalled is false, so loading WebView will be blocked and we
+ // should simply wait until we receive an intent declaring a new package was
+ // installed.
+ }
} else {
mLock.notifyAll();
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 28379f4..1f16481 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -290,7 +290,7 @@
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
TaskStack stack = mStacks.get(stackNdx);
stack.getBounds(mTmpRect);
- if (!mTmpRect.contains(x, y)) {
+ if (!mTmpRect.contains(x, y) || stack.isAdjustedForMinimizedDockedStack()) {
continue;
}
final ArrayList<Task> tasks = stack.getTasks();
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 6ac71c7..ff537be 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -270,6 +270,19 @@
mDockedStackListeners.finishBroadcast();
}
+ void notifyDockSideChanged(int newDockSide) {
+ final int size = mDockedStackListeners.beginBroadcast();
+ for (int i = 0; i < size; ++i) {
+ final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
+ try {
+ listener.onDockSideChanged(newDockSide);
+ } catch (RemoteException e) {
+ Slog.e(TAG_WM, "Error delivering dock side changed event.", e);
+ }
+ }
+ mDockedStackListeners.finishBroadcast();
+ }
+
void registerDockedStackListener(IDockedStackListener listener) {
mDockedStackListeners.register(listener);
notifyDockedDividerVisibilityChanged(wasVisible());
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index eea0e73..be9fb26 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -294,7 +294,8 @@
final WindowState child = windows.get(winNdx);
final InputChannel inputChannel = child.mInputChannel;
final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
- if (inputChannel == null || inputWindowHandle == null || child.mRemoved) {
+ if (inputChannel == null || inputWindowHandle == null || child.mRemoved
+ || child.isAdjustedForMinimizedDock()) {
// Skip this window because it cannot possibly receive input.
continue;
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 446b74b..7074a83 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -16,6 +16,20 @@
package com.android.server.wm;
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.view.WindowManager.DOCKED_BOTTOM;
+import static android.view.WindowManager.DOCKED_INVALID;
+import static android.view.WindowManager.DOCKED_LEFT;
+import static android.view.WindowManager.DOCKED_RIGHT;
+import static android.view.WindowManager.DOCKED_TOP;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.H.RESIZE_STACK;
+
import android.app.ActivityManager.StackId;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -35,20 +49,6 @@
import java.io.PrintWriter;
import java.util.ArrayList;
-import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static android.view.WindowManager.DOCKED_BOTTOM;
-import static android.view.WindowManager.DOCKED_INVALID;
-import static android.view.WindowManager.DOCKED_LEFT;
-import static android.view.WindowManager.DOCKED_RIGHT;
-import static android.view.WindowManager.DOCKED_TOP;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
-import static com.android.server.wm.WindowManagerService.H.RESIZE_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-
public class TaskStack implements DimLayer.DimLayerUser,
BoundsAnimationController.AnimateBoundsUser {
@@ -379,10 +379,15 @@
return false;
}
+ final int oldDockSide = mStackId == DOCKED_STACK_ID ? getDockSide() : DOCKED_INVALID;
mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
if (mStackId == DOCKED_STACK_ID) {
repositionDockedStackAfterRotation(mTmpRect2);
snapDockedStackAfterRotation(mTmpRect2);
+ final int newDockSide = getDockSide(mTmpRect2);
+ if (oldDockSide != newDockSide) {
+ mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
+ }
}
if (scheduleResize) {
@@ -910,7 +915,7 @@
// Calculate the content bounds excluding the area occupied by IME
getDisplayContent().getContentRect(displayContentRect);
contentBounds.set(displayContentRect);
- int imeTop = Math.max(imeWin.getDisplayFrameLw().top, contentBounds.top);
+ int imeTop = Math.max(imeWin.getFrameLw().top, contentBounds.top);
// if IME window is animating, get its actual vertical shown position (but no smaller than
// the final target vertical position)
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index eae7838..6bc633f 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -670,7 +670,6 @@
if (SHOW_TRANSACTIONS) Slog.i(
TAG, ">>> OPEN TRANSACTION animateLocked");
SurfaceControl.openTransaction();
- SurfaceControl.setAnimationTransaction();
try {
final int numDisplays = mDisplayContentsAnimators.size();
for (int i = 0; i < numDisplays; i++) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 57f38d1..22f0887 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -18,6 +18,7 @@
import android.Manifest;
import android.animation.ValueAnimator;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManagerInternal;
@@ -153,6 +154,8 @@
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.net.Socket;
import java.text.DateFormat;
import java.util.ArrayList;
@@ -332,6 +335,14 @@
private static final String PROPERTY_BUILD_DATE_UTC = "ro.build.date.utc";
+ // Enums for animation scale update types.
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE})
+ private @interface UpdateAnimationScaleMode {};
+ private static final int WINDOW_ANIMATION_SCALE = 0;
+ private static final int TRANSITION_ANIMATION_SCALE = 1;
+ private static final int ANIMATION_DURATION_SCALE = 2;
+
final private KeyguardDisableHandler mKeyguardDisableHandler;
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -613,18 +624,49 @@
private final class SettingsObserver extends ContentObserver {
private final Uri mDisplayInversionEnabledUri =
Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
+ private final Uri mWindowAnimationScaleUri =
+ Settings.Global.getUriFor(Settings.Global.WINDOW_ANIMATION_SCALE);
+ private final Uri mTransitionAnimationScaleUri =
+ Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE);
+ private final Uri mAnimationDurationScaleUri =
+ Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE);
public SettingsObserver() {
super(new Handler());
ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this,
UserHandle.USER_ALL);
+ resolver.registerContentObserver(mWindowAnimationScaleUri, false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(mTransitionAnimationScaleUri, false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(mAnimationDurationScaleUri, false, this,
+ UserHandle.USER_ALL);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
+ if (uri == null) {
+ return;
+ }
+
if (mDisplayInversionEnabledUri.equals(uri)) {
updateCircularDisplayMaskIfNeeded();
+ } else {
+ @UpdateAnimationScaleMode
+ final int mode;
+ if (mWindowAnimationScaleUri.equals(uri)) {
+ mode = WINDOW_ANIMATION_SCALE;
+ } else if (mTransitionAnimationScaleUri.equals(uri)) {
+ mode = TRANSITION_ANIMATION_SCALE;
+ } else if (mAnimationDurationScaleUri.equals(uri)) {
+ mode = ANIMATION_DURATION_SCALE;
+ } else {
+ // Ignoring unrecognized content changes
+ return;
+ }
+ Message m = mH.obtainMessage(H.UPDATE_ANIMATION_SCALE, mode, 0);
+ mH.sendMessage(m);
}
}
}
@@ -2072,6 +2114,11 @@
if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
reportNewConfig = true;
}
+ if (attrs.removeTimeoutMilliseconds > 0) {
+ mH.sendMessageDelayed(
+ mH.obtainMessage(H.WINDOW_REMOVE_TIMEOUT, win),
+ attrs.removeTimeoutMilliseconds);
+ }
}
if (reportNewConfig) {
@@ -3905,16 +3952,6 @@
return;
}
- if (transferStartingWindow(transferFrom, wtoken)) {
- return;
- }
-
- // There is no existing starting window, and the caller doesn't
- // want us to create one, so that's it!
- if (!createIfNeeded) {
- return;
- }
-
// If this is a translucent window, then don't
// show a starting window -- the current effect (a full-screen
// opaque starting window that fades away to the real contents
@@ -3960,6 +3997,16 @@
}
}
+ if (transferStartingWindow(transferFrom, wtoken)) {
+ return;
+ }
+
+ // There is no existing starting window, and the caller doesn't
+ // want us to create one, so that's it!
+ if (!createIfNeeded) {
+ return;
+ }
+
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating StartingData");
wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
labelRes, icon, logo, windowFlags);
@@ -5986,7 +6033,13 @@
"screenshotApplications()")) {
throw new SecurityException("Requires READ_FRAME_BUFFER permission");
}
- return screenshotApplicationsInner(appToken, displayId, width, height, false, frameScale);
+ try {
+ Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotApplications");
+ return screenshotApplicationsInner(appToken, displayId, width, height, false,
+ frameScale);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ }
}
Bitmap screenshotApplicationsInner(IBinder appToken, int displayId, int width, int height,
@@ -7747,6 +7800,8 @@
public static final int NOTIFY_APP_TRANSITION_CANCELLED = 48;
public static final int NOTIFY_APP_TRANSITION_FINISHED = 49;
public static final int NOTIFY_STARTING_WINDOW_DRAWN = 50;
+ public static final int UPDATE_ANIMATION_SCALE = 51;
+ public static final int WINDOW_REMOVE_TIMEOUT = 52;
/**
* Used to denote that an integer field in a message will not be used.
@@ -8030,6 +8085,36 @@
break;
}
+ case UPDATE_ANIMATION_SCALE: {
+ @UpdateAnimationScaleMode
+ final int mode = msg.arg1;
+ switch (mode) {
+ case WINDOW_ANIMATION_SCALE: {
+ mWindowAnimationScaleSetting = Settings.Global.getFloat(
+ mContext.getContentResolver(),
+ Settings.Global.WINDOW_ANIMATION_SCALE,
+ mWindowAnimationScaleSetting);
+ break;
+ }
+ case TRANSITION_ANIMATION_SCALE: {
+ mTransitionAnimationScaleSetting = Settings.Global.getFloat(
+ mContext.getContentResolver(),
+ Settings.Global.TRANSITION_ANIMATION_SCALE,
+ mTransitionAnimationScaleSetting);
+ break;
+ }
+ case ANIMATION_DURATION_SCALE: {
+ mAnimatorDurationScaleSetting = Settings.Global.getFloat(
+ mContext.getContentResolver(),
+ Settings.Global.ANIMATOR_DURATION_SCALE,
+ mAnimatorDurationScaleSetting);
+ dispatchNewAnimatorScaleLocked(null);
+ break;
+ }
+ }
+ break;
+ }
+
case FORCE_GC: {
synchronized (mWindowMap) {
// Since we're holding both mWindowMap and mAnimator we don't need to
@@ -8329,6 +8414,18 @@
mAmInternal.notifyStartingWindowDrawn();
}
break;
+ case WINDOW_REMOVE_TIMEOUT: {
+ final WindowState window = (WindowState) msg.obj;
+ synchronized(mWindowMap) {
+ // It's counterintuitive that we check that "mWindowRemovalAllowed"
+ // is false. But in fact if it's true, it means a remove has already
+ // been requested and we better just not do anything.
+ if (!window.mRemoved && !window.mWindowRemovalAllowed) {
+ removeWindowLocked(window);
+ }
+ }
+ }
+ break;
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG_WM, "handleMessage: exit");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 7f40079..8371cfe 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -642,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);
}
@@ -687,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);
@@ -733,10 +733,12 @@
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);
+ mTmpRect.set(0, 0, mDisplayContent.getDisplayInfo().logicalWidth,
+ mDisplayContent.getDisplayInfo().logicalHeight);
+ subtractInsets(mDisplayFrame, layoutContainingFrame, df, mTmpRect);
if (!layoutInParentFrame()) {
- subtractInsets(mContainingFrame, layoutContainingFrame, pf);
- subtractInsets(mInsetFrame, layoutContainingFrame, pf);
+ subtractInsets(mContainingFrame, layoutContainingFrame, pf, mTmpRect);
+ subtractInsets(mInsetFrame, layoutContainingFrame, pf, mTmpRect);
}
layoutDisplayFrame = df;
layoutDisplayFrame.intersect(layoutContainingFrame);
@@ -772,10 +774,6 @@
applyGravityAndUpdateFrame(layoutContainingFrame, layoutDisplayFrame);
- // Offset the actual frame by the amount layout frame is off.
- mFrame.offset(-layoutXDiff, -layoutYDiff);
- mCompatFrame.offset(-layoutXDiff, -layoutYDiff);
-
// Calculate the outsets before the content frame gets shrinked to the window frame.
if (hasOutsets) {
mOutsets.set(Math.max(mContentFrame.left - mOutsetFrame.left, 0),
@@ -814,20 +812,20 @@
mMovedByResize = true;
}
} else {
- mContentFrame.set(Math.max(mContentFrame.left, layoutContainingFrame.left),
- Math.max(mContentFrame.top, layoutContainingFrame.top),
- Math.min(mContentFrame.right, layoutContainingFrame.right),
- Math.min(mContentFrame.bottom, layoutContainingFrame.bottom));
+ mContentFrame.set(Math.max(mContentFrame.left, mFrame.left),
+ Math.max(mContentFrame.top, mFrame.top),
+ Math.min(mContentFrame.right, mFrame.right),
+ Math.min(mContentFrame.bottom, mFrame.bottom));
- mVisibleFrame.set(Math.max(mVisibleFrame.left, layoutContainingFrame.left),
- Math.max(mVisibleFrame.top, layoutContainingFrame.top),
- Math.min(mVisibleFrame.right, layoutContainingFrame.right),
- Math.min(mVisibleFrame.bottom, layoutContainingFrame.bottom));
+ mVisibleFrame.set(Math.max(mVisibleFrame.left, mFrame.left),
+ Math.max(mVisibleFrame.top, mFrame.top),
+ Math.min(mVisibleFrame.right, mFrame.right),
+ Math.min(mVisibleFrame.bottom, mFrame.bottom));
- mStableFrame.set(Math.max(mStableFrame.left, layoutContainingFrame.left),
- Math.max(mStableFrame.top, layoutContainingFrame.top),
- Math.min(mStableFrame.right, layoutContainingFrame.right),
- Math.min(mStableFrame.bottom, layoutContainingFrame.bottom));
+ mStableFrame.set(Math.max(mStableFrame.left, mFrame.left),
+ Math.max(mStableFrame.top, mFrame.top),
+ Math.min(mStableFrame.right, mFrame.right),
+ Math.min(mStableFrame.bottom, mFrame.bottom));
}
if (fullscreenTask && !windowsAreFloating) {
@@ -857,28 +855,31 @@
// non-fullscreen mode.
boolean overrideRightInset = !fullscreenTask && mFrame.right > mTmpRect.right;
boolean overrideBottomInset = !fullscreenTask && mFrame.bottom > mTmpRect.bottom;
- mContentInsets.set(mContentFrame.left - layoutContainingFrame.left,
- mContentFrame.top - layoutContainingFrame.top,
+ mContentInsets.set(mContentFrame.left - mFrame.left,
+ mContentFrame.top - mFrame.top,
overrideRightInset ? mTmpRect.right - mContentFrame.right
- : layoutContainingFrame.right - mContentFrame.right,
+ : mFrame.right - mContentFrame.right,
overrideBottomInset ? mTmpRect.bottom - mContentFrame.bottom
- : layoutContainingFrame.bottom - mContentFrame.bottom);
+ : mFrame.bottom - mContentFrame.bottom);
- mVisibleInsets.set(mVisibleFrame.left - layoutContainingFrame.left,
- mVisibleFrame.top - layoutContainingFrame.top,
+ mVisibleInsets.set(mVisibleFrame.left - mFrame.left,
+ mVisibleFrame.top - mFrame.top,
overrideRightInset ? mTmpRect.right - mVisibleFrame.right
- : layoutContainingFrame.right - mVisibleFrame.right,
+ : mFrame.right - mVisibleFrame.right,
overrideBottomInset ? mTmpRect.bottom - mVisibleFrame.bottom
- : layoutContainingFrame.bottom - mVisibleFrame.bottom);
+ : mFrame.bottom - mVisibleFrame.bottom);
- mStableInsets.set(Math.max(mStableFrame.left - layoutContainingFrame.left, 0),
- Math.max(mStableFrame.top - layoutContainingFrame.top, 0),
+ mStableInsets.set(Math.max(mStableFrame.left - mFrame.left, 0),
+ Math.max(mStableFrame.top - mFrame.top, 0),
overrideRightInset ? Math.max(mTmpRect.right - mStableFrame.right, 0)
- : Math.max(layoutContainingFrame.right - mStableFrame.right, 0),
+ : Math.max(mFrame.right - mStableFrame.right, 0),
overrideBottomInset ? Math.max(mTmpRect.bottom - mStableFrame.bottom, 0)
- : Math.max(layoutContainingFrame.bottom - mStableFrame.bottom, 0));
+ : Math.max(mFrame.bottom - mStableFrame.bottom, 0));
}
+ // Offset the actual frame by the amount layout frame is off.
+ mFrame.offset(-layoutXDiff, -layoutYDiff);
+ mCompatFrame.offset(-layoutXDiff, -layoutYDiff);
mContentFrame.offset(-layoutXDiff, -layoutYDiff);
mVisibleFrame.offset(-layoutXDiff, -layoutYDiff);
mStableFrame.offset(-layoutXDiff, -layoutYDiff);
@@ -1388,6 +1389,11 @@
return configChanged;
}
+ boolean isAdjustedForMinimizedDock() {
+ return mAppToken != null && mAppToken.mTask != null
+ && mAppToken.mTask.mStack.isAdjustedForMinimizedDock();
+ }
+
void removeLocked() {
disposeInputChannel();
@@ -1774,7 +1780,8 @@
return isVisibleOrAdding()
&& (mViewVisibility == View.VISIBLE)
&& ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
- && (mAppToken == null || mAppToken.windowsAreFocusable());
+ && (mAppToken == null || mAppToken.windowsAreFocusable())
+ && !isAdjustedForMinimizedDock();
}
@Override
@@ -2403,8 +2410,8 @@
pw.print(prefix); pw.print("mToken="); pw.println(mToken);
pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
if (mAppToken != null) {
- pw.print(prefix); pw.print("mAppToken="); pw.print(mAppToken);
- pw.print(" isAnimatingWithSavedSurface()=");
+ pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
+ pw.print(prefix); pw.print(" isAnimatingWithSavedSurface()=");
pw.print(isAnimatingWithSavedSurface());
pw.print(" mAppDied=");pw.println(mAppDied);
}
@@ -2489,6 +2496,7 @@
pw.print(" content="); mContentInsets.printShortString(pw);
pw.print(" visible="); mVisibleInsets.printShortString(pw);
pw.print(" stable="); mStableInsets.printShortString(pw);
+ pw.print(" surface="); mAttrs.surfaceInsets.printShortString(pw);
pw.print(" outsets="); mOutsets.printShortString(pw);
pw.println();
pw.print(prefix); pw.print("Lst insets: overscan=");
@@ -2590,7 +2598,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 9c25f63..0245513 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityManager.StackId;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
@@ -1032,7 +1033,7 @@
// relative to their containing frame. We need to offset the difference
// between the containing frame as used to calculate the crop and our
// bounds to compensate for this.
- if (mWin.isChildWindow() && mWin.layoutInParentFrame()) {
+ if (mWin.layoutInParentFrame()) {
mClipRect.offset( (mWin.mContainingFrame.left - mWin.mFrame.left),
mWin.mContainingFrame.top - mWin.mFrame.top );
}
@@ -1164,8 +1165,8 @@
final float scale = w.mInvGlobalScale;
mSystemDecorRect.left = (int) (mSystemDecorRect.left * scale - 0.5f);
mSystemDecorRect.top = (int) (mSystemDecorRect.top * scale - 0.5f);
- mSystemDecorRect.right = (int) ((mSystemDecorRect.right+1) * scale - 0.5f);
- mSystemDecorRect.bottom = (int) ((mSystemDecorRect.bottom+1) * scale - 0.5f);
+ mSystemDecorRect.right = (int) ((mSystemDecorRect.right + 1) * scale - 0.5f);
+ mSystemDecorRect.bottom = (int) ((mSystemDecorRect.bottom + 1) * scale - 0.5f);
}
}
@@ -1178,8 +1179,8 @@
return;
}
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Updating crop for window: " + w + ", " + "mLastCrop=" +
- mLastClipRect);
+ if (DEBUG_WINDOW_CROP) Slog.d(TAG,
+ "Updating crop win=" + w + " mLastCrop=" + mLastClipRect);
// Need to recompute a new system decor rect each time.
if (!w.isDefaultDisplay()) {
@@ -1204,8 +1205,8 @@
} else {
// Crop to the system decor specified by policy.
calculateSystemDecorRect();
- if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop for " + w + ", mDecorFrame="
- + w.mDecorFrame + ", mSystemDecorRect=" + mSystemDecorRect);
+ if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame="
+ + w.mDecorFrame + " mSystemDecorRect=" + mSystemDecorRect);
}
final boolean fullscreen = w.isFrameFullscreen(displayInfo);
@@ -1215,8 +1216,8 @@
// We use the clip rect as provided by the tranformation for non-fullscreen windows to
// avoid premature clipping with the system decor rect.
clipRect.set((mHasClipRect && !fullscreen) ? mClipRect : mSystemDecorRect);
- if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Initial clip rect: " + clipRect + ", mHasClipRect="
- + mHasClipRect + ", fullscreen=" + fullscreen);
+ if (DEBUG_WINDOW_CROP) Slog.d(TAG, "win=" + w + " Initial clip rect: " + clipRect
+ + " mHasClipRect=" + mHasClipRect + " fullscreen=" + fullscreen);
if (isFreeformResizing && !w.isChildWindow()) {
// For freeform resizing non child windows, we are using the big surface positioned
@@ -1243,7 +1244,8 @@
finalClipRect.setEmpty();
adjustCropToStackBounds(w, clipRect, finalClipRect, isFreeformResizing);
- if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Clip rect after stack adjustment=" + clipRect);
+ if (DEBUG_WINDOW_CROP) Slog.d(TAG,
+ "win=" + w + " Clip rect after stack adjustment=" + clipRect);
w.transformFromScreenToSurfaceSpace(clipRect);
@@ -1254,6 +1256,8 @@
}
void updateSurfaceWindowCrop(Rect clipRect, Rect finalClipRect, boolean recoveringMemory) {
+ if (DEBUG_WINDOW_CROP) Slog.d(TAG, "updateSurfaceWindowCrop: win=" + mWin
+ + " clipRect=" + clipRect + " finalClipRect=" + finalClipRect);
if (!clipRect.equals(mLastClipRect)) {
mLastClipRect.set(clipRect);
mSurfaceController.setCropInTransaction(clipRect, recoveringMemory);
@@ -1288,19 +1292,20 @@
}
final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
- if (w == winShowWhenLocked) {
+ if (w == winShowWhenLocked && mPolicy.isKeyguardShowingOrOccluded()) {
return;
}
final TaskStack stack = task.mStack;
stack.getDimBounds(mTmpStackBounds);
+ final Rect surfaceInsets = w.getAttrs().surfaceInsets;
// When we resize we use the big surface approach, which means we can't trust the
// window frame bounds anymore. Instead, the window will be placed at 0, 0, but to avoid
// hardcoding it, we use surface coordinates.
final int frameX = isFreeformResizing ? (int) mSurfaceController.getX() :
- w.mFrame.left + mWin.mXOffset - w.getAttrs().surfaceInsets.left;
+ w.mFrame.left + mWin.mXOffset - surfaceInsets.left;
final int frameY = isFreeformResizing ? (int) mSurfaceController.getY() :
- w.mFrame.top + mWin.mYOffset - w.getAttrs().surfaceInsets.top;
+ w.mFrame.top + mWin.mYOffset - surfaceInsets.top;
// If we are animating, we either apply the clip before applying all the animation
// transformation or after all the transformation.
@@ -1311,6 +1316,15 @@
if (useFinalClipRect) {
finalClipRect.set(mTmpStackBounds);
} else {
+ if (StackId.hasWindowShadow(stack.mStackId)
+ && !StackId.isTaskResizeAllowed(stack.mStackId)) {
+ // The windows in this stack display drop shadows and the fill the entire stack
+ // area. Adjust the stack bounds we will use to cropping take into account the
+ // offsets we use to display the drop shadow so it doesn't get cropped.
+ mTmpStackBounds.inset(-surfaceInsets.left, -surfaceInsets.top,
+ -surfaceInsets.right, -surfaceInsets.bottom);
+ }
+
clipRect.left = Math.max(0,
Math.max(mTmpStackBounds.left, frameX + clipRect.left) - frameX);
clipRect.top = Math.max(0,
@@ -1356,21 +1370,19 @@
// past where the system would have cropped us
mTmpClipRect.set(0, 0, mTmpSize.width(), mTmpSize.height());
mTmpFinalClipRect.setEmpty();
- updateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect, recoveringMemory);
} else {
mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top,
recoveringMemory);
- updateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect, recoveringMemory);
}
+ updateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect, recoveringMemory);
mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * extraHScale,
mDtDx * w.mVScale * extraVScale,
mDsDy * w.mHScale * extraHScale,
mDtDy * w.mVScale * extraVScale, recoveringMemory);
mSurfaceResized = mSurfaceController.setSizeInTransaction(
- mTmpSize.width(), mTmpSize.height(),
- recoveringMemory);
+ mTmpSize.width(), mTmpSize.height(), recoveringMemory);
if (mSurfaceResized) {
mReportSurfaceResized = true;
@@ -1775,7 +1787,7 @@
pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
- pw.print(" mAnimation="); pw.println(mAnimation);
+ pw.print(" mAnimation="); pw.print(mAnimation);
pw.print(" mStackClip="); pw.println(mStackClip);
}
if (mHasTransformation || mHasLocalTransformation) {
@@ -1793,9 +1805,9 @@
pw.print(prefix); pw.print(" mLastHidden="); pw.println(mLastHidden);
pw.print(prefix); pw.print("mSystemDecorRect="); mSystemDecorRect.printShortString(pw);
pw.print(" last="); mLastSystemDecorRect.printShortString(pw);
- if (mHasClipRect) {
- pw.print(" mLastClipRect="); mLastClipRect.printShortString(pw);
- }
+ pw.print(" mHasClipRect="); pw.print(mHasClipRect);
+ pw.print(" mLastClipRect="); mLastClipRect.printShortString(pw);
+
if (!mLastFinalClipRect.isEmpty()) {
pw.print(" mLastFinalClipRect="); mLastFinalClipRect.printShortString(pw);
}
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 78b0844..058b631 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -562,7 +562,7 @@
method_reportNavigationMessages = env->GetMethodID(
clazz,
"reportNavigationMessage",
- "(Landroid/location/GnssNavigationMessageEvent;)V");
+ "(Landroid/location/GnssNavigationMessage;)V");
err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err == 0) {
@@ -1165,7 +1165,7 @@
static jobject translate_gnss_clock(JNIEnv* env, GnssClock* clock) {
JavaObject object(env, "android/location/GnssClock");
- GpsClockFlags flags = clock->flags;
+ GnssClockFlags flags = clock->flags;
SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
LeapSecond,
@@ -1237,9 +1237,10 @@
static jobject translate_gnss_measurement(JNIEnv* env,
GnssMeasurement* measurement) {
JavaObject object(env, "android/location/GnssMeasurement");
- GpsMeasurementFlags flags = measurement->flags;
- SET(Svid, measurement->svid);
+ GnssMeasurementFlags flags = measurement->flags;
+
+ SET(Svid, static_cast<int32_t>(measurement->svid));
SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
SET(TimeOffsetNanos, measurement->time_offset_ns);
SET(State, static_cast<int32_t>(measurement->state));
@@ -1379,8 +1380,8 @@
ALOGE("Invalid data provided to gps_measurement_callback");
return;
}
- if (data->size != sizeof(GpsData)) {
- ALOGE("Invalid GpsData size found in gps_measurement_callback, "
+ if (data->size != sizeof(GnssData)) {
+ ALOGE("Invalid GnssData size found in gnss_measurement_callback, "
"size=%zd",
data->size);
return;
@@ -1486,26 +1487,6 @@
return object.get();
}
-static void set_navigation_message(jobject navigationMessage) {
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- jclass navigationMessageEventClass =
- env->FindClass("android/location/GnssNavigationMessageEvent");
- jmethodID navigationMessageEventCtor = env->GetMethodID(
- navigationMessageEventClass,
- "<init>",
- "(Landroid/location/GnssNavigationMessage;)V");
- jobject navigationMessageEvent = env->NewObject(
- navigationMessageEventClass,
- navigationMessageEventCtor,
- navigationMessage);
- env->CallVoidMethod(mCallbacksObj,
- method_reportNavigationMessages,
- navigationMessageEvent);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
- env->DeleteLocalRef(navigationMessageEventClass);
- env->DeleteLocalRef(navigationMessageEvent);
-}
-
static void navigation_message_callback(GpsNavigationMessage* message) {
if (message == NULL) {
ALOGE("Invalid Navigation Message provided to callback");
@@ -1517,7 +1498,9 @@
}
JNIEnv* env = AndroidRuntime::getJNIEnv();
jobject navigationMessage = translate_gps_navigation_message(env, message);
- set_navigation_message(navigationMessage);
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportNavigationMessages,
+ navigationMessage);
env->DeleteLocalRef(navigationMessage);
}
@@ -1532,7 +1515,9 @@
}
JNIEnv* env = AndroidRuntime::getJNIEnv();
jobject navigationMessage = translate_gnss_navigation_message(env, message);
- set_navigation_message(navigationMessage);
+ env->CallVoidMethod(mCallbacksObj,
+ method_reportNavigationMessages,
+ navigationMessage);
env->DeleteLocalRef(navigationMessage);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 72eebb5..d3d05f3 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;
@@ -215,7 +211,7 @@
private static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION
= "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION";
- private static final int MONITORING_CERT_NOTIFICATION_ID = R.string.ssl_ca_cert_warning;
+ private static final int MONITORING_CERT_NOTIFICATION_ID = R.plurals.ssl_ca_cert_warning;
private static final int PROFILE_WIPED_NOTIFICATION_ID = 1001;
private static final String ATTR_PERMISSION_PROVIDER = "permission-provider";
@@ -659,8 +655,8 @@
Bundle userRestrictions;
// Support text provided by the admin to display to the user.
- String shortSupportMessage = null;
- String longSupportMessage = null;
+ CharSequence shortSupportMessage = null;
+ CharSequence longSupportMessage = null;
// Background color of confirm credentials screen. Default: teal.
static final int DEF_ORGANIZATION_COLOR = Color.parseColor("#00796B");
@@ -874,12 +870,12 @@
}
if (!TextUtils.isEmpty(shortSupportMessage)) {
out.startTag(null, TAG_SHORT_SUPPORT_MESSAGE);
- out.text(shortSupportMessage);
+ out.text(shortSupportMessage.toString());
out.endTag(null, TAG_SHORT_SUPPORT_MESSAGE);
}
if (!TextUtils.isEmpty(longSupportMessage)) {
out.startTag(null, TAG_LONG_SUPPORT_MESSAGE);
- out.text(longSupportMessage);
+ out.text(longSupportMessage.toString());
out.endTag(null, TAG_LONG_SUPPORT_MESSAGE);
}
if (parentAdmin != null) {
@@ -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);
}
}
@@ -2701,23 +2696,25 @@
// Build and show a warning notification
int smallIconId;
String contentText;
- // TODO Why does it use the DO name? The cert APIs are all for PO. b/25772443
- final String ownerName = getDeviceOwnerName();
- if (isManagedProfile(userHandle.getIdentifier())) {
- contentText = mContext.getString(R.string.ssl_ca_cert_noti_by_administrator);
+ if (getProfileOwner(userHandle.getIdentifier()) != null) {
+ contentText = mContext.getString(R.string.ssl_ca_cert_noti_managed,
+ getProfileOwnerName(userHandle.getIdentifier()));
smallIconId = R.drawable.stat_sys_certificate_info;
- } else if (ownerName != null) {
- contentText = mContext.getString(R.string.ssl_ca_cert_noti_managed, ownerName);
+ } else if (getDeviceOwnerUserId() == userHandle.getIdentifier()) {
+ contentText = mContext.getString(R.string.ssl_ca_cert_noti_managed,
+ getDeviceOwnerName());
smallIconId = R.drawable.stat_sys_certificate_info;
} else {
contentText = mContext.getString(R.string.ssl_ca_cert_noti_by_unknown);
smallIconId = android.R.drawable.stat_sys_warning;
}
+ final int numberOfCertificates = pendingCertificates.size();
Intent dialogIntent = new Intent(Settings.ACTION_MONITORING_CERT_INFO);
dialogIntent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
dialogIntent.setPackage("com.android.settings");
+ dialogIntent.putExtra(Settings.EXTRA_NUMBER_OF_CERTIFICATES, numberOfCertificates);
PendingIntent notifyIntent = PendingIntent.getActivityAsUser(mContext, 0,
dialogIntent, PendingIntent.FLAG_UPDATE_CURRENT, null, userHandle);
@@ -2731,7 +2728,8 @@
}
final Notification noti = new Notification.Builder(userContext)
.setSmallIcon(smallIconId)
- .setContentTitle(mContext.getString(R.string.ssl_ca_cert_warning))
+ .setContentTitle(mContext.getResources().getQuantityText(
+ R.plurals.ssl_ca_cert_warning, numberOfCertificates))
.setContentText(contentText)
.setContentIntent(notifyIntent)
.setPriority(Notification.PRIORITY_HIGH)
@@ -3968,9 +3966,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);
@@ -6708,19 +6706,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);
}
@@ -6888,12 +6885,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);
@@ -8508,7 +8504,7 @@
}
@Override
- public void setShortSupportMessage(@NonNull ComponentName who, String message) {
+ public void setShortSupportMessage(@NonNull ComponentName who, CharSequence message) {
if (!mHasFeature) {
return;
}
@@ -8525,7 +8521,7 @@
}
@Override
- public String getShortSupportMessage(@NonNull ComponentName who) {
+ public CharSequence getShortSupportMessage(@NonNull ComponentName who) {
if (!mHasFeature) {
return null;
}
@@ -8538,7 +8534,7 @@
}
@Override
- public void setLongSupportMessage(@NonNull ComponentName who, String message) {
+ public void setLongSupportMessage(@NonNull ComponentName who, CharSequence message) {
if (!mHasFeature) {
return;
}
@@ -8555,7 +8551,7 @@
}
@Override
- public String getLongSupportMessage(@NonNull ComponentName who) {
+ public CharSequence getLongSupportMessage(@NonNull ComponentName who) {
if (!mHasFeature) {
return null;
}
@@ -8568,7 +8564,7 @@
}
@Override
- public String getShortSupportMessageForUser(@NonNull ComponentName who, int userHandle) {
+ public CharSequence getShortSupportMessageForUser(@NonNull ComponentName who, int userHandle) {
if (!mHasFeature) {
return null;
}
@@ -8586,7 +8582,7 @@
}
@Override
- public String getLongSupportMessageForUser(@NonNull ComponentName who, int userHandle) {
+ public CharSequence getLongSupportMessageForUser(@NonNull ComponentName who, int userHandle) {
if (!mHasFeature) {
return null;
}
@@ -8664,7 +8660,7 @@
}
@Override
- public void setOrganizationName(@NonNull ComponentName who, String text) {
+ public void setOrganizationName(@NonNull ComponentName who, CharSequence text) {
if (!mHasFeature) {
return;
}
@@ -8675,14 +8671,15 @@
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
if (!TextUtils.equals(admin.organizationName, text)) {
- admin.organizationName = TextUtils.nullIfEmpty(text);
+ admin.organizationName = (text == null || text.length() == 0)
+ ? null : text.toString();
saveSettingsLocked(userHandle);
}
}
}
@Override
- public String getOrganizationName(@NonNull ComponentName who) {
+ public CharSequence getOrganizationName(@NonNull ComponentName who) {
if (!mHasFeature) {
return null;
}
@@ -8696,7 +8693,7 @@
}
@Override
- public String getOrganizationNameForUser(int userHandle) {
+ public CharSequence getOrganizationNameForUser(int userHandle) {
if (!mHasFeature) {
return null;
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e7ae2b0..8c2f559 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -18,7 +18,6 @@
import android.app.ActivityManagerNative;
import android.app.ActivityThread;
-import android.app.IAlarmManager;
import android.app.INotificationManager;
import android.app.usage.UsageStatsManagerInternal;
import android.content.ComponentName;
@@ -55,13 +54,11 @@
import com.android.internal.os.ZygoteInit;
import com.android.internal.widget.ILockSettings;
import com.android.server.accessibility.AccessibilityManagerService;
-import com.android.server.accounts.AccountManagerService;
import com.android.server.am.ActivityManagerService;
import com.android.server.audio.AudioService;
import com.android.server.camera.CameraService;
import com.android.server.clipboard.ClipboardService;
import com.android.server.connectivity.MetricsLoggerService;
-import com.android.server.content.ContentService;
import com.android.server.devicepolicy.DevicePolicyManagerService;
import com.android.server.display.DisplayManagerService;
import com.android.server.dreams.DreamManagerService;
@@ -97,7 +94,6 @@
import com.android.server.twilight.TwilightService;
import com.android.server.usage.UsageStatsService;
import com.android.server.vr.VrManagerService;
-import com.android.server.wallpaper.WallpaperManagerService;
import com.android.server.webkit.WebViewUpdateService;
import com.android.server.wm.WindowManagerService;
@@ -157,8 +153,12 @@
"com.google.android.clockwork.ThermalObserver";
private static final String WEAR_BLUETOOTH_SERVICE_CLASS =
"com.google.android.clockwork.bluetooth.WearBluetoothService";
+ private static final String ACCOUNT_SERVICE_CLASS =
+ "com.android.server.accounts.AccountManagerService$Lifecycle";
private static final String CONTENT_SERVICE_CLASS =
"com.android.server.content.ContentService$Lifecycle";
+ private static final String WALLPAPER_SERVICE_CLASS =
+ "com.android.server.wallpaper.WallpaperManagerService$Lifecycle";
private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
@@ -187,6 +187,7 @@
private PackageManagerService mPackageManagerService;
private PackageManager mPackageManager;
private ContentResolver mContentResolver;
+ private EntropyMixer mEntropyMixer;
private boolean mOnlyCore;
private boolean mFirstBoot;
@@ -497,10 +498,7 @@
*/
private void startOtherServices() {
final Context context = mSystemContext;
- AccountManagerService accountManager = null;
- ContentService contentService = null;
VibratorService vibrator = null;
- IAlarmManager alarm = null;
IMountService mountService = null;
NetworkManagementService networkManagement = null;
NetworkStatsService networkStats = null;
@@ -516,8 +514,6 @@
TelephonyRegistry telephonyRegistry = null;
ConsumerIrService consumerIr = null;
MmsServiceBroker mmsService = null;
- EntropyMixer entropyMixer = null;
- VrManagerService vrManagerService = null;
HardwarePropertiesManagerService hardwarePropertiesService = null;
boolean disableStorage = SystemProperties.getBoolean("config.disable_storage", false);
@@ -556,7 +552,7 @@
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
traceBeginAndSlog("StartEntropyMixer");
- entropyMixer = new EntropyMixer(context);
+ mEntropyMixer = new EntropyMixer(context);
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
mContentResolver = context.getContentResolver();
@@ -566,13 +562,7 @@
// The AccountManager must come before the ContentService
traceBeginAndSlog("StartAccountManagerService");
- try {
- // TODO: seems like this should be disable-able, but req'd by ContentService
- accountManager = new AccountManagerService(context);
- ServiceManager.addService(Context.ACCOUNT_SERVICE, accountManager);
- } catch (Throwable e) {
- Slog.e(TAG, "Failure starting Account Manager", e);
- }
+ mSystemServiceManager.startService(ACCOUNT_SERVICE_CLASS);
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
traceBeginAndSlog("StartContentService");
@@ -593,9 +583,9 @@
ServiceManager.addService(Context.CONSUMER_IR_SERVICE, consumerIr);
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ traceBeginAndSlog("StartAlarmManagerService");
mSystemServiceManager.startService(AlarmManagerService.class);
- alarm = IAlarmManager.Stub.asInterface(
- ServiceManager.getService(Context.ALARM_SERVICE));
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
traceBeginAndSlog("InitWatchdog");
final Watchdog watchdog = Watchdog.getInstance();
@@ -652,7 +642,6 @@
StatusBarManagerService statusBar = null;
INotificationManager notification = null;
- WallpaperManagerService wallpaper = null;
LocationManagerService location = null;
CountryDetectorService countryDetector = null;
ILockSettings lockSettings = null;
@@ -823,7 +812,7 @@
mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS);
mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
mSystemServiceManager.startService(
- "com.android.server.wifi.WifiScanningService");
+ "com.android.server.wifi.scanner.WifiScanningService");
if (!disableRtt) {
mSystemServiceManager.startService("com.android.server.wifi.RttService");
@@ -886,24 +875,6 @@
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeAccountManagerServiceReady");
- try {
- if (accountManager != null)
- accountManager.systemReady();
- } catch (Throwable e) {
- reportWtf("making Account Manager Service ready", e);
- }
- Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
-
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeContentServiceReady");
- try {
- if (contentService != null)
- contentService.systemReady();
- } catch (Throwable e) {
- reportWtf("making Content Service ready", e);
- }
- Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
-
mSystemServiceManager.startService(NotificationManagerService.class);
notification = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
@@ -946,12 +917,7 @@
if (!disableNonCoreServices && context.getResources().getBoolean(
R.bool.config_enableWallpaperService)) {
traceBeginAndSlog("StartWallpaperManagerService");
- try {
- wallpaper = new WallpaperManagerService(context);
- ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);
- } catch (Throwable e) {
- reportWtf("starting Wallpaper Service", e);
- }
+ mSystemServiceManager.startService(WALLPAPER_SERVICE_CLASS);
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
@@ -1278,12 +1244,10 @@
final NetworkPolicyManagerService networkPolicyF = networkPolicy;
final ConnectivityService connectivityF = connectivity;
final NetworkScoreService networkScoreF = networkScore;
- final WallpaperManagerService wallpaperF = wallpaper;
final LocationManagerService locationF = location;
final CountryDetectorService countryDetectorF = countryDetector;
final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater;
final CommonTimeManagementService commonTimeMgmtServiceF = commonTimeMgmtService;
- final StatusBarManagerService statusBarF = statusBar;
final AssetAtlasService atlasF = atlas;
final InputManagerService inputManagerF = inputManager;
final TelephonyRegistry telephonyRegistryF = telephonyRegistry;
@@ -1371,11 +1335,6 @@
SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
try {
- if (wallpaperF != null) wallpaperF.systemRunning();
- } catch (Throwable e) {
- reportWtf("Notifying WallpaperService running", e);
- }
- try {
if (locationF != null) locationF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying Location Service running", e);
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/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index 406dd56..804fa03 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -336,17 +336,17 @@
class ReceiveThread extends Thread {
private final byte[] mPacket = new byte[DhcpPacket.MAX_LENGTH];
- private boolean stopped = false;
+ private volatile boolean mStopped = false;
public void halt() {
- stopped = true;
+ mStopped = true;
closeSockets(); // Interrupts the read() call the thread is blocked in.
}
@Override
public void run() {
if (DBG) Log.d(TAG, "Receive thread started");
- while (!stopped) {
+ while (!mStopped) {
int length = 0; // Or compiler can't tell it's initialized if a parse error occurs.
try {
length = Os.read(mPacketSock, mPacket, 0, mPacket.length);
@@ -355,7 +355,7 @@
if (DBG) Log.d(TAG, "Received packet: " + packet);
sendMessage(CMD_RECEIVED_PACKET, packet);
} catch (IOException|ErrnoException e) {
- if (!stopped) {
+ if (!mStopped) {
Log.e(TAG, "Read error", e);
}
DhcpClientEvent.logEvent(IpConnectivityEvent.IPCE_DHCP_RECV_ERROR,
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index a881408..b184fe5 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -3,6 +3,7 @@
import android.net.DhcpResults;
import android.net.LinkAddress;
import android.net.NetworkUtils;
+import android.net.metrics.DhcpErrorEvent;
import android.os.Build;
import android.os.SystemProperties;
import android.system.OsConstants;
@@ -765,6 +766,7 @@
// check to see if we need to parse L2, IP, and UDP encaps
if (pktType == ENCAP_L2) {
if (packet.remaining() < MIN_PACKET_LENGTH_L2) {
+ DhcpErrorEvent.logEvent(DhcpErrorEvent.L2_TOO_SHORT);
throw new ParseException("L2 packet too short, %d < %d",
packet.remaining(), MIN_PACKET_LENGTH_L2);
}
@@ -777,13 +779,16 @@
short l2type = packet.getShort();
- if (l2type != OsConstants.ETH_P_IP)
+ if (l2type != OsConstants.ETH_P_IP) {
+ DhcpErrorEvent.logEvent(DhcpErrorEvent.L2_WRONG_ETH_TYPE);
throw new ParseException("Unexpected L2 type 0x%04x, expected 0x%04x",
l2type, OsConstants.ETH_P_IP);
+ }
}
if (pktType <= ENCAP_L3) {
if (packet.remaining() < MIN_PACKET_LENGTH_L3) {
+ DhcpErrorEvent.logEvent(DhcpErrorEvent.L3_TOO_SHORT);
throw new ParseException("L3 packet too short, %d < %d",
packet.remaining(), MIN_PACKET_LENGTH_L3);
}
@@ -791,6 +796,7 @@
byte ipTypeAndLength = packet.get();
int ipVersion = (ipTypeAndLength & 0xf0) >> 4;
if (ipVersion != 4) {
+ DhcpErrorEvent.logEvent(DhcpErrorEvent.L3_NOT_IPV4);
throw new ParseException("Invalid IP version %d", ipVersion);
}
@@ -808,6 +814,7 @@
ipDst = readIpAddress(packet);
if (ipProto != IP_TYPE_UDP) {
+ DhcpErrorEvent.logEvent(DhcpErrorEvent.L4_NOT_UDP);
throw new ParseException("Protocol not UDP: %d", ipProto);
}
@@ -834,12 +841,14 @@
// socket to drop packets that don't have the right source ports. However, it's
// possible that a packet arrives between when the socket is bound and when the
// filter is set. http://b/26696823 .
+ DhcpErrorEvent.logEvent(DhcpErrorEvent.L4_WRONG_PORT);
throw new ParseException("Unexpected UDP ports %d->%d", udpSrcPort, udpDstPort);
}
}
// We need to check the length even for ENCAP_L3 because the IPv4 header is variable-length.
if (pktType > ENCAP_BOOTP || packet.remaining() < MIN_PACKET_LENGTH_BOOTP) {
+ DhcpErrorEvent.logEvent(DhcpErrorEvent.BOOTP_TOO_SHORT);
throw new ParseException("Invalid type or BOOTP packet too short, %d < %d",
packet.remaining(), MIN_PACKET_LENGTH_BOOTP);
}
@@ -864,6 +873,7 @@
packet.get(ipv4addr);
relayIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr);
} catch (UnknownHostException ex) {
+ DhcpErrorEvent.logEvent(DhcpErrorEvent.L3_INVALID_IP);
throw new ParseException("Invalid IPv4 address: %s", Arrays.toString(ipv4addr));
}
@@ -888,6 +898,7 @@
int dhcpMagicCookie = packet.getInt();
if (dhcpMagicCookie != DHCP_MAGIC_COOKIE) {
+ DhcpErrorEvent.logEvent(DhcpErrorEvent.DHCP_BAD_MAGIC_COOKIE);
throw new ParseException("Bad magic cookie 0x%08x, should be 0x%08x", dhcpMagicCookie,
DHCP_MAGIC_COOKIE);
}
@@ -896,9 +907,8 @@
boolean notFinishedOptions = true;
while ((packet.position() < packet.limit()) && notFinishedOptions) {
+ final byte optionType = packet.get(); // cannot underflow because position < limit
try {
- byte optionType = packet.get();
-
if (optionType == DHCP_OPTION_END) {
notFinishedOptions = false;
} else if (optionType == DHCP_OPTION_PAD) {
@@ -999,11 +1009,14 @@
}
if (expectedLen != optionLen) {
+ DhcpErrorEvent.logEvent(
+ DhcpErrorEvent.DHCP_INVALID_OPTION_LENGTH, optionType);
throw new ParseException("Invalid length %d for option %d, expected %d",
optionLen, optionType, expectedLen);
}
}
} catch (BufferUnderflowException e) {
+ DhcpErrorEvent.logEvent(DhcpErrorEvent.BUFFER_UNDERFLOW, optionType);
throw new ParseException("BufferUnderflowException");
}
}
@@ -1012,6 +1025,7 @@
switch(dhcpType) {
case (byte) 0xFF:
+ DhcpErrorEvent.logEvent(DhcpErrorEvent.DHCP_NO_MSG_TYPE);
throw new ParseException("No DHCP message type option");
case DHCP_MESSAGE_TYPE_DISCOVER:
newPacket = new DhcpDiscoverPacket(
@@ -1045,6 +1059,7 @@
clientMac);
break;
default:
+ DhcpErrorEvent.logEvent(DhcpErrorEvent.DHCP_UNKNOWN_MSG_TYPE);
throw new ParseException("Unimplemented DHCP type %d", dhcpType);
}
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 54aeb3d..59ebf1b 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -30,10 +30,12 @@
import android.net.RouteInfo;
import android.net.StaticIpConfiguration;
import android.net.dhcp.DhcpClient;
+import android.net.metrics.IpManagerEvent;
import android.os.INetworkManagementService;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
@@ -52,6 +54,10 @@
import java.net.SocketException;
import java.util.Objects;
+import static android.net.metrics.IpConnectivityEvent.IPCE_IPMGR_PROVISIONING_OK;
+import static android.net.metrics.IpConnectivityEvent.IPCE_IPMGR_PROVISIONING_FAIL;
+import static android.net.metrics.IpConnectivityEvent.IPCE_IPMGR_COMPLETE_LIFECYCLE;
+
/**
* IpManager
@@ -264,6 +270,7 @@
private ProxyInfo mHttpProxy;
private ApfFilter mApfFilter;
private boolean mMulticastFiltering;
+ private long mStartTimeMillis;
/**
* Member variables accessed both from within the StateMachine thread
@@ -355,6 +362,8 @@
public void startProvisioning(ProvisioningConfiguration req) {
getNetworkInterface();
+
+ mCallback.setNeighborDiscoveryOffload(true);
sendMessage(CMD_START, new ProvisioningConfiguration(req));
}
@@ -477,6 +486,12 @@
}
}
+ private void recordMetric(final int type) {
+ if (mStartTimeMillis <= 0) { Log.wtf(mTag, "Start time undefined!"); }
+ IpManagerEvent.logEvent(type, mInterfaceName,
+ SystemClock.elapsedRealtime() - mStartTimeMillis);
+ }
+
// For now: use WifiStateMachine's historical notion of provisioned.
private static boolean isProvisioned(LinkProperties lp) {
// For historical reasons, we should connect even if all we have is
@@ -534,6 +549,16 @@
delta = ProvisioningChange.LOST_PROVISIONING;
}
+ // Additionally:
+ //
+ // If the previous link properties had a global IPv6 address and an
+ // IPv6 default route then also consider the loss of that default route
+ // to be a loss of provisioning. See b/27962810.
+ if (oldLp.hasGlobalIPv6Address() && oldLp.hasIPv6DefaultRoute() &&
+ !newLp.hasIPv6DefaultRoute()) {
+ delta = ProvisioningChange.LOST_PROVISIONING;
+ }
+
return delta;
}
@@ -542,11 +567,13 @@
switch (delta) {
case GAINED_PROVISIONING:
if (VDBG) { Log.d(mTag, "onProvisioningSuccess()"); }
+ recordMetric(IPCE_IPMGR_PROVISIONING_OK);
mCallback.onProvisioningSuccess(newLp);
break;
case LOST_PROVISIONING:
if (VDBG) { Log.d(mTag, "onProvisioningFailure()"); }
+ recordMetric(IPCE_IPMGR_PROVISIONING_FAIL);
mCallback.onProvisioningFailure(newLp);
break;
@@ -722,6 +749,10 @@
}
resetLinkProperties();
+ if (mStartTimeMillis > 0) {
+ recordMetric(IPCE_IPMGR_COMPLETE_LIFECYCLE);
+ mStartTimeMillis = 0;
+ }
}
@Override
@@ -792,11 +823,16 @@
class StartedState extends State {
@Override
public void enter() {
+ mStartTimeMillis = SystemClock.elapsedRealtime();
+
mApfFilter = ApfFilter.maybeCreate(mConfiguration.mApfCapabilities, mNetworkInterface,
mCallback, mMulticastFiltering);
// TODO: investigate the effects of any multicast filtering racing/interfering with the
// rest of this IP configuration startup.
- if (mApfFilter == null) mCallback.setFallbackMulticastFilter(mMulticastFiltering);
+ if (mApfFilter == null) {
+ mCallback.setFallbackMulticastFilter(mMulticastFiltering);
+ }
+
// Set privacy extensions.
try {
mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
@@ -827,6 +863,7 @@
handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));
} else {
if (VDBG) { Log.d(mTag, "onProvisioningFailure()"); }
+ recordMetric(IPCE_IPMGR_PROVISIONING_FAIL);
mCallback.onProvisioningFailure(getLinkProperties());
transitionTo(mStoppingState);
}
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index af3175a..c8dbe02 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -26,6 +26,7 @@
import android.net.RouteInfo;
import android.net.metrics.IpReachabilityMonitorMessageEvent;
import android.net.metrics.IpReachabilityMonitorProbeEvent;
+import android.net.metrics.IpReachabilityMonitorLostEvent;
import android.net.netlink.NetlinkConstants;
import android.net.netlink.NetlinkErrorMessage;
import android.net.netlink.NetlinkMessage;
@@ -353,6 +354,7 @@
}
if (delta == ProvisioningChange.LOST_PROVISIONING) {
+ IpReachabilityMonitorLostEvent.logEvent(mInterfaceName);
final String logMsg = "FAILURE: LOST_PROVISIONING, " + msg;
Log.w(TAG, logMsg);
if (mCallback != null) {
@@ -521,7 +523,7 @@
final short msgType = neighMsg.getHeader().nlmsg_type;
final short nudState = ndMsg.ndm_state;
- IpReachabilityMonitorMessageEvent.logEvent(maybeGetInterfaceName(mInterfaceIndex),
+ IpReachabilityMonitorMessageEvent.logEvent(mInterfaceName,
destination.getHostAddress(), msgType, nudState);
final String eventMsg = "NeighborEvent{"
+ "elapsedMs=" + whenMs + ", "
@@ -553,11 +555,4 @@
}
}
}
-
- private String maybeGetInterfaceName(int index) {
- if (index == mInterfaceIndex) {
- return mInterfaceName;
- }
- return "ifindex-" + index;
- }
}
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index e6dd6a4..7ffdb35 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -19,7 +19,8 @@
easymocklib \
guava \
android-support-test \
- mockito-target
+ mockito-target \
+ ShortcutManagerTestUtils
LOCAL_JAVA_LIBRARIES := android.test.runner
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 2f20a4b..26eed24 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -70,6 +70,7 @@
import com.android.internal.util.WakeupMessage;
import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkMonitor;
+import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
import com.android.server.net.NetworkPinner;
import java.net.InetAddress;
@@ -223,11 +224,15 @@
private final NetworkCapabilities mNetworkCapabilities;
private final IdleableHandlerThread mHandlerThread;
private final ConditionVariable mDisconnected = new ConditionVariable();
+ private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
private int mScore;
private NetworkAgent mNetworkAgent;
private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
private Integer mExpectedKeepaliveSlot = null;
+ // Contains the redirectUrl from networkStatus(). Before reading, wait for
+ // mNetworkStatusReceived.
+ private String mRedirectUrl;
MockNetworkAgent(int transport) {
final int type = transportToLegacyType(transport);
@@ -266,6 +271,12 @@
public void stopPacketKeepalive(Message msg) {
onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
}
+
+ @Override
+ public void networkStatus(int status, String redirectUrl) {
+ mRedirectUrl = redirectUrl;
+ mNetworkStatusReceived.open();
+ }
};
// Waits for the NetworkAgent to be registered, which includes the creation of the
// NetworkMonitor.
@@ -340,13 +351,15 @@
if (callback != null) mCm.unregisterNetworkCallback(callback);
}
- public void connectWithCaptivePortal() {
+ public void connectWithCaptivePortal(String redirectUrl) {
mWrappedNetworkMonitor.gen204ProbeResult = 200;
+ mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
connect(false);
waitFor(new Criteria() { public boolean get() {
NetworkCapabilities caps = mCm.getNetworkCapabilities(getNetwork());
return caps != null && caps.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL);} });
mWrappedNetworkMonitor.gen204ProbeResult = 500;
+ mWrappedNetworkMonitor.gen204ProbeRedirectUrl = null;
}
public void disconnect() {
@@ -381,6 +394,11 @@
public void setExpectedKeepaliveSlot(Integer slot) {
mExpectedKeepaliveSlot = slot;
}
+
+ public String waitForRedirectUrl() {
+ assertTrue(mNetworkStatusReceived.block(TIMEOUT_MS));
+ return mRedirectUrl;
+ }
}
/**
@@ -543,6 +561,7 @@
private class WrappedNetworkMonitor extends NetworkMonitor {
// HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
public int gen204ProbeResult = 500;
+ public String gen204ProbeRedirectUrl = null;
public WrappedNetworkMonitor(Context context, Handler handler,
NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest) {
@@ -550,8 +569,8 @@
}
@Override
- protected int isCaptivePortal() {
- return gen204ProbeResult;
+ protected CaptivePortalProbeResult isCaptivePortal() {
+ return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl);
}
@Override
@@ -1344,8 +1363,10 @@
// Bring up a network with a captive portal.
// Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
- mWiFiNetworkAgent.connectWithCaptivePortal();
+ String firstRedirectUrl = "http://example.com/firstPath";
+ mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
captivePortalCallback.expectCallback(CallbackState.AVAILABLE);
+ assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
// Take down network.
// Expect onLost callback.
@@ -1355,8 +1376,10 @@
// Bring up a network with a captive portal.
// Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
- mWiFiNetworkAgent.connectWithCaptivePortal();
+ String secondRedirectUrl = "http://example.com/secondPath";
+ mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
captivePortalCallback.expectCallback(CallbackState.AVAILABLE);
+ assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
// Make captive portal disappear then revalidate.
// Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
diff --git a/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java
index dae8447..7d28e39 100644
--- a/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java
@@ -87,6 +87,12 @@
return new File(mStorageDir,
super.getLockPasswordFilename(userId).replace('/', '-')).getAbsolutePath();
}
+
+ @Override
+ String getChildProfileLockFile(int userId) {
+ return new File(mStorageDir,
+ super.getChildProfileLockFile(userId).replace('/', '-')).getAbsolutePath();
+ }
};
}
@@ -235,6 +241,27 @@
assertArrayEquals("profilepassword".getBytes(), mStorage.readPasswordHash(2).hash);
}
+ public void testLockType_WriteProfileWritesParent() {
+ mStorage.writePasswordHash("parentpassword".getBytes(), 10);
+ mStorage.writePatternHash("12345678".getBytes(), 20);
+
+ assertEquals(2, mStorage.getStoredCredentialType(10));
+ assertEquals(1, mStorage.getStoredCredentialType(20));
+ mStorage.clearCache();
+ assertEquals(2, mStorage.getStoredCredentialType(10));
+ assertEquals(1, mStorage.getStoredCredentialType(20));
+ }
+
+ public void testProfileLock_ReadWriteChildProfileLock() {
+ assertFalse(mStorage.hasChildProfileLock(20));
+ mStorage.writeChildProfileLock(20, "profilepassword".getBytes());
+ assertArrayEquals("profilepassword".getBytes(), mStorage.readChildProfileLock(20));
+ assertTrue(mStorage.hasChildProfileLock(20));
+ mStorage.clearCache();
+ assertArrayEquals("profilepassword".getBytes(), mStorage.readChildProfileLock(20));
+ assertTrue(mStorage.hasChildProfileLock(20));
+ }
+
public void testPassword_WriteParentWritesProfile() {
mStorage.writePasswordHash("profilepassword".getBytes(), 2);
mStorage.writePasswordHash("parentpasswordd".getBytes(), 1);
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 5b4803b..4468857 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -16,23 +16,34 @@
package com.android.server.accounts;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import android.accounts.Account;
import android.accounts.AuthenticatorDescription;
+import android.app.AppOpsManager;
import android.app.Notification;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.RegisteredServicesCache.ServiceInfo;
import android.content.pm.RegisteredServicesCacheListener;
+import android.content.pm.UserInfo;
+import android.database.DatabaseErrorHandler;
+import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
+import android.os.UserManager;
import android.test.AndroidTestCase;
-import android.test.IsolatedContext;
-import android.test.RenamingDelegatingContext;
-import android.test.mock.MockContentResolver;
import android.test.mock.MockContext;
import android.test.mock.MockPackageManager;
+import android.util.Log;
+import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -41,20 +52,28 @@
import java.util.Comparator;
public class AccountManagerServiceTest extends AndroidTestCase {
+ private static final String TAG = AccountManagerServiceTest.class.getSimpleName();
+
+ static final String PREN_DB = "pren.db";
+ static final String DE_DB = "de.db";
+ static final String CE_DB = "ce.db";
private AccountManagerService mAms;
@Override
protected void setUp() throws Exception {
- final String filenamePrefix = "test.";
- MockContentResolver resolver = new MockContentResolver();
- RenamingDelegatingContext targetContextWrapper = new RenamingDelegatingContext(
- new MyMockContext(), // The context that most methods are delegated to
- getContext(), // The context that file methods are delegated to
- filenamePrefix);
- Context context = new IsolatedContext(resolver, targetContextWrapper);
- setContext(context);
+ Context realTestContext = getContext();
+ Context mockContext = new MyMockContext(realTestContext);
+ setContext(mockContext);
mAms = new MyAccountManagerService(getContext(),
- new MyMockPackageManager(), new MockAccountAuthenticatorCache());
+ new MyMockPackageManager(), new MockAccountAuthenticatorCache(), realTestContext);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ new File(mAms.getCeDatabaseName(UserHandle.USER_SYSTEM)).delete();
+ new File(mAms.getDeDatabaseName(UserHandle.USER_SYSTEM)).delete();
+ new File(mAms.getPreNDatabaseName(UserHandle.USER_SYSTEM)).delete();
+ super.tearDown();
}
public class AccountSorter implements Comparator<Account> {
@@ -69,6 +88,7 @@
}
public void testCheckAddAccount() throws Exception {
+ unlockUser(UserHandle.USER_SYSTEM);
Account a11 = new Account("account1", "type1");
Account a21 = new Account("account2", "type1");
Account a31 = new Account("account3", "type1");
@@ -109,6 +129,7 @@
}
public void testPasswords() throws Exception {
+ unlockUser(UserHandle.USER_SYSTEM);
Account a11 = new Account("account1", "type1");
Account a12 = new Account("account1", "type2");
mAms.addAccountExplicitly(a11, "p11", null);
@@ -124,6 +145,7 @@
}
public void testUserdata() throws Exception {
+ unlockUser(UserHandle.USER_SYSTEM);
Account a11 = new Account("account1", "type1");
Bundle u11 = new Bundle();
u11.putString("a", "a_a11");
@@ -156,6 +178,7 @@
}
public void testAuthtokens() throws Exception {
+ unlockUser(UserHandle.USER_SYSTEM);
Account a11 = new Account("account1", "type1");
Account a12 = new Account("account1", "type2");
mAms.addAccountExplicitly(a11, "p11", null);
@@ -188,15 +211,21 @@
assertNull(mAms.peekAuthToken(a12, "att2"));
}
+ private void unlockUser(int userId) {
+ Intent intent = new Intent();
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ mAms.onUserUnlocked(intent);
+ }
+
static public class MockAccountAuthenticatorCache implements IAccountAuthenticatorCache {
private ArrayList<ServiceInfo<AuthenticatorDescription>> mServices;
public MockAccountAuthenticatorCache() {
- mServices = new ArrayList<ServiceInfo<AuthenticatorDescription>>();
+ mServices = new ArrayList<>();
AuthenticatorDescription d1 = new AuthenticatorDescription("type1", "p1", 0, 0, 0, 0);
AuthenticatorDescription d2 = new AuthenticatorDescription("type2", "p2", 0, 0, 0, 0);
- mServices.add(new ServiceInfo<AuthenticatorDescription>(d1, null, null));
- mServices.add(new ServiceInfo<AuthenticatorDescription>(d2, null, null));
+ mServices.add(new ServiceInfo<>(d1, null, null));
+ mServices.add(new ServiceInfo<>(d2, null, null));
}
@Override
@@ -232,10 +261,68 @@
}
static public class MyMockContext extends MockContext {
+ private Context mTestContext;
+ private AppOpsManager mAppOpsManager;
+ private UserManager mUserManager;
+
+ public MyMockContext(Context testContext) {
+ this.mTestContext = testContext;
+ this.mAppOpsManager = mock(AppOpsManager.class);
+ this.mUserManager = mock(UserManager.class);
+ final UserInfo ui = new UserInfo(UserHandle.USER_SYSTEM, "user0", 0);
+ when(mUserManager.getUserInfo(eq(ui.id))).thenReturn(ui);
+ }
+
@Override
public int checkCallingOrSelfPermission(final String permission) {
return PackageManager.PERMISSION_GRANTED;
}
+
+ @Override
+ public Object getSystemService(String name) {
+ if (Context.APP_OPS_SERVICE.equals(name)) {
+ return mAppOpsManager;
+ } else if( Context.USER_SERVICE.equals(name)) {
+ return mUserManager;
+ }
+ return null;
+ }
+
+ @Override
+ public String getSystemServiceName(Class<?> serviceClass) {
+ if (AppOpsManager.class.equals(serviceClass)) {
+ return Context.APP_OPS_SERVICE;
+ }
+ return null;
+ }
+
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
+ return null;
+ }
+
+ @Override
+ public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+ IntentFilter filter, String broadcastPermission, Handler scheduler) {
+ return null;
+ }
+
+ @Override
+ public SQLiteDatabase openOrCreateDatabase(String file, int mode,
+ SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) {
+ Log.i(TAG, "openOrCreateDatabase " + file + " mode " + mode);
+ return mTestContext.openOrCreateDatabase(file, mode, factory,errorHandler);
+ }
+
+ @Override
+ public void sendBroadcastAsUser(Intent intent, UserHandle user) {
+ Log.i(TAG, "sendBroadcastAsUser " + intent + " " + user);
+ }
+
+ @Override
+ public String getOpPackageName() {
+ return null;
+ }
}
static public class MyMockPackageManager extends MockPackageManager {
@@ -246,9 +333,11 @@
}
static public class MyAccountManagerService extends AccountManagerService {
+ private Context mRealTestContext;
public MyAccountManagerService(Context context, PackageManager packageManager,
- IAccountAuthenticatorCache authenticatorCache) {
+ IAccountAuthenticatorCache authenticatorCache, Context realTestContext) {
super(context, packageManager, authenticatorCache);
+ this.mRealTestContext = realTestContext;
}
@Override
@@ -258,5 +347,20 @@
@Override
protected void cancelNotification(final int id, UserHandle user) {
}
+
+ @Override
+ protected String getCeDatabaseName(int userId) {
+ return new File(mRealTestContext.getCacheDir(), CE_DB).getPath();
+ }
+
+ @Override
+ protected String getDeDatabaseName(int userId) {
+ return new File(mRealTestContext.getCacheDir(), DE_DB).getPath();
+ }
+
+ @Override
+ String getPreNDatabaseName(int userId) {
+ return new File(mRealTestContext.getCacheDir(), PREN_DB).getPath();
+ }
}
}
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/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
index baa5d36..ce02a79 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
@@ -27,6 +27,7 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.*;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -172,6 +173,11 @@
public String getPackageName() {
return mInjectedClientPackage;
}
+
+ @Override
+ public int getUserId() {
+ return getCallingUserId();
+ }
}
/** Context used in the service side */
@@ -190,6 +196,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. */
@@ -205,7 +216,8 @@
String injectShortcutManagerConstants() {
return ConfigConstants.KEY_RESET_INTERVAL_SEC + "=" + (INTERVAL / 1000) + ","
+ ConfigConstants.KEY_MAX_SHORTCUTS + "=" + MAX_SHORTCUTS + ","
- + ConfigConstants.KEY_MAX_DAILY_UPDATES + "=" + MAX_DAILY_UPDATES + ","
+ + ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL + "="
+ + MAX_UPDATES_PER_INTERVAL + ","
+ ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=" + MAX_ICON_DIMENSION + ","
+ ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "="
+ MAX_ICON_DIMENSION_LOWRAM + ","
@@ -454,7 +466,7 @@
private static final int MAX_SHORTCUTS = 10;
- private static final int MAX_DAILY_UPDATES = 3;
+ private static final int MAX_UPDATES_PER_INTERVAL = 3;
private static final int MAX_ICON_DIMENSION = 128;
@@ -598,14 +610,6 @@
addPackage(packageName, uid, version, packageName);
}
- private <T> List<T> list(T... array) {
- return Arrays.asList(array);
- }
-
- private <T> Set<T> set(Set<T> in) {
- return new ArraySet<T>(in);
- }
-
private Signature[] genSignatures(String... signatures) {
final Signature[] sigs = new Signature[signatures.length];
for (int i = 0; i < signatures.length; i++){
@@ -789,33 +793,6 @@
runTestOnUiThread(() -> {});
}
- public static Bundle makeBundle(Object... keysAndValues) {
- Preconditions.checkState((keysAndValues.length % 2) == 0);
-
- if (keysAndValues.length == 0) {
- return null;
- }
- final Bundle ret = new Bundle();
-
- for (int i = keysAndValues.length - 2; i >= 0; i -= 2) {
- final String key = keysAndValues[i].toString();
- final Object value = keysAndValues[i + 1];
-
- if (value == null) {
- ret.putString(key, null);
- } else if (value instanceof Integer) {
- ret.putInt(key, (Integer) value);
- } else if (value instanceof String) {
- ret.putString(key, (String) value);
- } else if (value instanceof Bundle) {
- ret.putBundle(key, (Bundle) value);
- } else {
- fail("Type not supported yet: " + value.getClass().getName());
- }
- }
- return ret;
- }
-
/**
* Make a shortcut with an ID.
*/
@@ -913,20 +890,6 @@
return new ComponentName(mClientContext, clazz);
}
- private <T> Set<T> makeSet(T... values) {
- final HashSet<T> ret = new HashSet<>();
- for (T s : values) {
- ret.add(s);
- }
- return ret;
- }
-
- private static void resetAll(Collection<?> mocks) {
- for (Object o : mocks) {
- reset(o);
- }
- }
-
@NonNull
private ShortcutInfo findById(List<ShortcutInfo> list, String id) {
for (ShortcutInfo s : list) {
@@ -947,59 +910,8 @@
assertEquals(expectedNextResetTime, mService.getNextResetTimeLocked());
}
- @NonNull
- private List<ShortcutInfo> assertShortcutIds(@NonNull List<ShortcutInfo> actualShortcuts,
- String... expectedIds) {
- final HashSet<String> expected = new HashSet<>(list(expectedIds));
- final HashSet<String> actual = new HashSet<>();
- for (ShortcutInfo s : actualShortcuts) {
- actual.add(s.getId());
- }
-
- // Compare the sets.
- assertEquals(expected, actual);
- return actualShortcuts;
- }
-
- @NonNull
- private List<ShortcutInfo> assertAllHaveIntents(
- @NonNull List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertNotNull("ID " + s.getId(), s.getIntent());
- }
- return actualShortcuts;
- }
-
- @NonNull
- private List<ShortcutInfo> assertAllNotHaveIntents(
- @NonNull List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertNull("ID " + s.getId(), s.getIntent());
- }
- return actualShortcuts;
- }
-
- @NonNull
- private List<ShortcutInfo> assertAllHaveTitle(
- @NonNull List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertNotNull("ID " + s.getId(), s.getTitle());
- }
- return actualShortcuts;
- }
-
- @NonNull
- private List<ShortcutInfo> assertAllNotHaveTitle(
- @NonNull List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertNull("ID " + s.getId(), s.getTitle());
- }
- return actualShortcuts;
- }
-
- @NonNull
- private List<ShortcutInfo> assertAllNotHaveIcon(
- @NonNull List<ShortcutInfo> actualShortcuts) {
+ public static List<ShortcutInfo> assertAllNotHaveIcon(
+ List<ShortcutInfo> actualShortcuts) {
for (ShortcutInfo s : actualShortcuts) {
assertNull("ID " + s.getId(), s.getIcon());
}
@@ -1007,35 +919,6 @@
}
@NonNull
- private List<ShortcutInfo> assertAllHaveIconResId(
- @NonNull List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertTrue("ID " + s.getId() + " not have icon res ID", s.hasIconResource());
- assertFalse("ID " + s.getId() + " shouldn't have icon FD", s.hasIconFile());
- }
- return actualShortcuts;
- }
-
- @NonNull
- private List<ShortcutInfo> assertAllHaveIconFile(
- @NonNull List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertFalse("ID " + s.getId() + " shouldn't have icon res ID", s.hasIconResource());
- assertTrue("ID " + s.getId() + " not have icon FD", s.hasIconFile());
- }
- return actualShortcuts;
- }
-
- @NonNull
- private List<ShortcutInfo> assertAllHaveIcon(
- @NonNull List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertTrue("ID " + s.getId() + " has no icon ", s.hasIconFile() || s.hasIconResource());
- }
- return actualShortcuts;
- }
-
- @NonNull
private List<ShortcutInfo> assertAllHaveFlags(@NonNull List<ShortcutInfo> actualShortcuts,
int shortcutFlags) {
for (ShortcutInfo s : actualShortcuts) {
@@ -1045,87 +928,6 @@
return actualShortcuts;
}
- @NonNull
- private List<ShortcutInfo> assertAllKeyFieldsOnly(
- @NonNull List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertTrue("ID " + s.getId(), s.hasKeyFieldsOnly());
- }
- return actualShortcuts;
- }
-
- @NonNull
- private List<ShortcutInfo> assertAllNotKeyFieldsOnly(
- @NonNull List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertFalse("ID " + s.getId(), s.hasKeyFieldsOnly());
- }
- return actualShortcuts;
- }
-
- @NonNull
- private List<ShortcutInfo> assertAllDynamic(@NonNull List<ShortcutInfo> actualShortcuts) {
- return assertAllHaveFlags(actualShortcuts, ShortcutInfo.FLAG_DYNAMIC);
- }
-
- @NonNull
- private List<ShortcutInfo> assertAllPinned(@NonNull List<ShortcutInfo> actualShortcuts) {
- return assertAllHaveFlags(actualShortcuts, ShortcutInfo.FLAG_PINNED);
- }
-
- @NonNull
- private List<ShortcutInfo> assertAllDynamicOrPinned(
- @NonNull List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertTrue("ID " + s.getId(), s.isDynamic() || s.isPinned());
- }
- return actualShortcuts;
- }
-
- private void assertDynamicOnly(ShortcutInfo si) {
- assertTrue(si.isDynamic());
- assertFalse(si.isPinned());
- }
-
- private void assertPinnedOnly(ShortcutInfo si) {
- assertFalse(si.isDynamic());
- assertTrue(si.isPinned());
- }
-
- private void assertDynamicAndPinned(ShortcutInfo si) {
- assertTrue(si.isDynamic());
- assertTrue(si.isPinned());
- }
-
- private void assertBitmapSize(int expectedWidth, int expectedHeight, @NonNull Bitmap bitmap) {
- assertEquals("width", expectedWidth, bitmap.getWidth());
- assertEquals("height", expectedHeight, bitmap.getHeight());
- }
-
- private <T> void assertAllUnique(Collection<T> list) {
- final Set<Object> set = new HashSet<>();
- for (T item : list) {
- if (set.contains(item)) {
- fail("Duplicate item found: " + item + " (in the list: " + list + ")");
- }
- set.add(item);
- }
- }
-
- @NonNull
- private Bitmap pfdToBitmap(@NonNull ParcelFileDescriptor pfd) {
- Preconditions.checkNotNull(pfd);
- try {
- return BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
- } finally {
- IoUtils.closeQuietly(pfd);
- }
- }
-
- private void assertBundleEmpty(BaseBundle b) {
- assertTrue(b == null || b.size() == 0);
- }
-
private ShortcutInfo getPackageShortcut(String packageName, String shortcutId, int userId) {
return mService.getPackageShortcutForTest(packageName, shortcutId, userId);
}
@@ -1152,9 +954,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 +1011,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);
@@ -1249,7 +1075,7 @@
assertResetTimes(START_TIME + INTERVAL, START_TIME + 2 * INTERVAL);
- // Advance further; 4 days since start.
+ // Advance further; 4 hours since start.
mInjectedCurrentTimeLillis = START_TIME + 4 * INTERVAL + 50;
assertResetTimes(START_TIME + 4 * INTERVAL, START_TIME + 5 * INTERVAL);
@@ -1286,14 +1112,14 @@
mService.updateConfigurationLocked(
ConfigConstants.KEY_RESET_INTERVAL_SEC + "=123,"
+ ConfigConstants.KEY_MAX_SHORTCUTS + "=4,"
- + ConfigConstants.KEY_MAX_DAILY_UPDATES + "=5,"
+ + ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL + "=5,"
+ ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=100,"
+ ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "=50,"
+ ConfigConstants.KEY_ICON_FORMAT + "=WEBP,"
+ ConfigConstants.KEY_ICON_QUALITY + "=75");
assertEquals(123000, mService.getResetIntervalForTest());
assertEquals(4, mService.getMaxDynamicShortcutsForTest());
- assertEquals(5, mService.getMaxDailyUpdatesForTest());
+ assertEquals(5, mService.getMaxUpdatesPerIntervalForTest());
assertEquals(100, mService.getMaxIconDimensionForTest());
assertEquals(CompressFormat.WEBP, mService.getIconPersistFormatForTest());
assertEquals(75, mService.getIconPersistQualityForTest());
@@ -1309,8 +1135,8 @@
assertEquals(ShortcutService.DEFAULT_MAX_SHORTCUTS_PER_APP,
mService.getMaxDynamicShortcutsForTest());
- assertEquals(ShortcutService.DEFAULT_MAX_DAILY_UPDATES,
- mService.getMaxDailyUpdatesForTest());
+ assertEquals(ShortcutService.DEFAULT_MAX_UPDATES_PER_INTERVAL,
+ mService.getMaxUpdatesPerIntervalForTest());
assertEquals(50, mService.getMaxIconDimensionForTest());
@@ -1329,7 +1155,7 @@
/** Test for {@link android.content.pm.ShortcutManager#getRemainingCallCount()} */
public void testGetRemainingCallCount() {
- assertEquals(MAX_DAILY_UPDATES, mManager.getRemainingCallCount());
+ assertEquals(MAX_UPDATES_PER_INTERVAL, mManager.getRemainingCallCount());
}
/** Test for {@link android.content.pm.ShortcutManager#getRateLimitResetTime()} */
@@ -1416,61 +1242,71 @@
mManager.getDynamicShortcuts()),
"shortcut1");
- assertTrue(mManager.addDynamicShortcut(si2));
+ assertTrue(mManager.addDynamicShortcuts(list(si2, si3)));
assertEquals(1, mManager.getRemainingCallCount());
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
- "shortcut1", "shortcut2");
+ "shortcut1", "shortcut2", "shortcut3");
- // Add with the same ID
- assertTrue(mManager.addDynamicShortcut(makeShortcut("shortcut1")));
+ // This should not crash. It'll still consume the quota.
+ assertTrue(mManager.addDynamicShortcuts(list()));
assertEquals(0, mManager.getRemainingCallCount());
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
- "shortcut1", "shortcut2");
+ "shortcut1", "shortcut2", "shortcut3");
+
+ mInjectedCurrentTimeLillis += INTERVAL; // reset
+
+ // Add with the same ID
+ assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("shortcut1"))));
+ assertEquals(2, mManager.getRemainingCallCount());
+ assertShortcutIds(assertAllNotKeyFieldsOnly(
+ mManager.getDynamicShortcuts()),
+ "shortcut1", "shortcut2", "shortcut3");
// TODO Check max number
// TODO Check fields.
runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
- assertTrue(mManager.addDynamicShortcut(makeShortcut("s1")));
+ assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
});
}
- public void testDeleteDynamicShortcut() {
+ public void testDeleteDynamicShortcuts() {
final ShortcutInfo si1 = makeShortcut("shortcut1");
final ShortcutInfo si2 = makeShortcut("shortcut2");
final ShortcutInfo si3 = makeShortcut("shortcut3");
+ final ShortcutInfo si4 = makeShortcut("shortcut4");
- assertTrue(mManager.setDynamicShortcuts(list(si1, si2, si3)));
+ assertTrue(mManager.setDynamicShortcuts(list(si1, si2, si3, si4)));
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
- "shortcut1", "shortcut2", "shortcut3");
+ "shortcut1", "shortcut2", "shortcut3", "shortcut4");
assertEquals(2, mManager.getRemainingCallCount());
- mManager.deleteDynamicShortcut("shortcut1");
+ mManager.removeDynamicShortcuts(list("shortcut1"));
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
- "shortcut2", "shortcut3");
+ "shortcut2", "shortcut3", "shortcut4");
- mManager.deleteDynamicShortcut("shortcut1");
+ mManager.removeDynamicShortcuts(list("shortcut1"));
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
- "shortcut2", "shortcut3");
+ "shortcut2", "shortcut3", "shortcut4");
- mManager.deleteDynamicShortcut("shortcutXXX");
+ mManager.removeDynamicShortcuts(list("shortcutXXX"));
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
- "shortcut2", "shortcut3");
+ "shortcut2", "shortcut3", "shortcut4");
- mManager.deleteDynamicShortcut("shortcut2");
+ mManager.removeDynamicShortcuts(list("shortcut2", "shortcut4"));
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()),
"shortcut3");
- mManager.deleteDynamicShortcut("shortcut3");
+ mManager.removeDynamicShortcuts(list("shortcut3"));
assertShortcutIds(assertAllNotKeyFieldsOnly(
mManager.getDynamicShortcuts()));
@@ -1490,7 +1326,7 @@
assertEquals(2, mManager.getRemainingCallCount());
- mManager.deleteAllDynamicShortcuts();
+ mManager.removeAllDynamicShortcuts();
assertEquals(0, mManager.getDynamicShortcuts().size());
assertEquals(2, mManager.getRemainingCallCount());
@@ -1558,7 +1394,7 @@
assertEquals(0, mManager.getRemainingCallCount());
assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
- // 4 days later...
+ // 4 hours later...
mInjectedCurrentTimeLillis = START_TIME + 4 * INTERVAL;
assertTrue(mManager.setDynamicShortcuts(list(si1)));
assertEquals(2, mManager.getRemainingCallCount());
@@ -1684,7 +1520,7 @@
assertFalse(mManager.setDynamicShortcuts(list(si2)));
}
- public void testIcons() {
+ public void testIcons() throws IOException {
final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32);
final Icon res64x64 = Icon.createWithResource(getTestContext(), R.drawable.black_64x64);
final Icon res512x512 = Icon.createWithResource(getTestContext(), R.drawable.black_512x512);
@@ -1728,6 +1564,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 +1583,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.
@@ -1927,13 +1802,13 @@
getCallingUser());
});
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
- mManager.deleteDynamicShortcut("s1");
- mManager.deleteDynamicShortcut("s2");
+ mManager.removeDynamicShortcuts(list("s1"));
+ mManager.removeDynamicShortcuts(list("s2"));
});
runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
- mManager.deleteDynamicShortcut("s1");
- mManager.deleteDynamicShortcut("s3");
- mManager.deleteDynamicShortcut("s5");
+ mManager.removeDynamicShortcuts(list("s1"));
+ mManager.removeDynamicShortcuts(list("s3"));
+ mManager.removeDynamicShortcuts(list("s5"));
});
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
@@ -2034,9 +1909,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 +1992,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 +2044,13 @@
getCallingUser())),
"s1", "s3");
+ 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
}
@@ -2181,7 +2100,7 @@
// Delete some.
setCaller(CALLING_PACKAGE_1);
assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
- mManager.deleteDynamicShortcut("s2");
+ mManager.removeDynamicShortcuts(list("s2"));
assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
dumpsysOnLogcat();
@@ -2246,19 +2165,19 @@
// Delete some.
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
- mManager.deleteDynamicShortcut("s2");
+ mManager.removeDynamicShortcuts(list("s2"));
assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
});
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
- mManager.deleteDynamicShortcut("s3");
+ mManager.removeDynamicShortcuts(list("s3"));
assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
});
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
- mManager.deleteDynamicShortcut("s2");
+ mManager.removeDynamicShortcuts(list("s2"));
assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
});
@@ -2310,7 +2229,7 @@
// Delete some.
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertShortcutIds(mManager.getPinnedShortcuts(), "s3");
- mManager.deleteDynamicShortcut("s3");
+ mManager.removeDynamicShortcuts(list("s3"));
assertShortcutIds(mManager.getPinnedShortcuts(), "s3");
});
@@ -2318,8 +2237,8 @@
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
assertShortcutIds(mManager.getPinnedShortcuts(), "s1", "s2");
- mManager.deleteDynamicShortcut("s1");
- mManager.deleteDynamicShortcut("s3");
+ mManager.removeDynamicShortcuts(list("s1"));
+ mManager.removeDynamicShortcuts(list("s3"));
assertShortcutIds(mManager.getPinnedShortcuts(), "s1", "s2");
});
@@ -2428,13 +2347,13 @@
// Delete all dynamic.
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
- mManager.deleteAllDynamicShortcuts();
+ mManager.removeAllDynamicShortcuts();
assertEquals(0, mManager.getDynamicShortcuts().size());
assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2", "s3");
});
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
- mManager.deleteAllDynamicShortcuts();
+ mManager.removeAllDynamicShortcuts();
assertEquals(0, mManager.getDynamicShortcuts().size());
assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s2", "s1");
@@ -2469,7 +2388,7 @@
});
// Re-publish s1.
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
- assertTrue(mManager.addDynamicShortcut(makeShortcut("s1")));
+ assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1");
assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2", "s3");
@@ -3071,7 +2990,7 @@
// Just to make it complicated, delete some.
setCaller(CALLING_PACKAGE_1);
- mManager.deleteDynamicShortcut("s2");
+ mManager.removeDynamicShortcuts(list("s2"));
// intent and check.
setCaller(LAUNCHER_1);
@@ -3143,11 +3062,11 @@
any(UserHandle.class)
);
- // Test for addDynamicShortcut.
+ // Test for addDynamicShortcuts.
reset(c0);
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
- dumpsysOnLogcat("before addDynamicShortcut");
- assertTrue(mManager.addDynamicShortcut(makeShortcut("s4")));
+ dumpsysOnLogcat("before addDynamicShortcuts");
+ assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s4"))));
});
waitOnMainThread();
@@ -3163,7 +3082,7 @@
// Test for remove
reset(c0);
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
- mManager.deleteDynamicShortcut("s1");
+ mManager.removeDynamicShortcuts(list("s1"));
});
waitOnMainThread();
@@ -3196,7 +3115,7 @@
// Test for deleteAll
reset(c0);
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
- mManager.deleteAllDynamicShortcuts();
+ mManager.removeAllDynamicShortcuts();
});
waitOnMainThread();
@@ -3224,20 +3143,6 @@
assertEquals(0, shortcuts.getValue().size());
}
- private void assertCallbackNotReceived(LauncherApps.Callback mock) {
- verify(mock, times(0)).onShortcutsChanged(anyString(), anyList(),
- any(UserHandle.class));
- }
-
- private void assertCallbackReceived(LauncherApps.Callback mock,
- UserHandle user, String packageName, String... ids) {
- ArgumentCaptor<List> shortcutsCaptor = ArgumentCaptor.forClass(List.class);
-
- verify(mock, times(1)).onShortcutsChanged(eq(packageName), shortcutsCaptor.capture(),
- eq(user));
- assertShortcutIds(shortcutsCaptor.getValue(), ids);
- }
-
public void testLauncherCallback_crossProfile() throws Throwable {
prepareCrossProfileDataSet();
@@ -3284,7 +3189,7 @@
resetAll(all);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
- mManager.deleteDynamicShortcut("x");
+ mManager.removeDynamicShortcuts(list());
});
waitOnMainThread();
@@ -3301,7 +3206,7 @@
resetAll(all);
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
- mManager.deleteDynamicShortcut("x");
+ mManager.removeDynamicShortcuts(list());
});
waitOnMainThread();
@@ -3319,7 +3224,7 @@
resetAll(all);
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
- mManager.deleteDynamicShortcut("x");
+ mManager.removeDynamicShortcuts(list());
});
waitOnMainThread();
@@ -3339,7 +3244,7 @@
resetAll(all);
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
- mManager.deleteDynamicShortcut("x");
+ mManager.removeDynamicShortcuts(list());
});
waitOnMainThread();
@@ -3359,7 +3264,7 @@
resetAll(all);
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
- mManager.deleteDynamicShortcut("x");
+ mManager.removeDynamicShortcuts(list());
});
waitOnMainThread();
@@ -3583,16 +3488,16 @@
// Remove all dynamic shortcuts; now all shortcuts are just pinned.
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
- mManager.deleteAllDynamicShortcuts();
+ mManager.removeAllDynamicShortcuts();
});
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
- mManager.deleteAllDynamicShortcuts();
+ mManager.removeAllDynamicShortcuts();
});
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
- mManager.deleteAllDynamicShortcuts();
+ mManager.removeAllDynamicShortcuts();
});
runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
- mManager.deleteAllDynamicShortcuts();
+ mManager.removeAllDynamicShortcuts();
});
@@ -3607,18 +3512,18 @@
// Check the registered packages.
dumpsysOnLogcat();
- assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
- set(user0.getAllPackages().keySet()));
- assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
- set(user10.getAllPackages().keySet()));
+ assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
+ hashSet(user0.getAllPackages().keySet()));
+ assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
+ hashSet(user10.getAllPackages().keySet()));
assertEquals(
- makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
+ set(PackageWithUser.of(USER_0, LAUNCHER_1),
PackageWithUser.of(USER_0, LAUNCHER_2)),
- set(user0.getAllLaunchers().keySet()));
+ hashSet(user0.getAllLaunchers().keySet()));
assertEquals(
- makeSet(PackageWithUser.of(USER_10, LAUNCHER_1),
+ set(PackageWithUser.of(USER_10, LAUNCHER_1),
PackageWithUser.of(USER_10, LAUNCHER_2)),
- set(user10.getAllLaunchers().keySet()));
+ hashSet(user10.getAllLaunchers().keySet()));
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
"s0_1", "s0_2");
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
@@ -3639,18 +3544,18 @@
mService.cleanUpPackageLocked("abc", USER_0, USER_0);
// No changes.
- assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
- set(user0.getAllPackages().keySet()));
- assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
- set(user10.getAllPackages().keySet()));
+ assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
+ hashSet(user0.getAllPackages().keySet()));
+ assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
+ hashSet(user10.getAllPackages().keySet()));
assertEquals(
- makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
+ set(PackageWithUser.of(USER_0, LAUNCHER_1),
PackageWithUser.of(USER_0, LAUNCHER_2)),
- set(user0.getAllLaunchers().keySet()));
+ hashSet(user0.getAllLaunchers().keySet()));
assertEquals(
- makeSet(PackageWithUser.of(USER_10, LAUNCHER_1),
+ set(PackageWithUser.of(USER_10, LAUNCHER_1),
PackageWithUser.of(USER_10, LAUNCHER_2)),
- set(user10.getAllLaunchers().keySet()));
+ hashSet(user10.getAllLaunchers().keySet()));
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
"s0_1", "s0_2");
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
@@ -3670,18 +3575,18 @@
uninstallPackage(USER_0, CALLING_PACKAGE_1);
mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_0, USER_0);
- assertEquals(makeSet(CALLING_PACKAGE_2),
- set(user0.getAllPackages().keySet()));
- assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
- set(user10.getAllPackages().keySet()));
+ assertEquals(set(CALLING_PACKAGE_2),
+ hashSet(user0.getAllPackages().keySet()));
+ assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
+ hashSet(user10.getAllPackages().keySet()));
assertEquals(
- makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
+ set(PackageWithUser.of(USER_0, LAUNCHER_1),
PackageWithUser.of(USER_0, LAUNCHER_2)),
- set(user0.getAllLaunchers().keySet()));
+ hashSet(user0.getAllLaunchers().keySet()));
assertEquals(
- makeSet(PackageWithUser.of(USER_10, LAUNCHER_1),
+ set(PackageWithUser.of(USER_10, LAUNCHER_1),
PackageWithUser.of(USER_10, LAUNCHER_2)),
- set(user10.getAllLaunchers().keySet()));
+ hashSet(user10.getAllLaunchers().keySet()));
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
"s0_2");
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
@@ -3701,17 +3606,17 @@
uninstallPackage(USER_10, LAUNCHER_1);
mService.cleanUpPackageLocked(LAUNCHER_1, USER_10, USER_10);
- assertEquals(makeSet(CALLING_PACKAGE_2),
- set(user0.getAllPackages().keySet()));
- assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
- set(user10.getAllPackages().keySet()));
+ assertEquals(set(CALLING_PACKAGE_2),
+ hashSet(user0.getAllPackages().keySet()));
+ assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
+ hashSet(user10.getAllPackages().keySet()));
assertEquals(
- makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
+ set(PackageWithUser.of(USER_0, LAUNCHER_1),
PackageWithUser.of(USER_0, LAUNCHER_2)),
- set(user0.getAllLaunchers().keySet()));
+ hashSet(user0.getAllLaunchers().keySet()));
assertEquals(
- makeSet(PackageWithUser.of(USER_10, LAUNCHER_2)),
- set(user10.getAllLaunchers().keySet()));
+ set(PackageWithUser.of(USER_10, LAUNCHER_2)),
+ hashSet(user10.getAllLaunchers().keySet()));
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
"s0_2");
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
@@ -3729,17 +3634,17 @@
uninstallPackage(USER_10, CALLING_PACKAGE_2);
mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_10, USER_10);
- assertEquals(makeSet(CALLING_PACKAGE_2),
- set(user0.getAllPackages().keySet()));
- assertEquals(makeSet(CALLING_PACKAGE_1),
- set(user10.getAllPackages().keySet()));
+ assertEquals(set(CALLING_PACKAGE_2),
+ hashSet(user0.getAllPackages().keySet()));
+ assertEquals(set(CALLING_PACKAGE_1),
+ hashSet(user10.getAllPackages().keySet()));
assertEquals(
- makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
+ set(PackageWithUser.of(USER_0, LAUNCHER_1),
PackageWithUser.of(USER_0, LAUNCHER_2)),
- set(user0.getAllLaunchers().keySet()));
+ hashSet(user0.getAllLaunchers().keySet()));
assertEquals(
- makeSet(PackageWithUser.of(USER_10, LAUNCHER_2)),
- set(user10.getAllLaunchers().keySet()));
+ set(PackageWithUser.of(USER_10, LAUNCHER_2)),
+ hashSet(user10.getAllLaunchers().keySet()));
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
"s0_2");
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
@@ -3757,17 +3662,17 @@
uninstallPackage(USER_10, LAUNCHER_2);
mService.cleanUpPackageLocked(LAUNCHER_2, USER_10, USER_10);
- assertEquals(makeSet(CALLING_PACKAGE_2),
- set(user0.getAllPackages().keySet()));
- assertEquals(makeSet(CALLING_PACKAGE_1),
- set(user10.getAllPackages().keySet()));
+ assertEquals(set(CALLING_PACKAGE_2),
+ hashSet(user0.getAllPackages().keySet()));
+ assertEquals(set(CALLING_PACKAGE_1),
+ hashSet(user10.getAllPackages().keySet()));
assertEquals(
- makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
+ set(PackageWithUser.of(USER_0, LAUNCHER_1),
PackageWithUser.of(USER_0, LAUNCHER_2)),
- set(user0.getAllLaunchers().keySet()));
+ hashSet(user0.getAllLaunchers().keySet()));
assertEquals(
- makeSet(),
- set(user10.getAllLaunchers().keySet()));
+ set(),
+ hashSet(user10.getAllLaunchers().keySet()));
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
"s0_2");
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
@@ -3785,16 +3690,16 @@
uninstallPackage(USER_10, CALLING_PACKAGE_1);
mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_10, USER_10);
- assertEquals(makeSet(CALLING_PACKAGE_2),
- set(user0.getAllPackages().keySet()));
- assertEquals(makeSet(),
- set(user10.getAllPackages().keySet()));
+ assertEquals(set(CALLING_PACKAGE_2),
+ hashSet(user0.getAllPackages().keySet()));
+ assertEquals(set(),
+ hashSet(user10.getAllPackages().keySet()));
assertEquals(
- makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
+ set(PackageWithUser.of(USER_0, LAUNCHER_1),
PackageWithUser.of(USER_0, LAUNCHER_2)),
- set(user0.getAllLaunchers().keySet()));
- assertEquals(makeSet(),
- set(user10.getAllLaunchers().keySet()));
+ hashSet(user0.getAllLaunchers().keySet()));
+ assertEquals(set(),
+ hashSet(user10.getAllLaunchers().keySet()));
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
"s0_2");
assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
@@ -4115,22 +4020,22 @@
public void testHandlePackageDelete() {
setCaller(CALLING_PACKAGE_1, USER_0);
- assertTrue(mManager.addDynamicShortcut(makeShortcut("s1")));
+ assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
setCaller(CALLING_PACKAGE_2, USER_0);
- assertTrue(mManager.addDynamicShortcut(makeShortcut("s1")));
+ assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
setCaller(CALLING_PACKAGE_3, USER_0);
- assertTrue(mManager.addDynamicShortcut(makeShortcut("s1")));
+ assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
setCaller(CALLING_PACKAGE_1, USER_10);
- assertTrue(mManager.addDynamicShortcut(makeShortcut("s1")));
+ assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
setCaller(CALLING_PACKAGE_2, USER_10);
- assertTrue(mManager.addDynamicShortcut(makeShortcut("s1")));
+ assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
setCaller(CALLING_PACKAGE_3, USER_10);
- assertTrue(mManager.addDynamicShortcut(makeShortcut("s1")));
+ assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
@@ -4935,7 +4840,7 @@
assertShortcutIds(
mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_P0)
/* empty */);
- TestUtils.assertExpectException(
+ assertExpectException(
SecurityException.class, "", () -> {
mLauncherApps.getShortcuts(
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10);
@@ -5014,7 +4919,7 @@
assertShortcutIds(
mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_P0),
"s1", "s4");
- TestUtils.assertExpectException(
+ assertExpectException(
SecurityException.class, "unrelated profile", () -> {
mLauncherApps.getShortcuts(
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10);
@@ -5030,12 +4935,12 @@
assertShortcutIds(
mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_10)
/* empty */);
- TestUtils.assertExpectException(
+ assertExpectException(
SecurityException.class, "unrelated profile", () -> {
mLauncherApps.getShortcuts(
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0);
});
- TestUtils.assertExpectException(
+ assertExpectException(
SecurityException.class, "unrelated profile", () -> {
mLauncherApps.getShortcuts(
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_P0);
@@ -5046,16 +4951,16 @@
// ShortcutInfo tests
public void testShortcutInfoMissingMandatoryFields() {
- TestUtils.assertExpectException(
+ assertExpectException(
IllegalArgumentException.class,
"ID must be provided",
() -> new ShortcutInfo.Builder(getTestContext()).build());
- TestUtils.assertExpectException(
+ assertExpectException(
IllegalArgumentException.class,
"title must be provided",
() -> new ShortcutInfo.Builder(getTestContext()).setId("id").build()
.enforceMandatoryFields());
- TestUtils.assertExpectException(
+ assertExpectException(
NullPointerException.class,
"Intent must be provided",
() -> new ShortcutInfo.Builder(getTestContext()).setId("id").setTitle("x").build()
@@ -5063,12 +4968,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());
@@ -5083,6 +4991,7 @@
.setTitle("title")
.setText("text")
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+ .setCategories(list(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setWeight(123)
.setExtras(pb)
.build();
@@ -5098,6 +5007,7 @@
assertEquals("content://a.b.c/", si.getIcon().getUriString());
assertEquals("title", si.getTitle());
assertEquals("text", si.getText());
+ assertEquals(list(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getWeight());
@@ -5109,14 +5019,17 @@
}
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/"))
.setTitle("title")
.setText("text")
+ .setCategories(list(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setWeight(123)
.setExtras(pb)
@@ -5127,12 +5040,15 @@
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());
assertEquals("title", si.getTitle());
assertEquals("text", si.getText());
+ assertEquals(list(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getWeight());
@@ -5144,12 +5060,13 @@
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());
assertEquals("title", si.getTitle());
assertEquals("text", si.getText());
+ assertEquals(list(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getWeight());
@@ -5157,39 +5074,85 @@
assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
assertEquals(null, si.getBitmapPath());
- assertEquals(0, si.getIconResourceId());
+
+ assertEquals(456, si.getIconResourceId());
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());
assertEquals("title", si.getTitle());
assertEquals("text", si.getText());
+ assertEquals(list(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals(null, si.getIntent());
assertEquals(123, si.getWeight());
assertEquals(1, si.getExtras().getInt("k"));
assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
assertEquals(null, si.getBitmapPath());
- assertEquals(0, si.getIconResourceId());
+
+ assertEquals(456, si.getIconResourceId());
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());
assertEquals(null, si.getTitle());
assertEquals(null, si.getText());
+ assertEquals(null, si.getCategories());
assertEquals(null, si.getIntent());
assertEquals(0, si.getWeight());
assertEquals(null, si.getExtras());
assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY, si.getFlags());
assertEquals(null, si.getBitmapPath());
- assertEquals(0, si.getIconResourceId());
+
+ assertEquals(456, si.getIconResourceId());
+ }
+
+ public void testShortcutInfoClone_minimum() {
+ PersistableBundle pb = new PersistableBundle();
+ pb.putInt("k", 1);
+ ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
+ .setId("id")
+ .setTitle("title")
+ .setIntent(makeIntent("action", ShortcutActivity.class))
+ .build();
+ ShortcutInfo si = sorig.clone(/* clone flags*/ 0);
+
+ assertEquals(getTestContext().getPackageName(), si.getPackageName());
+ assertEquals("id", si.getId());
+ assertEquals("title", si.getTitle());
+ assertEquals("action", si.getIntent().getAction());
+ assertEquals(null, si.getCategories());
+
+ si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
+
+ assertEquals(getTestContext().getPackageName(), si.getPackageName());
+ assertEquals("id", si.getId());
+ assertEquals("title", si.getTitle());
+ assertEquals("action", si.getIntent().getAction());
+ assertEquals(null, si.getCategories());
+
+ si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
+
+ assertEquals(getTestContext().getPackageName(), si.getPackageName());
+ assertEquals("id", si.getId());
+ assertEquals("title", si.getTitle());
+ assertEquals(null, si.getIntent());
+ assertEquals(null, si.getCategories());
+
+ si = sorig.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO);
+
+ assertEquals(getTestContext().getPackageName(), si.getPackageName());
+ assertEquals("id", si.getId());
+ assertEquals(null, si.getTitle());
+ assertEquals(null, si.getIntent());
+ assertEquals(null, si.getCategories());
}
public void testShortcutInfoCopyNonNullFieldsFrom() throws InterruptedException {
@@ -5201,6 +5164,7 @@
.setIcon(Icon.createWithContentUri("content://a.b.c/"))
.setTitle("title")
.setText("text")
+ .setCategories(list(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setWeight(123)
.setExtras(pb)
@@ -5214,38 +5178,57 @@
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setActivityComponent(new ComponentName("x", "y")).build());
+ assertEquals("text", si.getText());
assertEquals(new ComponentName("x", "y"), si.getActivityComponent());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setIcon(Icon.createWithContentUri("content://x.y.z/")).build());
+ assertEquals("text", si.getText());
assertEquals("content://x.y.z/", si.getIcon().getUriString());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setTitle("xyz").build());
+ assertEquals("text", si.getText());
assertEquals("xyz", si.getTitle());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setText("xxx").build());
+ assertEquals(123, si.getWeight());
assertEquals("xxx", si.getText());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
+ .setCategories(list()).build());
+ assertEquals("text", si.getText());
+ assertEquals(list(), si.getCategories());
+
+ si = sorig.clone(/* flags=*/ 0);
+ si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
+ .setCategories(list("x")).build());
+ assertEquals("text", si.getText());
+ assertEquals(list("x"), si.getCategories());
+
+ si = sorig.clone(/* flags=*/ 0);
+ si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setIntent(makeIntent("action2", ShortcutActivity.class)).build());
+ assertEquals("text", si.getText());
assertEquals("action2", si.getIntent().getAction());
assertEquals(null, si.getIntent().getStringExtra("key"));
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setIntent(makeIntent("action3", ShortcutActivity.class, "key", "x")).build());
+ assertEquals("text", si.getText());
assertEquals("action3", si.getIntent().getAction());
assertEquals("x", si.getIntent().getStringExtra("key"));
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setWeight(999).build());
+ assertEquals("text", si.getText());
assertEquals(999, si.getWeight());
@@ -5255,8 +5238,11 @@
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setExtras(pb2).build());
+ assertEquals("text", si.getText());
assertEquals(99, si.getExtras().getInt("x"));
+ // Make sure the timestamp gets updated too.
+
final long timestamp = si.getLastChangedTimestamp();
Thread.sleep(2);
@@ -5267,7 +5253,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));
@@ -5280,12 +5266,13 @@
.setIcon(bmp32x32)
.setTitle("title")
.setText("text")
+ .setCategories(list(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setWeight(123)
.setExtras(pb)
.build();
- mManager.addDynamicShortcut(sorig);
+ mManager.addDynamicShortcuts(list(sorig));
Thread.sleep(2);
final long now = System.currentTimeMillis();
@@ -5293,17 +5280,20 @@
// 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());
assertEquals(null, si.getIcon());
assertEquals("title", si.getTitle());
assertEquals("text", si.getText());
+ assertEquals(list(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getWeight());
@@ -5329,12 +5319,13 @@
.setIcon(bmp32x32)
.setTitle("title")
.setText("text")
+ .setCategories(list(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setWeight(123)
.setExtras(pb)
.build();
- mManager.addDynamicShortcut(sorig);
+ mManager.addDynamicShortcuts(list(sorig));
// Dynamic shortcuts won't be backed up, so we need to pin it.
setCaller(LAUNCHER_1, USER_0);
@@ -5343,6 +5334,8 @@
// Do backup & restore.
backupAndRestore();
+ mService.handleUnlockUser(USER_0); // Load user-0.
+
ShortcutInfo si;
si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_0);
@@ -5352,6 +5345,7 @@
assertEquals(null, si.getIcon());
assertEquals("title", si.getTitle());
assertEquals("text", si.getText());
+ assertEquals(list(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getWeight());
@@ -5367,7 +5361,7 @@
dumpsysOnLogcat("test1", /* force= */ true);
}
- public void testDumpsys_withIcons() {
+ public void testDumpsys_withIcons() throws IOException {
testIcons();
// Dump after having some icons.
dumpsysOnLogcat("test1", /* force= */ true);
diff --git a/services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java b/services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java
new file mode 100644
index 0000000..e33be40
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/webkit/TestSystemImpl.java
@@ -0,0 +1,116 @@
+/*
+ * 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.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.webkit.WebViewProviderInfo;
+
+import java.util.HashMap;
+
+public class TestSystemImpl implements SystemInterface {
+ private String mUserProvider = null;
+ private final WebViewProviderInfo[] mPackageConfigs;
+ HashMap<String, PackageInfo> mPackages = new HashMap();
+ private boolean mFallbackLogicEnabled;
+ private final int mNumRelros;
+ private final boolean mIsDebuggable;
+
+ public TestSystemImpl(WebViewProviderInfo[] packageConfigs, boolean fallbackLogicEnabled,
+ int numRelros, boolean isDebuggable) {
+ mPackageConfigs = packageConfigs;
+ mFallbackLogicEnabled = fallbackLogicEnabled;
+ mNumRelros = numRelros;
+ mIsDebuggable = isDebuggable;
+ }
+
+ @Override
+ public WebViewProviderInfo[] getWebViewPackages() {
+ return mPackageConfigs;
+ }
+
+ @Override
+ public int onWebViewProviderChanged(PackageInfo packageInfo) {
+ return mNumRelros;
+ }
+
+ @Override
+ public String getUserChosenWebViewProvider(Context context) { return mUserProvider; }
+
+ @Override
+ public void updateUserSetting(Context context, String newProviderName) {
+ mUserProvider = newProviderName;
+ }
+
+ @Override
+ public void killPackageDependents(String packageName) {}
+
+ @Override
+ public boolean isFallbackLogicEnabled() {
+ return mFallbackLogicEnabled;
+ }
+
+ @Override
+ public void enableFallbackLogic(boolean enable) {
+ mFallbackLogicEnabled = enable;
+ }
+
+ @Override
+ public void uninstallAndDisablePackageForAllUsers(Context context, String packageName) {
+ enablePackageForAllUsers(context, packageName, false);
+ }
+
+ @Override
+ public void enablePackageForAllUsers(Context context, String packageName, boolean enable) {
+ enablePackageForUser(packageName, enable, 0);
+ }
+
+ @Override
+ public void enablePackageForUser(String packageName, boolean enable, int userId) {
+ PackageInfo packageInfo = mPackages.get(packageName);
+ if (packageInfo == null) {
+ throw new IllegalArgumentException("There is no package called " + packageName);
+ }
+ packageInfo.applicationInfo.enabled = enable;
+ setPackageInfo(packageInfo);
+ }
+
+ @Override
+ public boolean systemIsDebuggable() { return mIsDebuggable; }
+
+ @Override
+ public PackageInfo getPackageInfoForProvider(WebViewProviderInfo info) throws
+ NameNotFoundException {
+ PackageInfo ret = mPackages.get(info.packageName);
+ if (ret == null) throw new NameNotFoundException(info.packageName);
+ return ret;
+ }
+
+ public void setPackageInfo(PackageInfo pi) {
+ mPackages.put(pi.packageName, pi);
+ }
+
+ public void removePackageInfo(String packageName) {
+ mPackages.remove(packageName);
+ }
+
+ @Override
+ public int getFactoryPackageVersion(String packageName) {
+ return 0;
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
new file mode 100644
index 0000000..c03324a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
@@ -0,0 +1,820 @@
+/*
+ * 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.Signature;
+import android.os.Bundle;
+import android.util.Base64;
+import android.test.AndroidTestCase;
+
+import android.webkit.WebViewFactory;
+import android.webkit.WebViewProviderInfo;
+import android.webkit.WebViewProviderResponse;
+
+import java.util.concurrent.CountDownLatch;
+
+import org.hamcrest.Description;
+
+import org.mockito.Mockito;
+import org.mockito.Matchers;
+import org.mockito.ArgumentMatcher;
+
+
+/**
+ * Tests for WebViewUpdateService
+ */
+public class WebViewUpdateServiceTest extends AndroidTestCase {
+ private final static String TAG = WebViewUpdateServiceTest.class.getSimpleName();
+
+ private WebViewUpdateServiceImpl mWebViewUpdateServiceImpl;
+ private TestSystemImpl mTestSystemImpl;
+
+ private static final String WEBVIEW_LIBRARY_FLAG = "com.android.webview.WebViewLibrary";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ /**
+ * Creates a new instance.
+ */
+ public WebViewUpdateServiceTest() {
+ }
+
+ private void setupWithPackages(WebViewProviderInfo[] packages) {
+ setupWithPackages(packages, true);
+ }
+
+ private void setupWithPackages(WebViewProviderInfo[] packages,
+ boolean fallbackLogicEnabled) {
+ setupWithPackages(packages, fallbackLogicEnabled, 1);
+ }
+
+ private void setupWithPackages(WebViewProviderInfo[] packages,
+ boolean fallbackLogicEnabled, int numRelros) {
+ setupWithPackages(packages, fallbackLogicEnabled, numRelros,
+ true /* isDebuggable == true -> don't check package signatures */);
+ }
+
+ private void setupWithPackages(WebViewProviderInfo[] packages,
+ boolean fallbackLogicEnabled, int numRelros, boolean isDebuggable) {
+ TestSystemImpl testing = new TestSystemImpl(packages, fallbackLogicEnabled, numRelros,
+ isDebuggable);
+ mTestSystemImpl = Mockito.spy(testing);
+ mWebViewUpdateServiceImpl =
+ new WebViewUpdateServiceImpl(null /*Context*/, mTestSystemImpl);
+ }
+
+ private void setEnabledAndValidPackageInfos(WebViewProviderInfo[] providers) {
+ for(WebViewProviderInfo wpi : providers) {
+ mTestSystemImpl.setPackageInfo(createPackageInfo(wpi.packageName, true /* enabled */,
+ true /* valid */));
+ }
+ }
+
+ private void checkCertainPackageUsedAfterWebViewBootPreparation(String expectedProviderName,
+ WebViewProviderInfo[] webviewPackages) {
+ checkCertainPackageUsedAfterWebViewBootPreparation(
+ expectedProviderName, webviewPackages, 1);
+ }
+
+ private void checkCertainPackageUsedAfterWebViewBootPreparation(String expectedProviderName,
+ WebViewProviderInfo[] webviewPackages, int numRelros) {
+ setupWithPackages(webviewPackages, true, numRelros);
+ // Add (enabled and valid) package infos for each provider
+ setEnabledAndValidPackageInfos(webviewPackages);
+
+ mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+
+ Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
+ Mockito.argThat(new IsPackageInfoWithName(expectedProviderName)));
+
+ for (int n = 0; n < numRelros; n++) {
+ mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
+ }
+
+ WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
+ assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
+ assertEquals(expectedProviderName, response.packageInfo.packageName);
+ }
+
+ // For matching the package name of a PackageInfo
+ private class IsPackageInfoWithName extends ArgumentMatcher<PackageInfo> {
+ private final String mPackageName;
+
+ IsPackageInfoWithName(String name) {
+ mPackageName = name;
+ }
+
+ @Override
+ public boolean matches(Object p) {
+ return ((PackageInfo) p).packageName.equals(mPackageName);
+ }
+
+ // Provide a more useful description in case of mismatch
+ @Override
+ public void describeTo (Description description) {
+ description.appendText(String.format("PackageInfo with name '%s'", mPackageName));
+ }
+ }
+
+ private static PackageInfo createPackageInfo(
+ String packageName, boolean enabled, boolean valid) {
+ PackageInfo p = new PackageInfo();
+ p.packageName = packageName;
+ p.applicationInfo = new ApplicationInfo();
+ p.applicationInfo.enabled = enabled;
+ p.applicationInfo.metaData = new Bundle();
+ if (valid) {
+ // no flag means invalid
+ p.applicationInfo.metaData.putString(WEBVIEW_LIBRARY_FLAG, "blah");
+ }
+ return p;
+ }
+
+ private static PackageInfo createPackageInfo(
+ String packageName, boolean enabled, boolean valid, Signature[] signatures) {
+ PackageInfo p = createPackageInfo(packageName, enabled, valid);
+ p.signatures = signatures;
+ return p;
+ }
+
+ private void checkPreparationPhasesForPackage(String expectedPackage, int numPreparation) {
+ // Verify that onWebViewProviderChanged was called for the numPreparation'th time for the
+ // expected package
+ Mockito.verify(mTestSystemImpl, Mockito.times(numPreparation)).onWebViewProviderChanged(
+ Mockito.argThat(new IsPackageInfoWithName(expectedPackage)));
+
+ mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
+
+ WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
+ assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
+ assertEquals(expectedPackage, response.packageInfo.packageName);
+ }
+
+
+ // ****************
+ // Tests
+ // ****************
+
+
+ public void testWithSinglePackage() {
+ String testPackageName = "test.package.name";
+ checkCertainPackageUsedAfterWebViewBootPreparation(testPackageName,
+ new WebViewProviderInfo[] {
+ new WebViewProviderInfo(testPackageName, "",
+ true /*default available*/, false /* fallback */, null)});
+ }
+
+ public void testDefaultPackageUsedOverNonDefault() {
+ String defaultPackage = "defaultPackage";
+ String nonDefaultPackage = "nonDefaultPackage";
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(nonDefaultPackage, "", false, false, null),
+ new WebViewProviderInfo(defaultPackage, "", true, false, null)};
+ checkCertainPackageUsedAfterWebViewBootPreparation(defaultPackage, packages);
+ }
+
+ public void testSeveralRelros() {
+ String singlePackage = "singlePackage";
+ checkCertainPackageUsedAfterWebViewBootPreparation(
+ singlePackage,
+ new WebViewProviderInfo[] {
+ new WebViewProviderInfo(singlePackage, "", true /*def av*/, false, null)},
+ 2);
+ }
+
+ // Ensure that package with valid signatures is chosen rather than package with invalid
+ // signatures.
+ public void testWithSignatures() {
+ String validPackage = "valid package";
+ String invalidPackage = "invalid package";
+
+ Signature validSignature = new Signature("11");
+ Signature invalidExpectedSignature = new Signature("22");
+ Signature invalidPackageSignature = new Signature("33");
+
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(invalidPackage, "", true, false, new String[]{
+ Base64.encodeToString(
+ invalidExpectedSignature.toByteArray(), Base64.DEFAULT)}),
+ new WebViewProviderInfo(validPackage, "", true, false, new String[]{
+ Base64.encodeToString(
+ validSignature.toByteArray(), Base64.DEFAULT)})
+ };
+ setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */,
+ false /* isDebuggable */);
+ mTestSystemImpl.setPackageInfo(createPackageInfo(invalidPackage, true /* enabled */,
+ true /* valid */, new Signature[]{invalidPackageSignature}));
+ mTestSystemImpl.setPackageInfo(createPackageInfo(validPackage, true /* enabled */,
+ true /* valid */, new Signature[]{validSignature}));
+
+ mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+
+
+ checkPreparationPhasesForPackage(validPackage, 1 /* first preparation for this package */);
+
+ WebViewProviderInfo[] validPackages = mWebViewUpdateServiceImpl.getValidWebViewPackages();
+ assertEquals(1, validPackages.length);
+ assertEquals(validPackage, validPackages[0].packageName);
+ }
+
+ public void testFailWaitingForRelro() {
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo("packagename", "", true, true, null)};
+ setupWithPackages(packages);
+ setEnabledAndValidPackageInfos(packages);
+
+ mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+
+ Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
+ Mockito.argThat(new IsPackageInfoWithName(packages[0].packageName)));
+
+ // Never call notifyRelroCreation()
+
+ WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
+ assertEquals(WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO, response.status);
+ }
+
+ public void testFailListingEmptyWebviewPackages() {
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[0];
+ setupWithPackages(packages);
+ setEnabledAndValidPackageInfos(packages);
+
+ mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+
+ Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged(
+ Matchers.anyObject());
+
+ WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
+ assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
+ }
+
+ public void testFailListingInvalidWebviewPackage() {
+ WebViewProviderInfo wpi = new WebViewProviderInfo("package", "", true, true, null);
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {wpi};
+ setupWithPackages(packages);
+ mTestSystemImpl.setPackageInfo(
+ createPackageInfo(wpi.packageName, true /* enabled */, false /* valid */));
+
+ mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+
+ Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged(
+ Matchers.anyObject());
+
+ WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
+ assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
+
+ // Verify that we can recover from failing to list webview packages.
+ mTestSystemImpl.setPackageInfo(
+ createPackageInfo(wpi.packageName, true /* enabled */, true /* valid */));
+ mWebViewUpdateServiceImpl.packageStateChanged(wpi.packageName,
+ WebViewUpdateService.PACKAGE_ADDED_REPLACED);
+
+ checkPreparationPhasesForPackage(wpi.packageName, 1);
+ }
+
+ // Test that switching provider using changeProviderAndSetting works.
+ public void testSwitchingProvider() {
+ String firstPackage = "first";
+ String secondPackage = "second";
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(firstPackage, "", true, false, null),
+ new WebViewProviderInfo(secondPackage, "", true, false, null)};
+ checkSwitchingProvider(packages, firstPackage, secondPackage);
+ }
+
+ public void testSwitchingProviderToNonDefault() {
+ String defaultPackage = "defaultPackage";
+ String nonDefaultPackage = "nonDefaultPackage";
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(defaultPackage, "", true, false, null),
+ new WebViewProviderInfo(nonDefaultPackage, "", false, false, null)};
+ checkSwitchingProvider(packages, defaultPackage, nonDefaultPackage);
+ }
+
+ private void checkSwitchingProvider(WebViewProviderInfo[] packages, String initialPackage,
+ String finalPackage) {
+ checkCertainPackageUsedAfterWebViewBootPreparation(initialPackage, packages);
+
+ mWebViewUpdateServiceImpl.changeProviderAndSetting(finalPackage);
+ checkPreparationPhasesForPackage(finalPackage, 1 /* first preparation for this package */);
+
+ Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(initialPackage));
+ }
+
+ // Change provider during relro creation by using changeProviderAndSetting
+ public void testSwitchingProviderDuringRelroCreation() {
+ checkChangingProviderDuringRelroCreation(true);
+ }
+
+ // Change provider during relro creation by enabling a provider
+ public void testChangingProviderThroughEnablingDuringRelroCreation() {
+ checkChangingProviderDuringRelroCreation(false);
+ }
+
+ private void checkChangingProviderDuringRelroCreation(boolean settingsChange) {
+ String firstPackage = "first";
+ String secondPackage = "second";
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(firstPackage, "", true, false, null),
+ new WebViewProviderInfo(secondPackage, "", true, false, null)};
+ setupWithPackages(packages);
+ if (settingsChange) {
+ // Have all packages be enabled, so that we can change provider however we want to
+ setEnabledAndValidPackageInfos(packages);
+ } else {
+ // Have all packages be disabled so that we can change one to enabled later
+ for(WebViewProviderInfo wpi : packages) {
+ mTestSystemImpl.setPackageInfo(createPackageInfo(wpi.packageName,
+ false /* enabled */, true /* valid */));
+ }
+ }
+
+ CountDownLatch countdown = new CountDownLatch(1);
+
+ mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+
+ Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
+ Mockito.argThat(new IsPackageInfoWithName(firstPackage)));
+
+ assertEquals(firstPackage, mWebViewUpdateServiceImpl.getCurrentWebViewPackageName());
+
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ WebViewProviderResponse threadResponse =
+ mWebViewUpdateServiceImpl.waitForAndGetProvider();
+ assertEquals(WebViewFactory.LIBLOAD_SUCCESS, threadResponse.status);
+ assertEquals(secondPackage, threadResponse.packageInfo.packageName);
+ // Verify that we killed the first package
+ Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(firstPackage));
+ countdown.countDown();
+ }
+ }).start();
+ try {
+ Thread.sleep(1000); // Let the new thread run / be blocked
+ } catch (InterruptedException e) {
+ }
+
+ if (settingsChange) {
+ mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
+ } else {
+ // Switch provider by enabling the second one
+ mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
+ true /* valid */));
+ mWebViewUpdateServiceImpl.packageStateChanged(
+ secondPackage, WebViewUpdateService.PACKAGE_CHANGED);
+ }
+ mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
+ // first package done, should start on second
+
+ Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
+ Mockito.argThat(new IsPackageInfoWithName(secondPackage)));
+
+ mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
+ // second package done, the other thread should now be unblocked
+ try {
+ countdown.await();
+ } catch (InterruptedException e) {
+ }
+ }
+
+ public void testRunFallbackLogicIfEnabled() {
+ checkFallbackLogicBeingRun(true);
+ }
+
+ public void testDontRunFallbackLogicIfDisabled() {
+ checkFallbackLogicBeingRun(false);
+ }
+
+ private void checkFallbackLogicBeingRun(boolean fallbackLogicEnabled) {
+ String primaryPackage = "primary";
+ String fallbackPackage = "fallback";
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(
+ primaryPackage, "", true /* default available */, false /* fallback */, null),
+ new WebViewProviderInfo(
+ fallbackPackage, "", true /* default available */, true /* fallback */, null)};
+ setupWithPackages(packages, fallbackLogicEnabled);
+ setEnabledAndValidPackageInfos(packages);
+
+ mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+ // Verify that we disable the fallback package if fallback logic enabled, and don't disable
+ // the fallback package if that logic is disabled
+ if (fallbackLogicEnabled) {
+ Mockito.verify(mTestSystemImpl).uninstallAndDisablePackageForAllUsers(
+ Matchers.anyObject(), Mockito.eq(fallbackPackage));
+ } else {
+ Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers(
+ Matchers.anyObject(), Matchers.anyObject());
+ }
+ Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
+ Mockito.argThat(new IsPackageInfoWithName(primaryPackage)));
+
+ // Enable fallback package
+ mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */,
+ true /* valid */));
+ mWebViewUpdateServiceImpl.packageStateChanged(
+ fallbackPackage, WebViewUpdateService.PACKAGE_CHANGED);
+
+ if (fallbackLogicEnabled) {
+ // Check that we have now disabled the fallback package twice
+ Mockito.verify(mTestSystemImpl, Mockito.times(2)).uninstallAndDisablePackageForAllUsers(
+ Matchers.anyObject(), Mockito.eq(fallbackPackage));
+ } else {
+ // Check that we still haven't disabled any package
+ Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers(
+ Matchers.anyObject(), Matchers.anyObject());
+ }
+ }
+
+ /**
+ * Scenario for installing primary package when fallback enabled.
+ * 1. Start with only fallback installed
+ * 2. Install non-fallback
+ * 3. Fallback should be disabled
+ */
+ public void testInstallingNonFallbackPackage() {
+ String primaryPackage = "primary";
+ String fallbackPackage = "fallback";
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(
+ primaryPackage, "", true /* default available */, false /* fallback */, null),
+ new WebViewProviderInfo(
+ fallbackPackage, "", true /* default available */, true /* fallback */, null)};
+ setupWithPackages(packages, true /* isFallbackLogicEnabled */);
+ mTestSystemImpl.setPackageInfo(
+ createPackageInfo(fallbackPackage, true /* enabled */ , true /* valid */));
+
+ mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+ Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers(
+ Matchers.anyObject(), Matchers.anyObject());
+
+ checkPreparationPhasesForPackage(fallbackPackage,
+ 1 /* first preparation for this package*/);
+
+ // Install primary package
+ mTestSystemImpl.setPackageInfo(
+ createPackageInfo(primaryPackage, true /* enabled */ , true /* valid */));
+ mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
+ WebViewUpdateService.PACKAGE_ADDED_REPLACED);
+
+ // Verify fallback disabled, primary package used as provider, and fallback package killed
+ Mockito.verify(mTestSystemImpl).uninstallAndDisablePackageForAllUsers(
+ Matchers.anyObject(), Mockito.eq(fallbackPackage));
+ checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation for this package*/);
+ Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(fallbackPackage));
+ }
+
+ public void testFallbackChangesEnabledState() {
+ String primaryPackage = "primary";
+ String fallbackPackage = "fallback";
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(
+ primaryPackage, "", true /* default available */, false /* fallback */, null),
+ new WebViewProviderInfo(
+ fallbackPackage, "", true /* default available */, true /* fallback */, null)};
+ setupWithPackages(packages, true /* fallbackLogicEnabled */);
+ setEnabledAndValidPackageInfos(packages);
+
+ mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+
+ // Verify fallback disabled at boot when primary package enabled
+ Mockito.verify(mTestSystemImpl).enablePackageForUser(
+ Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */,
+ Matchers.anyInt());
+
+ checkPreparationPhasesForPackage(primaryPackage, 1);
+
+ // Disable primary package and ensure fallback becomes enabled and used
+ mTestSystemImpl.setPackageInfo(
+ createPackageInfo(primaryPackage, false /* enabled */, true /* valid */));
+ mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
+ WebViewUpdateService.PACKAGE_CHANGED);
+
+ Mockito.verify(mTestSystemImpl).enablePackageForUser(
+ Mockito.eq(fallbackPackage), Mockito.eq(true) /* enable */,
+ Matchers.anyInt());
+
+ checkPreparationPhasesForPackage(fallbackPackage, 1);
+
+
+ // Again enable primary package and verify primary is used and fallback becomes disabled
+ mTestSystemImpl.setPackageInfo(
+ createPackageInfo(primaryPackage, true /* enabled */, true /* valid */));
+ mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
+ WebViewUpdateService.PACKAGE_CHANGED);
+
+ // Verify fallback is disabled a second time when primary package becomes enabled
+ Mockito.verify(mTestSystemImpl, Mockito.times(2)).enablePackageForUser(
+ Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */,
+ Matchers.anyInt());
+
+ checkPreparationPhasesForPackage(primaryPackage, 2);
+ }
+
+ public void testAddUserWhenFallbackLogicEnabled() {
+ checkAddingNewUser(true);
+ }
+
+ public void testAddUserWhenFallbackLogicDisabled() {
+ checkAddingNewUser(false);
+ }
+
+ public void checkAddingNewUser(boolean fallbackLogicEnabled) {
+ String primaryPackage = "primary";
+ String fallbackPackage = "fallback";
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(
+ primaryPackage, "", true /* default available */, false /* fallback */, null),
+ new WebViewProviderInfo(
+ fallbackPackage, "", true /* default available */, true /* fallback */, null)};
+ setupWithPackages(packages, fallbackLogicEnabled);
+ setEnabledAndValidPackageInfos(packages);
+ int newUser = 100;
+ mWebViewUpdateServiceImpl.handleNewUser(newUser);
+ if (fallbackLogicEnabled) {
+ // Verify fallback package becomes disabled for new user
+ Mockito.verify(mTestSystemImpl).enablePackageForUser(
+ Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */,
+ Mockito.eq(newUser));
+ } else {
+ // Verify that we don't disable fallback for new user
+ Mockito.verify(mTestSystemImpl, Mockito.never()).enablePackageForUser(
+ Mockito.anyObject(), Matchers.anyBoolean() /* enable */,
+ Matchers.anyInt() /* user */);
+ }
+ }
+
+ /**
+ * Timing dependent test where we verify that the list of valid webview packages becoming empty
+ * at a certain point doesn't crash us or break our state.
+ */
+ public void testNotifyRelroDoesntCrashIfNoPackages() {
+ String firstPackage = "first";
+ String secondPackage = "second";
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(firstPackage, "", true /* default available */,
+ false /* fallback */, null),
+ new WebViewProviderInfo(secondPackage, "", true /* default available */,
+ false /* fallback */, null)};
+ setupWithPackages(packages);
+ // Add (enabled and valid) package infos for each provider
+ setEnabledAndValidPackageInfos(packages);
+
+ mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+
+ Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
+ Mockito.argThat(new IsPackageInfoWithName(firstPackage)));
+
+ // Change provider during relro creation to enter a state where we are
+ // waiting for relro creation to complete just to re-run relro creation.
+ // (so that in next notifyRelroCreationCompleted() call we have to list webview packages)
+ mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
+
+ // Make packages invalid to cause exception to be thrown
+ mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */,
+ false /* valid */));
+ mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
+ false /* valid */));
+
+ // This shouldn't throw an exception!
+ mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
+
+ WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
+ assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
+
+ // Now make a package valid again and verify that we can switch back to that
+ mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */,
+ true /* valid */));
+
+ mWebViewUpdateServiceImpl.packageStateChanged(firstPackage,
+ WebViewUpdateService.PACKAGE_ADDED_REPLACED);
+
+ // Ensure we use firstPackage
+ checkPreparationPhasesForPackage(firstPackage, 2 /* second preparation for this package */);
+ }
+
+ /**
+ * Verify that even if a user-chosen package is removed temporarily we start using it again when
+ * it is added back.
+ */
+ public void testTempRemovePackageDoesntSwitchProviderPermanently() {
+ String firstPackage = "first";
+ String secondPackage = "second";
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(firstPackage, "", true /* default available */,
+ false /* fallback */, null),
+ new WebViewProviderInfo(secondPackage, "", true /* default available */,
+ false /* fallback */, null)};
+ checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages);
+
+ // Explicitly use the second package
+ mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
+ checkPreparationPhasesForPackage(secondPackage, 1 /* first time for this package */);
+
+ // Remove second package (invalidate it) and verify that first package is used
+ mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
+ false /* valid */));
+ mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
+ WebViewUpdateService.PACKAGE_ADDED);
+ checkPreparationPhasesForPackage(firstPackage, 2 /* second time for this package */);
+
+ // Now make the second package valid again and verify that it is used again
+ mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
+ true /* valid */));
+ mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
+ WebViewUpdateService.PACKAGE_ADDED);
+ checkPreparationPhasesForPackage(secondPackage, 2 /* second time for this package */);
+ }
+
+ /**
+ * Ensure that we update the user-chosen setting across boots if the chosen package is no
+ * longer installed and valid.
+ */
+ public void testProviderSettingChangedDuringBootIfProviderNotAvailable() {
+ String chosenPackage = "chosenPackage";
+ String nonChosenPackage = "non-chosenPackage";
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(chosenPackage, "", true /* default available */,
+ false /* fallback */, null),
+ new WebViewProviderInfo(nonChosenPackage, "", true /* default available */,
+ false /* fallback */, null)};
+
+ setupWithPackages(packages);
+ // Only 'install' nonChosenPackage
+ mTestSystemImpl.setPackageInfo(
+ createPackageInfo(nonChosenPackage, true /* enabled */, true /* valid */));
+
+ // Set user-chosen package
+ mTestSystemImpl.updateUserSetting(null, chosenPackage);
+
+ mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+
+ // Verify that we switch the setting to point to the current package
+ Mockito.verify(mTestSystemImpl).updateUserSetting(
+ Mockito.anyObject(), Mockito.eq(nonChosenPackage));
+ assertEquals(nonChosenPackage, mTestSystemImpl.getUserChosenWebViewProvider(null));
+
+ checkPreparationPhasesForPackage(nonChosenPackage, 1);
+ }
+
+ public void testRecoverFailedListingWebViewPackagesSettingsChange() {
+ checkRecoverAfterFailListingWebviewPackages(true);
+ }
+
+ public void testRecoverFailedListingWebViewPackagesAddedPackage() {
+ checkRecoverAfterFailListingWebviewPackages(false);
+ }
+
+ /**
+ * Test that we can recover correctly from failing to list WebView packages.
+ * settingsChange: whether to fail during changeProviderAndSetting or packageStateChanged
+ */
+ public void checkRecoverAfterFailListingWebviewPackages(boolean settingsChange) {
+ String firstPackage = "first";
+ String secondPackage = "second";
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(firstPackage, "", true /* default available */,
+ false /* fallback */, null),
+ new WebViewProviderInfo(secondPackage, "", true /* default available */,
+ false /* fallback */, null)};
+ checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages);
+
+ // Make both packages invalid so that we fail listing WebView packages
+ mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */,
+ false /* valid */));
+ mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
+ false /* valid */));
+
+ // Change package to hit the webview packages listing problem.
+ if (settingsChange) {
+ mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
+ } else {
+ mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
+ WebViewUpdateService.PACKAGE_ADDED_REPLACED);
+ }
+
+ WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
+ assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
+
+ // Make second package valid and verify that we can load it again
+ mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
+ true /* valid */));
+
+ mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
+ WebViewUpdateService.PACKAGE_ADDED_REPLACED);
+
+
+ checkPreparationPhasesForPackage(secondPackage, 1);
+ }
+
+ public void testDontKillIfPackageReplaced() {
+ checkDontKillIfPackageRemoved(true);
+ }
+
+ public void testDontKillIfPackageRemoved() {
+ checkDontKillIfPackageRemoved(false);
+ }
+
+ public void checkDontKillIfPackageRemoved(boolean replaced) {
+ String firstPackage = "first";
+ String secondPackage = "second";
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(firstPackage, "", true /* default available */,
+ false /* fallback */, null),
+ new WebViewProviderInfo(secondPackage, "", true /* default available */,
+ false /* fallback */, null)};
+ checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages);
+
+ // Replace or remove the current webview package
+ if (replaced) {
+ mTestSystemImpl.setPackageInfo(
+ createPackageInfo(firstPackage, true /* enabled */, false /* valid */));
+ mWebViewUpdateServiceImpl.packageStateChanged(firstPackage,
+ WebViewUpdateService.PACKAGE_ADDED_REPLACED);
+ } else {
+ mTestSystemImpl.removePackageInfo(firstPackage);
+ mWebViewUpdateServiceImpl.packageStateChanged(firstPackage,
+ WebViewUpdateService.PACKAGE_REMOVED);
+ }
+
+ checkPreparationPhasesForPackage(secondPackage, 1);
+
+ Mockito.verify(mTestSystemImpl, Mockito.never()).killPackageDependents(
+ Mockito.anyObject());
+ }
+
+ public void testKillIfSettingChanged() {
+ String firstPackage = "first";
+ String secondPackage = "second";
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(firstPackage, "", true /* default available */,
+ false /* fallback */, null),
+ new WebViewProviderInfo(secondPackage, "", true /* default available */,
+ false /* fallback */, null)};
+ checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages);
+
+ mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
+
+ checkPreparationPhasesForPackage(secondPackage, 1);
+
+ Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(firstPackage));
+ }
+
+ /**
+ * Test that we kill apps using an old provider when we change the provider setting, even if the
+ * new provider is not the one we intended to change to.
+ */
+ public void testKillIfChangeProviderIncorrectly() {
+ String firstPackage = "first";
+ String secondPackage = "second";
+ String thirdPackage = "third";
+ WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+ new WebViewProviderInfo(firstPackage, "", true /* default available */,
+ false /* fallback */, null),
+ new WebViewProviderInfo(secondPackage, "", true /* default available */,
+ false /* fallback */, null),
+ new WebViewProviderInfo(thirdPackage, "", true /* default available */,
+ false /* fallback */, null)};
+ setupWithPackages(packages);
+ setEnabledAndValidPackageInfos(packages);
+
+ // Start with the setting pointing to the third package
+ mTestSystemImpl.updateUserSetting(null, thirdPackage);
+
+ mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+ checkPreparationPhasesForPackage(thirdPackage, 1);
+
+ mTestSystemImpl.setPackageInfo(
+ createPackageInfo(secondPackage, true /* enabled */, false /* valid */));
+
+ // Try to switch to the invalid second package, this should result in switching to the first
+ // package, since that is more preferred than the third one.
+ assertEquals(firstPackage,
+ mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage));
+
+ checkPreparationPhasesForPackage(firstPackage, 1);
+
+ Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(thirdPackage));
+ }
+}
diff --git a/services/tests/shortcutmanagerutils/Android.mk b/services/tests/shortcutmanagerutils/Android.mk
new file mode 100644
index 0000000..701e058
--- /dev/null
+++ b/services/tests/shortcutmanagerutils/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ mockito-target
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := ShortcutManagerTestUtils
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
new file mode 100644
index 0000000..d09b62c
--- /dev/null
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -0,0 +1,506 @@
+/*
+ * 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.pm.shortcutmanagertest;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyList;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.pm.LauncherApps;
+import android.content.pm.ShortcutInfo;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.BaseBundle;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
+import android.test.MoreAsserts;
+import android.util.Log;
+
+import junit.framework.Assert;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.mockito.Mockito;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.BooleanSupplier;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+public class ShortcutManagerTestUtils {
+ private static final String TAG = "ShortcutManagerUtils";
+
+ private static final boolean ENABLE_DUMPSYS = true; // DO NOT SUBMIT WITH true
+
+ private static final int STANDARD_TIMEOUT_SEC = 5;
+
+ private ShortcutManagerTestUtils() {
+ }
+
+ private static List<String> readAll(ParcelFileDescriptor pfd) {
+ try {
+ try {
+ final ArrayList<String> ret = new ArrayList<>();
+ try (BufferedReader r = new BufferedReader(
+ new FileReader(pfd.getFileDescriptor()))) {
+ String line;
+ while ((line = r.readLine()) != null) {
+ ret.add(line);
+ }
+ r.readLine();
+ }
+ return ret;
+ } finally {
+ pfd.close();
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static String concatResult(List<String> result) {
+ final StringBuilder sb = new StringBuilder();
+ for (String s : result) {
+ sb.append(s);
+ sb.append("\n");
+ }
+ return sb.toString();
+ }
+
+ private static List<String> runCommand(Instrumentation instrumentation, String command) {
+ return runCommand(instrumentation, command, null);
+ }
+ private static List<String> runCommand(Instrumentation instrumentation, String command,
+ Predicate<List<String>> resultAsserter) {
+ Log.d(TAG, "Running command: " + command);
+ final List<String> result;
+ try {
+ result = readAll(
+ instrumentation.getUiAutomation().executeShellCommand(command));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ if (resultAsserter != null && !resultAsserter.test(result)) {
+ fail("Command '" + command + "' failed, output was:\n" + concatResult(result));
+ }
+ return result;
+ }
+
+ private static void runCommandForNoOutput(Instrumentation instrumentation, String command) {
+ runCommand(instrumentation, command, result -> result.size() == 0);
+ }
+
+ private static List<String> runShortcutCommand(Instrumentation instrumentation, String command,
+ Predicate<List<String>> resultAsserter) {
+ return runCommand(instrumentation, "cmd shortcut " + command, resultAsserter);
+ }
+
+ public static List<String> runShortcutCommandForSuccess(Instrumentation instrumentation,
+ String command) {
+ return runShortcutCommand(instrumentation, command, result -> result.contains("Success"));
+ }
+
+ public static String getDefaultLauncher(Instrumentation instrumentation) {
+ final String PREFIX = "Launcher: ComponentInfo{";
+ final String POSTFIX = "}";
+ final List<String> result = runShortcutCommandForSuccess(
+ instrumentation, "get-default-launcher");
+ for (String s : result) {
+ if (s.startsWith(PREFIX) && s.endsWith(POSTFIX)) {
+ return s.substring(PREFIX.length(), s.length() - POSTFIX.length());
+ }
+ }
+ fail("Default launcher not found");
+ return null;
+ }
+
+ public static void setDefaultLauncher(Instrumentation instrumentation, String component) {
+ runCommandForNoOutput(instrumentation, "cmd package set-home-activity " + component);
+ }
+
+ public static void setDefaultLauncher(Instrumentation instrumentation, Context packageContext) {
+ setDefaultLauncher(instrumentation, packageContext.getPackageName()
+ + "/android.content.pm.cts.shortcutmanager.packages.Launcher");
+ }
+
+ public static void overrideConfig(Instrumentation instrumentation, String config) {
+ runShortcutCommandForSuccess(instrumentation, "override-config " + config);
+ }
+
+ public static void resetConfig(Instrumentation instrumentation) {
+ runShortcutCommandForSuccess(instrumentation, "reset-config");
+ }
+
+ public static void resetThrottling(Instrumentation instrumentation) {
+ runShortcutCommandForSuccess(instrumentation, "reset-throttling");
+ }
+
+ public static void resetAllThrottling(Instrumentation instrumentation) {
+ runShortcutCommandForSuccess(instrumentation, "reset-all-throttling");
+ }
+
+ public static void clearShortcuts(Instrumentation instrumentation, int userId,
+ String packageName) {
+ runShortcutCommandForSuccess(instrumentation, "clear-shortcuts "
+ + " --user " + userId + " " + packageName);
+ }
+
+ public static void dumpsysShortcut(Instrumentation instrumentation) {
+ if (!ENABLE_DUMPSYS) {
+ return;
+ }
+ for (String s : runCommand(instrumentation, "dumpsys shortcut")) {
+ Log.e(TAG, s);
+ }
+ }
+
+ public static Bundle makeBundle(Object... keysAndValues) {
+ assertTrue((keysAndValues.length % 2) == 0);
+
+ if (keysAndValues.length == 0) {
+ return null;
+ }
+ final Bundle ret = new Bundle();
+
+ for (int i = keysAndValues.length - 2; i >= 0; i -= 2) {
+ final String key = keysAndValues[i].toString();
+ final Object value = keysAndValues[i + 1];
+
+ if (value == null) {
+ ret.putString(key, null);
+ } else if (value instanceof Integer) {
+ ret.putInt(key, (Integer) value);
+ } else if (value instanceof String) {
+ ret.putString(key, (String) value);
+ } else if (value instanceof Bundle) {
+ ret.putBundle(key, (Bundle) value);
+ } else {
+ fail("Type not supported yet: " + value.getClass().getName());
+ }
+ }
+ return ret;
+ }
+
+ public static <T> List<T> list(T... array) {
+ return Arrays.asList(array);
+ }
+
+ public static <T> Set<T> hashSet(Set<T> in) {
+ return new HashSet<T>(in);
+ }
+
+ public static <T> Set<T> set(T... values) {
+ return set(v -> v, values);
+ }
+
+ public static <T, V> Set<T> set(Function<V, T> converter, V... values) {
+ return set(converter, Arrays.asList(values));
+ }
+
+ public static <T, V> Set<T> set(Function<V, T> converter, List<V> values) {
+ final HashSet<T> ret = new HashSet<>();
+ for (V v : values) {
+ ret.add(converter.apply(v));
+ }
+ return ret;
+ }
+
+ public static void resetAll(Collection<?> mocks) {
+ for (Object o : mocks) {
+ reset(o);
+ }
+ }
+ public static void assertExpectException(Class<? extends Throwable> expectedExceptionType,
+ String expectedExceptionMessageRegex, Runnable r) {
+ assertExpectException("", expectedExceptionType, expectedExceptionMessageRegex, r);
+ }
+
+ public static void assertDynamicShortcutCountExceeded(Runnable r) {
+ assertExpectException(IllegalArgumentException.class,
+ "Max number of dynamic shortcuts exceeded", r);
+ }
+
+ public static void assertExpectException(String message,
+ Class<? extends Throwable> expectedExceptionType,
+ String expectedExceptionMessageRegex, Runnable r) {
+ try {
+ r.run();
+ Assert.fail("Expected exception type " + expectedExceptionType.getName()
+ + " was not thrown (message=" + message + ")");
+ } catch (Throwable e) {
+ Assert.assertTrue(
+ "Expected exception type was " + expectedExceptionType.getName()
+ + " but caught " + e + " (message=" + message + ")",
+ expectedExceptionType.isAssignableFrom(e.getClass()));
+ if (expectedExceptionMessageRegex != null) {
+ MoreAsserts.assertContainsRegex(expectedExceptionMessageRegex, e.getMessage());
+ }
+ }
+ }
+
+ public static List<ShortcutInfo> assertShortcutIds(List<ShortcutInfo> actualShortcuts,
+ String... expectedIds) {
+ final HashSet<String> expected = new HashSet<>(list(expectedIds));
+ final HashSet<String> actual = new HashSet<>();
+ for (ShortcutInfo s : actualShortcuts) {
+ actual.add(s.getId());
+ }
+
+ // Compare the sets.
+ assertEquals(expected, actual);
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllHaveIntents(
+ List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertNotNull("ID " + s.getId(), s.getIntent());
+ }
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllNotHaveIntents(
+ List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertNull("ID " + s.getId(), s.getIntent());
+ }
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllHaveTitle(
+ List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertNotNull("ID " + s.getId(), s.getTitle());
+ }
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllNotHaveTitle(
+ List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertNull("ID " + s.getId(), s.getTitle());
+ }
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllHaveIconResId(
+ List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertTrue("ID " + s.getId() + " not have icon res ID", s.hasIconResource());
+ assertFalse("ID " + s.getId() + " shouldn't have icon FD", s.hasIconFile());
+ }
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllHaveIconFile(
+ List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertFalse("ID " + s.getId() + " shouldn't have icon res ID", s.hasIconResource());
+ assertTrue("ID " + s.getId() + " not have icon FD", s.hasIconFile());
+ }
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllHaveIcon(
+ List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertTrue("ID " + s.getId() + " has no icon ", s.hasIconFile() || s.hasIconResource());
+ }
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllKeyFieldsOnly(
+ List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertTrue("ID " + s.getId(), s.hasKeyFieldsOnly());
+ }
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllNotKeyFieldsOnly(
+ List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertFalse("ID " + s.getId(), s.hasKeyFieldsOnly());
+ }
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllDynamic(List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertTrue("ID " + s.getId(), s.isDynamic());
+ }
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllPinned(List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertTrue("ID " + s.getId(), s.isPinned());
+ }
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllDynamicOrPinned(
+ List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertTrue("ID " + s.getId(), s.isDynamic() || s.isPinned());
+ }
+ return actualShortcuts;
+ }
+
+ public static void assertDynamicOnly(ShortcutInfo si) {
+ assertTrue(si.isDynamic());
+ assertFalse(si.isPinned());
+ }
+
+ public static void assertPinnedOnly(ShortcutInfo si) {
+ assertFalse(si.isDynamic());
+ assertTrue(si.isPinned());
+ }
+
+ public static void assertDynamicAndPinned(ShortcutInfo si) {
+ assertTrue(si.isDynamic());
+ assertTrue(si.isPinned());
+ }
+
+ public static void assertBitmapSize(int expectedWidth, int expectedHeight, Bitmap bitmap) {
+ assertEquals("width", expectedWidth, bitmap.getWidth());
+ assertEquals("height", expectedHeight, bitmap.getHeight());
+ }
+
+ public static <T> void assertAllUnique(Collection<T> list) {
+ final Set<Object> set = new HashSet<>();
+ for (T item : list) {
+ if (set.contains(item)) {
+ fail("Duplicate item found: " + item + " (in the list: " + list + ")");
+ }
+ set.add(item);
+ }
+ }
+
+ public static Bitmap pfdToBitmap(ParcelFileDescriptor pfd) {
+ assertNotNull(pfd);
+ try {
+ try {
+ return BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
+ } finally {
+ pfd.close();
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void assertBundleEmpty(BaseBundle b) {
+ assertTrue(b == null || b.size() == 0);
+ }
+
+ public static void assertCallbackNotReceived(LauncherApps.Callback mock) {
+ verify(mock, times(0)).onShortcutsChanged(anyString(), anyList(),
+ any(UserHandle.class));
+ }
+
+ public static void assertCallbackReceived(LauncherApps.Callback mock,
+ UserHandle user, String packageName, String... ids) {
+ verify(mock).onShortcutsChanged(eq(packageName), checkShortcutIds(ids),
+ eq(user));
+ }
+
+ public static boolean checkAssertSuccess(Runnable r) {
+ try {
+ r.run();
+ return true;
+ } catch (AssertionError e) {
+ return false;
+ }
+ }
+
+ public static <T> T checkArgument(Predicate<T> checker, String description,
+ List<T> matchedCaptor) {
+ final Matcher<T> m = new BaseMatcher<T>() {
+ @Override
+ public boolean matches(Object item) {
+ if (item == null) {
+ return false;
+ }
+ final T value = (T) item;
+ if (!checker.test(value)) {
+ return false;
+ }
+
+ if (matchedCaptor != null) {
+ matchedCaptor.add(value);
+ }
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description d) {
+ d.appendText(description);
+ }
+ };
+ return Mockito.argThat(m);
+ }
+
+ public static List<ShortcutInfo> checkShortcutIds(String... ids) {
+ return checkArgument((List<ShortcutInfo> list) -> {
+ final Set<String> actualSet = set(si -> si.getId(), list);
+ return actualSet.equals(set(ids));
+
+ }, "Shortcut IDs=[" + Arrays.toString(ids) + "]", null);
+ }
+
+ public static void waitUntil(String message, BooleanSupplier condition) {
+ waitUntil(message, condition, STANDARD_TIMEOUT_SEC);
+ }
+
+ public static void waitUntil(String message, BooleanSupplier condition, int timeoutSeconds) {
+ final long timeout = System.currentTimeMillis() + (timeoutSeconds * 1000L);
+ while (System.currentTimeMillis() < timeout) {
+ if (condition.getAsBoolean()) {
+ return;
+ }
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ fail("Timed out for: " + message);
+ }
+}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 0aeb96f..ecfeff9 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -152,6 +152,7 @@
private ArrayList<UsageStatsManagerInternal.AppIdleStateChangeListener>
mPackageAccessListeners = new ArrayList<>();
+ private boolean mHaveCarrierPrivilegedApps;
private List<String> mCarrierPrivilegedApps;
public UsageStatsService(Context context) {
@@ -931,11 +932,14 @@
private boolean isCarrierApp(String packageName) {
synchronized (mLock) {
- if (mCarrierPrivilegedApps == null) {
+ if (!mHaveCarrierPrivilegedApps) {
fetchCarrierPrivilegedAppsLocked();
}
+ if (mCarrierPrivilegedApps != null) {
+ return mCarrierPrivilegedApps.contains(packageName);
+ }
+ return false;
}
- return mCarrierPrivilegedApps.contains(packageName);
}
void clearCarrierPrivilegedApps() {
@@ -943,6 +947,7 @@
Slog.i(TAG, "Clearing carrier privileged apps list");
}
synchronized (mLock) {
+ mHaveCarrierPrivilegedApps = false;
mCarrierPrivilegedApps = null; // Need to be refetched.
}
}
@@ -951,6 +956,7 @@
TelephonyManager telephonyManager =
getContext().getSystemService(TelephonyManager.class);
mCarrierPrivilegedApps = telephonyManager.getPackagesWithCarrierPrivileges();
+ mHaveCarrierPrivilegedApps = true;
if (DEBUG) {
Slog.d(TAG, "apps with carrier privilege " + mCarrierPrivilegedApps);
}
@@ -1024,7 +1030,8 @@
}
pw.println();
- pw.println("Carrier privileged apps: " + mCarrierPrivilegedApps);
+ pw.println("Carrier privileged apps (have=" + mHaveCarrierPrivilegedApps
+ + "): " + mCarrierPrivilegedApps);
pw.println();
pw.println("Settings:");
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index f13e019..53377f9 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -84,22 +84,15 @@
private final PhoneStateListener mPhoneStateListener;
private final PowerManager mPowerManager;
- // The SoundTriggerManager layer handles multiple generic recognition models. We store the
- // ModelData here in a hashmap.
- private final HashMap<UUID, ModelData> mGenericModelDataMap;
+ // The SoundTriggerManager layer handles multiple recognition models of type generic and
+ // keyphrase. We store the ModelData here in a hashmap.
+ private final HashMap<UUID, ModelData> mModelDataMap;
- // 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;
+ // An index of keyphrase sound models so that we can reach them easily. We support indexing
+ // keyphrase sound models with a keyphrase ID. Sound model with the same keyphrase ID will
+ // replace an existing model, thus there is a 1:1 mapping from keyphrase ID to a voice
+ // sound model.
+ private HashMap<Integer, UUID> mKeyphraseUuidMap;
private boolean mCallActive = false;
private boolean mIsPowerSaveMode = false;
@@ -119,7 +112,8 @@
mContext = context;
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- mGenericModelDataMap = new HashMap<UUID, ModelData>();
+ mModelDataMap = new HashMap<UUID, ModelData>();
+ mKeyphraseUuidMap = new HashMap<Integer, UUID>();
mPhoneStateListener = new MyCallStateListener();
if (status != SoundTrigger.STATUS_OK || modules.size() == 0) {
Slog.w(TAG, "listModules status=" + status + ", # of modules=" + modules.size());
@@ -153,6 +147,10 @@
synchronized (mLock) {
ModelData modelData = getOrCreateGenericModelDataLocked(modelId);
+ if (modelData == null) {
+ Slog.w(TAG, "Irrecoverable error occurred, check UUID / sound model data.");
+ return STATUS_ERROR;
+ }
return startRecognition(soundModel, modelData, callback, recognitionConfig,
INVALID_VALUE /* keyphraseId */);
}
@@ -180,20 +178,48 @@
+ " 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.");
+ dumpModelStateLocked();
+ }
+
+ ModelData model = getKeyphraseModelDataLocked(keyphraseId);
+ if (model != null && !model.isKeyphraseModel()) {
+ Slog.e(TAG, "Generic model with same UUID exists.");
+ return STATUS_ERROR;
+ }
+
+ // Process existing model first.
+ if (model != null && model.getModelId() != soundModel.uuid) {
+ // The existing model has a different UUID, should be replaced.
+ int status = cleanUpExistingKeyphraseModel(model);
+ removeKeyphraseModelLocked(keyphraseId);
+ if (status != STATUS_OK) {
+ return status;
}
+ model = null;
}
- if (mKeyphraseModelData == null) {
- mKeyphraseModelData = ModelData.createKeyphraseModelData(soundModel.uuid);
+
+ // We need to create a new one: either no previous models existed for given keyphrase id
+ // or the existing model had a different UUID and was cleaned up.
+ if (model == null) {
+ model = createKeyphraseModelDataLocked(soundModel.uuid, keyphraseId);
}
- return startRecognition(soundModel, mKeyphraseModelData, callback, recognitionConfig,
+
+ return startRecognition(soundModel, model, callback, recognitionConfig,
keyphraseId);
}
}
+ private int cleanUpExistingKeyphraseModel(ModelData modelData) {
+ // Stop and clean up a previous ModelData if one exists. This usually is used when the
+ // previous model has a different UUID for the same keyphrase ID.
+ int status = tryStopAndUnloadLocked(modelData, true /* stop */, true /* unload */);
+ if (status != STATUS_OK) {
+ Slog.w(TAG, "Unable to stop or unload previous model: " +
+ modelData.toString());
+ }
+ return status;
+ }
+
/**
* Starts recognition for the given sound model. A single routine for both keyphrase and
* generic sound models.
@@ -228,17 +254,15 @@
initializeTelephonyAndPowerStateListeners();
}
- // 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 the existing SoundModel is different (for the same UUID for Generic and same
+ // keyphrase ID for voice), ensure that it is unloaded and stopped before proceeding.
+ // This works for both keyphrase and generic models. This logic also ensures that a
+ // previously loaded (or started) model is appropriately stopped. Since this is a
+ // generalization of the previous logic with a single keyphrase model, we should have
+ // no regression with the previous version of this code as was given in the
+ // startKeyphrase() routine.
if (modelData.getSoundModel() != null) {
- boolean stopModel = false; // Stop the model after checking that its started.
+ boolean stopModel = false; // Stop the model after checking that it is started.
boolean unloadModel = false;
if (modelData.getSoundModel().equals(soundModel) && modelData.isModelStarted()) {
// The model has not changed, but the previous model is "started".
@@ -273,7 +297,7 @@
modelData.clearCallback();
}
- // Load the model if its not loaded.
+ // Load the model if it is not loaded.
if (!modelData.isModelLoaded()) {
// Load the model
int[] handle = new int[] { INVALID_VALUE };
@@ -291,9 +315,6 @@
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);
@@ -322,8 +343,8 @@
return STATUS_ERROR;
}
- ModelData modelData = mGenericModelDataMap.get(modelId);
- if (modelData == null) {
+ ModelData modelData = mModelDataMap.get(modelId);
+ if (modelData == null || !modelData.isGenericModel()) {
Slog.w(TAG, "Attempting stopRecognition on invalid model with id:" + modelId);
return STATUS_ERROR;
}
@@ -355,21 +376,23 @@
return STATUS_ERROR;
}
+ ModelData modelData = getKeyphraseModelDataLocked(keyphraseId);
+ if (modelData == null || !modelData.isKeyphraseModel()) {
+ Slog.e(TAG, "No model exists for given keyphrase Id.");
+ return STATUS_ERROR;
+ }
+
if (DBG) {
Slog.d(TAG, "stopRecognition for keyphraseId=" + keyphraseId + ", callback =" +
callback.asBinder());
- Slog.d(TAG, "current callback=" + (mKeyphraseModelData == null ? "null" :
- mKeyphraseModelData.getCallback().asBinder()));
+ Slog.d(TAG, "current callback=" + (modelData == null ? "null" :
+ modelData.getCallback().asBinder()));
}
- int status = stopRecognition(mKeyphraseModelData, callback);
+ int status = stopRecognition(modelData, callback);
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.
- internalClearKeyphraseStateLocked();
return status;
}
}
@@ -424,9 +447,6 @@
internalClearGlobalStateLocked();
}
- if (modelData.isKeyphraseModel()) {
- mKeyphraseId = INVALID_VALUE;
- }
return status;
}
}
@@ -475,25 +495,18 @@
return;
}
- // Stop Keyphrase recognition if one exists.
- if (mKeyphraseModelData != null && mKeyphraseModelData.getHandle() != INVALID_VALUE) {
- mKeyphraseModelData.setRequested(false);
- int status = updateRecognitionLocked(mKeyphraseModelData, isRecognitionAllowed(),
- false /* don't notify for synchronous calls */);
- internalClearKeyphraseStateLocked();
- }
-
- // Stop all generic recognition models.
- for (ModelData model : mGenericModelDataMap.values()) {
+ // Stop all recognition models.
+ for (ModelData model : mModelDataMap.values()) {
if (model.isModelStarted()) {
+ model.setRequested(false);
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.
- Slog.w(TAG, "Error stopping generic model: " + model.getHandle());
+ Slog.w(TAG, "Error stopping keyphrase model: " + model.getHandle());
}
model.clearState();
model.clearCallback();
+ model.setRecognitionConfig(null);
}
}
internalClearGlobalStateLocked();
@@ -507,24 +520,27 @@
int unloadKeyphraseSoundModel(int keyphraseId) {
synchronized (mLock) {
MetricsLogger.count(mContext, "sth_unload_keyphrase_sound_model", 1);
- if (mModule == null || mKeyphraseModelData == null ||
- mKeyphraseModelData.getHandle() == INVALID_VALUE) {
+ ModelData modelData = getKeyphraseModelDataLocked(keyphraseId);
+ if (mModule == null || modelData == null || modelData.getHandle() == INVALID_VALUE ||
+ !modelData.isKeyphraseModel()) {
return STATUS_ERROR;
}
// Stop recognition if it's the current one.
- mKeyphraseModelData.setRequested(false);
- int status = updateRecognitionLocked(mKeyphraseModelData, isRecognitionAllowed(),
+ modelData.setRequested(false);
+ int status = updateRecognitionLocked(modelData, isRecognitionAllowed(),
false /* don't notify */);
if (status != SoundTrigger.STATUS_OK) {
Slog.w(TAG, "Stop recognition failed for keyphrase ID:" + status);
}
- status = mModule.unloadSoundModel(mKeyphraseModelData.getHandle());
+ status = mModule.unloadSoundModel(modelData.getHandle());
if (status != SoundTrigger.STATUS_OK) {
Slog.w(TAG, "unloadKeyphraseSoundModel call failed with " + status);
}
- mKeyphraseModelData.clearState();
+
+ // Remove it from existence.
+ removeKeyphraseModelLocked(keyphraseId);
return status;
}
}
@@ -535,8 +551,8 @@
if (modelId == null || mModule == null) {
return STATUS_ERROR;
}
- ModelData modelData = mGenericModelDataMap.get(modelId);
- if (modelData == null) {
+ ModelData modelData = mModelDataMap.get(modelId);
+ if (modelData == null || !modelData.isGenericModel()) {
Slog.w(TAG, "Unload error: Attempting unload invalid generic model with id:" +
modelId);
return STATUS_ERROR;
@@ -559,8 +575,10 @@
Slog.w(TAG, "unloadGenericSoundModel() call failed with " + status);
Slog.w(TAG, "unloadGenericSoundModel() force-marking model as unloaded.");
}
- mGenericModelDataMap.remove(modelId);
- if (DBG) dumpGenericModelStateLocked();
+
+ // Remove it from existence.
+ mModelDataMap.remove(modelId);
+ if (DBG) dumpModelStateLocked();
return status;
}
}
@@ -612,7 +630,7 @@
return;
}
ModelData model = getModelDataForLocked(event.soundModelHandle);
- if (model == null) {
+ if (model == null || !model.isGenericModel()) {
Slog.w(TAG, "Generic recognition event: Model does not exist for handle: " +
event.soundModelHandle);
return;
@@ -723,67 +741,64 @@
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onError", e);
} finally {
- internalClearKeyphraseStateLocked();
- internalClearGenericModelStateLocked();
+ internalClearModelStateLocked();
internalClearGlobalStateLocked();
}
}
+ private int getKeyphraseIdFromEvent(KeyphraseRecognitionEvent event) {
+ if (event == null) {
+ Slog.w(TAG, "Null RecognitionEvent received.");
+ return INVALID_VALUE;
+ }
+ KeyphraseRecognitionExtra[] keyphraseExtras =
+ ((KeyphraseRecognitionEvent) event).keyphraseExtras;
+ if (keyphraseExtras == null || keyphraseExtras.length == 0) {
+ Slog.w(TAG, "Invalid keyphrase recognition event!");
+ return INVALID_VALUE;
+ }
+ // TODO: Handle more than one keyphrase extras.
+ return keyphraseExtras[0].id;
+ }
+
private void onKeyphraseRecognitionSuccessLocked(KeyphraseRecognitionEvent event) {
Slog.i(TAG, "Recognition success");
MetricsLogger.count(mContext, "sth_keyphrase_recognition_event", 1);
+ int keyphraseId = getKeyphraseIdFromEvent(event);
+ ModelData modelData = getKeyphraseModelDataLocked(keyphraseId);
- if (mKeyphraseModelData == null) {
- Slog.e(TAG, "Received onRecognition event for null keyphrase model data.");
+ if (modelData == null || !modelData.isKeyphraseModel()) {
+ Slog.e(TAG, "Keyphase model data does not exist for ID:" + keyphraseId);
return;
}
- if (mKeyphraseModelData.getCallback() == null) {
- Slog.w(TAG, "Received onRecognition event without any listener for it.");
- return;
- }
-
- KeyphraseRecognitionExtra[] keyphraseExtras =
- ((KeyphraseRecognitionEvent) event).keyphraseExtras;
- if (keyphraseExtras == null || keyphraseExtras.length == 0) {
- Slog.w(TAG, "Invalid keyphrase recognition event!");
- return;
- }
- // TODO: Handle more than one keyphrase extras.
- if (mKeyphraseId != keyphraseExtras[0].id) {
- Slog.w(TAG, "received onRecognition event for a different keyphrase");
+ if (modelData.getCallback() == null) {
+ Slog.w(TAG, "Received onRecognition event without callback for keyphrase model.");
return;
}
try {
- mKeyphraseModelData.getCallback().onKeyphraseDetected(
- (KeyphraseRecognitionEvent) event);
+ modelData.getCallback().onKeyphraseDetected((KeyphraseRecognitionEvent) event);
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onKeyphraseDetected", e);
}
- mKeyphraseModelData.setStopped();
+ modelData.setStopped();
- RecognitionConfig config = mKeyphraseModelData.getRecognitionConfig();
+ RecognitionConfig config = modelData.getRecognitionConfig();
if (config != null) {
// Whether we should continue by starting this again.
- mKeyphraseModelData.setRequested(config.allowMultipleTriggers);
+ modelData.setRequested(config.allowMultipleTriggers);
}
// TODO: Remove this block if the lower layer supports multiple triggers.
- if (mKeyphraseModelData.getRequested()) {
- updateRecognitionLocked(mKeyphraseModelData, isRecognitionAllowed(),
- true /* notify */);
+ if (modelData.getRequested()) {
+ updateRecognitionLocked(modelData, 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);
+ for (ModelData modelData : mModelDataMap.values()) {
updateRecognitionLocked(modelData, isAllowed, notify);
}
}
@@ -809,11 +824,7 @@
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException in onError", e);
} finally {
- if (mKeyphraseModelData != null) {
- mKeyphraseModelData.clearState();
- }
- internalClearKeyphraseStateLocked();
- internalClearGenericModelStateLocked();
+ internalClearModelStateLocked();
internalClearGlobalStateLocked();
if (mModule != null) {
mModule.detach();
@@ -822,10 +833,7 @@
}
}
- // 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
- // by the cleanup happening with the generic sound models.
+ // internalClearGlobalStateLocked() cleans up the telephony and power save listeners.
private void internalClearGlobalStateLocked() {
// Unregister from call state changes.
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
@@ -837,20 +845,9 @@
}
}
- private void internalClearKeyphraseStateLocked() {
- if (mKeyphraseModelData != null) {
- mKeyphraseModelData.setStopped();
- mKeyphraseModelData.setRequested(false);
- mKeyphraseModelData.setRecognitionConfig(null);
- mKeyphraseModelData.setCallback(null);
- }
-
- mKeyphraseId = INVALID_VALUE;
- }
-
- private void internalClearGenericModelStateLocked() {
- for (UUID modelId : mGenericModelDataMap.keySet()) {
- ModelData modelData = mGenericModelDataMap.get(modelId);
+ // Clears state for all models (generic and keyphrase).
+ private void internalClearModelStateLocked() {
+ for (ModelData modelData : mModelDataMap.values()) {
modelData.clearState();
modelData.clearCallback();
}
@@ -884,14 +881,10 @@
synchronized (mLock) {
pw.print(" module properties=");
pw.println(mModuleProperties == null ? "null" : mModuleProperties);
- pw.print(" keyphrase ID="); pw.println(mKeyphraseId);
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());
- }
}
}
@@ -914,34 +907,60 @@
// 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);
+ for (ModelData modelData : mModelDataMap.values()) {
+ IRecognitionStatusCallback callback = modelData.getCallback();
+ if (callback != null) {
+ callback.onError(STATUS_ERROR);
}
}
}
private ModelData getOrCreateGenericModelDataLocked(UUID modelId) {
- ModelData modelData = mGenericModelDataMap.get(modelId);
+ ModelData modelData = mModelDataMap.get(modelId);
if (modelData == null) {
modelData = ModelData.createGenericModelData(modelId);
- mGenericModelDataMap.put(modelId, modelData);
+ mModelDataMap.put(modelId, modelData);
+ } else if (!modelData.isGenericModel()) {
+ Slog.e(TAG, "UUID already used for non-generic model.");
+ return null;
}
return modelData;
}
+ private void removeKeyphraseModelLocked(int keyphraseId) {
+ UUID uuid = mKeyphraseUuidMap.get(keyphraseId);
+ if (uuid == null) {
+ return;
+ }
+ mModelDataMap.remove(uuid);
+ mKeyphraseUuidMap.remove(keyphraseId);
+ }
+
+ private ModelData getKeyphraseModelDataLocked(int keyphraseId) {
+ UUID uuid = mKeyphraseUuidMap.get(keyphraseId);
+ if (uuid == null) {
+ return null;
+ }
+ return mModelDataMap.get(uuid);
+ }
+
+ // Use this to create a new ModelData entry for a keyphrase Id. It will overwrite existing
+ // mapping if one exists.
+ private ModelData createKeyphraseModelDataLocked(UUID modelId, int keyphraseId) {
+ mKeyphraseUuidMap.remove(keyphraseId);
+ mModelDataMap.remove(modelId);
+ mKeyphraseUuidMap.put(keyphraseId, modelId);
+ ModelData modelData = ModelData.createKeyphraseModelData(modelId);
+ mModelDataMap.put(modelId, modelData);
+ return modelData;
+ }
+
// Instead of maintaining a second hashmap of modelHandle -> ModelData, we just
// iterate through to find the right object (since we don't expect 100s of models
// to be stored).
private ModelData getModelDataForLocked(int modelHandle) {
// Fetch ModelData object corresponding to the model handle.
- for (ModelData model : mGenericModelDataMap.values()) {
+ for (ModelData model : mModelDataMap.values()) {
if (model.getHandle() == modelHandle) {
return model;
}
@@ -1051,9 +1070,9 @@
return status;
}
- private void dumpGenericModelStateLocked() {
- for (UUID modelId : mGenericModelDataMap.keySet()) {
- ModelData modelData = mGenericModelDataMap.get(modelId);
+ private void dumpModelStateLocked() {
+ for (UUID modelId : mModelDataMap.keySet()) {
+ ModelData modelData = mModelDataMap.get(modelId);
Slog.i(TAG, "Model :" + modelData.toString());
}
}
@@ -1065,14 +1084,7 @@
mRecognitionRunning = false;
return mRecognitionRunning;
}
- if (mKeyphraseModelData != null && mKeyphraseModelData.getCallback() != null &&
- mKeyphraseModelData.isModelStarted() &&
- mKeyphraseModelData.getHandle() != INVALID_VALUE) {
- mRecognitionRunning = true;
- return mRecognitionRunning;
- }
- for (UUID modelId : mGenericModelDataMap.keySet()) {
- ModelData modelData = mGenericModelDataMap.get(modelId);
+ for (ModelData modelData : mModelDataMap.values()) {
if (modelData.isModelStarted()) {
mRecognitionRunning = true;
return mRecognitionRunning;
@@ -1233,6 +1245,10 @@
return mModelType == SoundModel.TYPE_KEYPHRASE;
}
+ synchronized boolean isGenericModel() {
+ return mModelType == SoundModel.TYPE_GENERIC_SOUND;
+ }
+
synchronized String stateToString() {
switch(mModelState) {
case MODEL_NOTLOADED: return "NOT_LOADED";
@@ -1259,7 +1275,17 @@
"ModelState: " + stateToString() + "\n" +
requestedToString() + "\n" +
callbackToString() + "\n" +
- uuidToString();
+ uuidToString() + "\n" + modelTypeToString();
+ }
+
+ synchronized String modelTypeToString() {
+ String type = null;
+ switch (mModelType) {
+ case SoundModel.TYPE_GENERIC_SOUND: type = "Generic"; break;
+ case SoundModel.TYPE_UNKNOWN: type = "Unknown"; break;
+ case SoundModel.TYPE_KEYPHRASE: type = "Keyphrase"; break;
+ }
+ return "Model type: " + type + "\n";
}
}
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 1544723..1e9db18 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -17,6 +17,7 @@
package com.android.server.voiceinteraction;
import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.content.BroadcastReceiver;
@@ -42,9 +43,11 @@
import com.android.internal.app.IVoiceInteractionSessionShowCallback;
import com.android.internal.app.IVoiceInteractor;
+import com.android.server.LocalServices;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.List;
class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConnection.Callback {
final static String TAG = "VoiceInteractionServiceManager";
@@ -148,8 +151,14 @@
mActiveSession = new VoiceInteractionSessionConnection(mLock, mSessionComponentName,
mUser, mContext, this, mInfo.getServiceInfo().applicationInfo.uid, mHandler);
}
+ List<IBinder> activityTokens = null;
+ if (activityToken == null) {
+ // Let's get top activities from all visible stacks
+ activityTokens = LocalServices.getService(ActivityManagerInternal.class)
+ .getTopVisibleActivities();
+ }
return mActiveSession.showLocked(args, flags, mDisabledShowContext, showCallback,
- activityToken);
+ activityToken, activityTokens);
}
public boolean hideSessionLocked() {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index e04f312..0922a12 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -45,6 +45,7 @@
import android.util.Slog;
import android.view.IWindowManager;
import android.view.WindowManager;
+
import com.android.internal.app.IAssistScreenshotReceiver;
import com.android.internal.app.IVoiceInteractionSessionShowCallback;
import com.android.internal.app.IVoiceInteractor;
@@ -55,10 +56,15 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.List;
final class VoiceInteractionSessionConnection implements ServiceConnection {
+
final static String TAG = "VoiceInteractionServiceManager";
+ private static final String KEY_RECEIVER_EXTRA_COUNT = "count";
+ private static final String KEY_RECEIVER_EXTRA_INDEX = "index";
+
final IBinder mToken = new Binder();
final Object mLock;
final ComponentName mSessionComponentName;
@@ -82,11 +88,27 @@
IVoiceInteractionSession mSession;
IVoiceInteractor mInteractor;
boolean mHaveAssistData;
- Bundle mAssistData;
+ int mPendingAssistDataCount;
+ ArrayList<AssistDataForActivity> mAssistData = new ArrayList<>();
boolean mHaveScreenshot;
Bitmap mScreenshot;
ArrayList<IVoiceInteractionSessionShowCallback> mPendingShowCallbacks = new ArrayList<>();
+ static class AssistDataForActivity {
+ int activityIndex;
+ int activityCount;
+ Bundle data;
+
+ public AssistDataForActivity(Bundle data) {
+ this.data = data;
+ Bundle receiverExtras = data.getBundle(VoiceInteractionSession.KEY_RECEIVER_EXTRAS);
+ if (receiverExtras != null) {
+ activityIndex = receiverExtras.getInt(KEY_RECEIVER_EXTRA_INDEX);
+ activityCount = receiverExtras.getInt(KEY_RECEIVER_EXTRA_COUNT);
+ }
+ }
+ }
+
IVoiceInteractionSessionShowCallback mShowCallback =
new IVoiceInteractionSessionShowCallback.Stub() {
@Override
@@ -125,7 +147,7 @@
synchronized (mLock) {
if (mShown) {
mHaveAssistData = true;
- mAssistData = resultData;
+ mAssistData.add(new AssistDataForActivity(resultData));
deliverSessionDataLocked();
}
}
@@ -198,7 +220,8 @@
}
public boolean showLocked(Bundle args, int flags, int disabledContext,
- IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) {
+ IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken,
+ List<IBinder> topActivities) {
if (mBound) {
if (!mFullyBound) {
mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection,
@@ -220,30 +243,41 @@
mShowArgs = args;
mShowFlags = flags;
mHaveAssistData = false;
+ mPendingAssistDataCount = 0;
boolean needDisclosure = false;
if ((flags&VoiceInteractionSession.SHOW_WITH_ASSIST) != 0) {
if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_STRUCTURE, mCallingUid,
mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
&& structureEnabled) {
- try {
- MetricsLogger.count(mContext, "assist_with_context", 1);
- if (mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
- mAssistReceiver, activityToken)) {
- needDisclosure = true;
- } else {
- // Wasn't allowed... given that, let's not do the screenshot either.
- mHaveAssistData = true;
- mAssistData = null;
- screenshotEnabled = false;
+ mAssistData.clear();
+ final int count = activityToken != null ? 1 : topActivities.size();
+ for (int i = 0; i < count; i++) {
+ IBinder topActivity = count == 1 ? activityToken : topActivities.get(i);
+ try {
+ MetricsLogger.count(mContext, "assist_with_context", 1);
+ Bundle receiverExtras = new Bundle();
+ receiverExtras.putInt(KEY_RECEIVER_EXTRA_INDEX, i);
+ receiverExtras.putInt(KEY_RECEIVER_EXTRA_COUNT, count);
+ if (mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
+ mAssistReceiver, receiverExtras, topActivity, i == 0)) {
+ needDisclosure = true;
+ mPendingAssistDataCount++;
+ } else if (i == 0) {
+ // Wasn't allowed... given that, let's not do the screenshot either.
+ mHaveAssistData = true;
+ mAssistData.clear();
+ screenshotEnabled = false;
+ break;
+ }
+ } catch (RemoteException e) {
}
- } catch (RemoteException e) {
}
} else {
mHaveAssistData = true;
- mAssistData = null;
+ mAssistData.clear();
}
} else {
- mAssistData = null;
+ mAssistData.clear();
}
mHaveScreenshot = false;
if ((flags&VoiceInteractionSession.SHOW_WITH_SCREENSHOT) != 0) {
@@ -335,41 +369,26 @@
return;
}
if (mHaveAssistData) {
- Bundle assistData;
- AssistStructure structure;
- AssistContent content;
- if (mAssistData != null) {
- assistData = mAssistData.getBundle("data");
- structure = mAssistData.getParcelable("structure");
- content = mAssistData.getParcelable("content");
- int uid = mAssistData.getInt(Intent.EXTRA_ASSIST_UID, -1);
- if (uid >= 0 && content != null) {
- Intent intent = content.getIntent();
- if (intent != null) {
- ClipData data = intent.getClipData();
- if (data != null && Intent.isAccessUriMode(intent.getFlags())) {
- grantClipDataPermissions(data, intent.getFlags(), uid,
- mCallingUid, mSessionComponentName.getPackageName());
- }
- }
- ClipData data = content.getClipData();
- if (data != null) {
- grantClipDataPermissions(data,
- Intent.FLAG_GRANT_READ_URI_PERMISSION,
- uid, mCallingUid, mSessionComponentName.getPackageName());
- }
+ AssistDataForActivity assistData;
+ while (!mAssistData.isEmpty()) {
+ if (mPendingAssistDataCount <= 0) {
+ Slog.e(TAG, "mPendingAssistDataCount is " + mPendingAssistDataCount);
}
- } else {
- assistData = null;
- structure = null;
- content = null;
+ mPendingAssistDataCount--;
+ assistData = mAssistData.remove(0);
+ if (assistData.data == null) {
+ try {
+ mSession.handleAssist(null, null, null, assistData.activityIndex,
+ assistData.activityCount);
+ } catch (RemoteException e) {
+ }
+ } else {
+ deliverSessionDataLocked(assistData);
+ }
}
- try {
- mSession.handleAssist(assistData, structure, content);
- } catch (RemoteException e) {
- }
- mAssistData = null;
- mHaveAssistData = false;
+ if (mPendingAssistDataCount <= 0) {
+ mHaveAssistData = false;
+ } // else, more to come
}
if (mHaveScreenshot) {
try {
@@ -381,6 +400,37 @@
}
}
+ private void deliverSessionDataLocked(AssistDataForActivity assistDataForActivity) {
+ Bundle assistData = assistDataForActivity.data.getBundle(
+ VoiceInteractionSession.KEY_DATA);
+ AssistStructure structure = assistDataForActivity.data.getParcelable(
+ VoiceInteractionSession.KEY_STRUCTURE);
+ AssistContent content = assistDataForActivity.data.getParcelable(
+ VoiceInteractionSession.KEY_CONTENT);
+ int uid = assistDataForActivity.data.getInt(Intent.EXTRA_ASSIST_UID, -1);
+ if (uid >= 0 && content != null) {
+ Intent intent = content.getIntent();
+ if (intent != null) {
+ ClipData data = intent.getClipData();
+ if (data != null && Intent.isAccessUriMode(intent.getFlags())) {
+ grantClipDataPermissions(data, intent.getFlags(), uid,
+ mCallingUid, mSessionComponentName.getPackageName());
+ }
+ }
+ ClipData data = content.getClipData();
+ if (data != null) {
+ grantClipDataPermissions(data,
+ Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ uid, mCallingUid, mSessionComponentName.getPackageName());
+ }
+ }
+ try {
+ mSession.handleAssist(assistData, structure, content,
+ assistDataForActivity.activityIndex, assistDataForActivity.activityCount);
+ } catch (RemoteException e) {
+ }
+ }
+
public boolean hideLocked() {
if (mBound) {
if (mShown) {
@@ -388,7 +438,7 @@
mShowArgs = null;
mShowFlags = 0;
mHaveAssistData = false;
- mAssistData = null;
+ mAssistData.clear();
if (mSession != null) {
try {
mSession.hide();
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index adc7c21..26730de 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -426,6 +426,13 @@
public static final String KEY_CARRIER_METERED_APN_TYPES_STRINGS =
"carrier_metered_apn_types_strings";
+ /**
+ * CDMA carrier ERI (Enhanced Roaming Indicator) file name
+ * @hide
+ */
+ public static final String KEY_CARRIER_ERI_FILE_NAME_STRING =
+ "carrier_eri_file_name_string";
+
/* The following 3 fields are related to carrier visual voicemail. */
/**
@@ -541,6 +548,27 @@
public static final String KEY_EDITABLE_WFC_MODE_BOOL = "editable_wfc_mode_bool";
/**
+ * List operator-specific error codes and indices of corresponding error strings in
+ * wfcOperatorErrorAlertMessages and wfcOperatorErrorNotificationMessages.
+ *
+ * Example: "REG09|0" specifies error code "REG09" and index "0". This index will be
+ * used to find alert and notification messages in wfcOperatorErrorAlertMessages and
+ * wfcOperatorErrorNotificationMessages.
+ *
+ * @hide
+ */
+ public static final String KEY_WFC_OPERATOR_ERROR_CODES_STRING_ARRAY =
+ "wfc_operator_error_codes_string_array";
+
+ /**
+ * Indexes of SPN format strings in wfcSpnFormats and wfcDataSpnFormats.
+ * @hide
+ */
+ public static final String KEY_WFC_SPN_FORMAT_IDX_INT = "wfc_spn_format_idx_int";
+ /** @hide */
+ public static final String KEY_WFC_DATA_SPN_FORMAT_IDX_INT = "wfc_data_spn_format_idx_int";
+
+ /**
* If this is true, the SIM card (through Customer Service Profile EF file) will be able to
* prevent manual operator selection. If false, this SIM setting will be ignored and manual
* operator selection will always be available. See CPHS4_2.WW6, CPHS B.4.7.1 for more
@@ -686,8 +714,8 @@
sDefaults.putString(KEY_VVM_DESTINATION_NUMBER_STRING, "");
sDefaults.putInt(KEY_VVM_PORT_NUMBER_INT, 0);
sDefaults.putString(KEY_VVM_TYPE_STRING, "");
- sDefaults.putBoolean(KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN,false);
- sDefaults.putBoolean(KEY_VVM_PREFETCH_BOOLEAN,true);
+ sDefaults.putBoolean(KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN, false);
+ sDefaults.putBoolean(KEY_VVM_PREFETCH_BOOLEAN, true);
sDefaults.putString(KEY_CARRIER_VVM_PACKAGE_NAME_STRING, "");
sDefaults.putBoolean(KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL, false);
sDefaults.putBoolean(KEY_CI_ACTION_ON_SYS_UPDATE_BOOL, false);
@@ -705,6 +733,7 @@
"max_retries=3, 5000, 5000, 5000");
sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_DEFAULT_LONG, 20000);
sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_FASTER_LONG, 3000);
+ sDefaults.putString(KEY_CARRIER_ERI_FILE_NAME_STRING, "eri.xml");
sDefaults.putInt(KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT, 7200);
sDefaults.putStringArray(KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{"default", "mms", "dun", "supl"});
@@ -723,6 +752,9 @@
sDefaults.putBoolean(KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL, false);
sDefaults.putBoolean(KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL, false);
sDefaults.putBoolean(KEY_EDITABLE_WFC_MODE_BOOL, true);
+ sDefaults.putStringArray(KEY_WFC_OPERATOR_ERROR_CODES_STRING_ARRAY, null);
+ sDefaults.putInt(KEY_WFC_SPN_FORMAT_IDX_INT, 0);
+ sDefaults.putInt(KEY_WFC_DATA_SPN_FORMAT_IDX_INT, 0);
// MMS defaults
sDefaults.putBoolean(KEY_MMS_ALIAS_ENABLED_BOOL, false);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 865af78..0bca628 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -717,16 +717,11 @@
*/
/** {@hide} */
public String getDeviceSoftwareVersion(int slotId) {
- // FIXME methods taking slot id should not use subscription, instead us Uicc directly
- int[] subId = SubscriptionManager.getSubId(slotId);
- if (subId == null || subId.length == 0) {
- return null;
- }
+ ITelephony telephony = getITelephony();
+ if (telephony == null) return null;
+
try {
- IPhoneSubInfo info = getSubscriberInfo();
- if (info == null)
- return null;
- return info.getDeviceSvnUsingSubId(subId[0], mContext.getOpPackageName());
+ return telephony.getDeviceSoftwareVersionForSlot(slotId, getOpPackageName());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -798,12 +793,11 @@
*/
/** {@hide} */
public String getImei(int slotId) {
- int[] subId = SubscriptionManager.getSubId(slotId);
+ ITelephony telephony = getITelephony();
+ if (telephony == null) return null;
+
try {
- IPhoneSubInfo info = getSubscriberInfo();
- if (info == null)
- return null;
- return info.getImeiForSubscriber(subId[0], mContext.getOpPackageName());
+ return telephony.getImeiForSlot(slotId, getOpPackageName());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1014,22 +1008,32 @@
} else {
phoneId = SubscriptionManager.getPhoneId(subId);
}
+
+ return getCurrentPhoneTypeForSlot(phoneId);
+ }
+
+ /**
+ * See getCurrentPhoneType.
+ *
+ * @hide
+ */
+ public int getCurrentPhoneTypeForSlot(int slotId) {
try{
ITelephony telephony = getITelephony();
- if (telephony != null && subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- return telephony.getActivePhoneTypeForSubscriber(subId);
+ if (telephony != null) {
+ return telephony.getActivePhoneTypeForSlot(slotId);
} else {
// This can happen when the ITelephony interface is not up yet.
- return getPhoneTypeFromProperty(phoneId);
+ return getPhoneTypeFromProperty(slotId);
}
} catch (RemoteException ex) {
// This shouldn't happen in the normal case, as a backup we
// read from the system property.
- return getPhoneTypeFromProperty(phoneId);
+ return getPhoneTypeFromProperty(slotId);
} catch (NullPointerException ex) {
// This shouldn't happen in the normal case, as a backup we
// read from the system property.
- return getPhoneTypeFromProperty(phoneId);
+ return getPhoneTypeFromProperty(slotId);
}
}
@@ -2555,20 +2559,31 @@
* @param subId whose call state is returned
*/
public int getCallState(int subId) {
+ int phoneId = SubscriptionManager.getPhoneId(subId);
+ return getCallStateForSlot(phoneId);
+ }
+
+ /**
+ * See getCallState.
+ *
+ * @hide
+ */
+ public int getCallStateForSlot(int slotId) {
try {
ITelephony telephony = getITelephony();
if (telephony == null)
return CALL_STATE_IDLE;
- return telephony.getCallStateForSubscriber(subId);
+ return telephony.getCallStateForSlot(slotId);
} catch (RemoteException ex) {
// the phone process is restarting.
return CALL_STATE_IDLE;
} catch (NullPointerException ex) {
// the phone process is restarting.
return CALL_STATE_IDLE;
- }
+ }
}
+
/** Data connection activity: No traffic. */
public static final int DATA_ACTIVITY_NONE = 0x00000000;
/** Data connection activity: Currently receiving IP PPP traffic. */
@@ -3629,22 +3644,6 @@
}
/**
- * Returns the response of SIM Authentication through RIL for the default subscription.
- * Returns null if the Authentication hasn't been successful
- *
- * <p>Requires that the calling app has carrier privileges.
- * @see #hasCarrierPrivileges
- *
- * @param appType ICC application type (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
- * @param data authentication challenge data
- * @return the response of SIM Authentication, or null if not available
- * @hide
- */
- public String getIccSimChallengeResponse(int appType, String data) {
- return getIccAuthentication(getDefaultSubscription(), appType, AUTHTYPE_EAP_SIM, data);
- }
-
- /**
* Get P-CSCF address from PCO after data connection is established or modified.
* @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
* @return array of P-CSCF address
diff --git a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
new file mode 100644
index 0000000..ca7354f
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.telephony;
+
+import android.annotation.Nullable;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.os.RemoteException;
+import android.telephony.TelephonyManager;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utilities for handling carrier applications.
+ * @hide
+ */
+public final class CarrierAppUtils {
+ private static final String TAG = "CarrierAppUtils";
+
+ private static final boolean DEBUG = false; // STOPSHIP if true
+
+ private CarrierAppUtils() {}
+
+ /**
+ * Handle preinstalled carrier apps which should be disabled until a matching SIM is inserted.
+ *
+ * Evaluates the list of applications in config_disabledUntilUsedPreinstalledCarrierApps. We
+ * want to disable each such application which is present on the system image until the user
+ * inserts a SIM which causes that application to gain carrier privilege (indicating a "match"),
+ * without interfering with the user if they opt to enable/disable the app explicitly.
+ *
+ * So, for each such app, we either disable until used IFF the app is not carrier privileged AND
+ * in the default state (e.g. not explicitly DISABLED/DISABLED_BY_USER/ENABLED), or we enable if
+ * the app is carrier privileged and in either the default state or DISABLED_UNTIL_USED.
+ *
+ * When enabling a carrier app we also grant it default permissions.
+ *
+ * This method is idempotent and is safe to be called at any time; it should be called once at
+ * system startup prior to any application running, as well as any time the set of carrier
+ * privileged apps may have changed.
+ */
+ public synchronized static void disableCarrierAppsUntilPrivileged(String callingPackage,
+ IPackageManager packageManager, TelephonyManager telephonyManager, int userId) {
+ if (DEBUG) {
+ Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
+ }
+ String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray(
+ com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps);
+ disableCarrierAppsUntilPrivileged(callingPackage, packageManager, telephonyManager, userId,
+ systemCarrierAppsDisabledUntilUsed);
+ }
+
+ /**
+ * Like {@link #disableCarrierAppsUntilPrivileged(String, IPackageManager, TelephonyManager,
+ * int)}, but assumes that no carrier apps have carrier privileges.
+ *
+ * This prevents a potential race condition on first boot - since the app's default state is
+ * enabled, we will initially disable it when the telephony stack is first initialized as it has
+ * not yet read the carrier privilege rules. However, since telephony is initialized later on
+ * late in boot, the app being disabled may have already been started in response to certain
+ * broadcasts. The app will continue to run (briefly) after being disabled, before the Package
+ * Manager can kill it, and this can lead to crashes as the app is in an unexpected state.
+ */
+ public synchronized static void disableCarrierAppsUntilPrivileged(String callingPackage,
+ IPackageManager packageManager, int userId) {
+ if (DEBUG) {
+ Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
+ }
+ String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray(
+ com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps);
+ disableCarrierAppsUntilPrivileged(callingPackage, packageManager,
+ null /* telephonyManager */, userId, systemCarrierAppsDisabledUntilUsed);
+ }
+
+ // Must be public b/c framework unit tests can't access package-private methods.
+ @VisibleForTesting
+ public static void disableCarrierAppsUntilPrivileged(String callingPackage,
+ IPackageManager packageManager, @Nullable TelephonyManager telephonyManager, int userId,
+ String[] systemCarrierAppsDisabledUntilUsed) {
+ List<ApplicationInfo> candidates = getDefaultCarrierAppCandidatesHelper(packageManager,
+ userId, systemCarrierAppsDisabledUntilUsed);
+ if (candidates == null || candidates.isEmpty()) {
+ return;
+ }
+
+ List<String> enabledCarrierPackages = new ArrayList<>();
+
+ try {
+ for (ApplicationInfo ai : candidates) {
+ String packageName = ai.packageName;
+ boolean hasPrivileges = telephonyManager != null &&
+ telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) ==
+ TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+
+ // Only update enabled state for the app on /system. Once it has been updated we
+ // shouldn't touch it.
+ if (!ai.isUpdatedSystemApp()) {
+ if (hasPrivileges
+ && (ai.enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ || ai.enabledSetting ==
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
+ Slog.i(TAG, "Update state(" + packageName + "): ENABLED for user "
+ + userId);
+ packageManager.setApplicationEnabledSetting(packageName,
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP, userId, callingPackage);
+ } else if (!hasPrivileges
+ && ai.enabledSetting ==
+ PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
+ Slog.i(TAG, "Update state(" + packageName
+ + "): DISABLED_UNTIL_USED for user " + userId);
+ packageManager.setApplicationEnabledSetting(packageName,
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED, 0,
+ userId, callingPackage);
+ }
+ }
+
+ // Always re-grant default permissions to carrier apps w/ privileges.
+ if (hasPrivileges) {
+ enabledCarrierPackages.add(ai.packageName);
+ }
+ }
+
+ if (!enabledCarrierPackages.isEmpty()) {
+ // Since we enabled at least one app, ensure we grant default permissions to those
+ // apps.
+ String[] packageNames = new String[enabledCarrierPackages.size()];
+ enabledCarrierPackages.toArray(packageNames);
+ packageManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId);
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Could not reach PackageManager", e);
+ }
+ }
+
+ /**
+ * Returns the list of "default" carrier apps.
+ *
+ * This is the subset of apps returned by
+ * {@link #getDefaultCarrierAppCandidates(IPackageManager, int)} which currently have carrier
+ * privileges per the SIM(s) inserted in the device.
+ */
+ public static List<ApplicationInfo> getDefaultCarrierApps(IPackageManager packageManager,
+ TelephonyManager telephonyManager, int userId) {
+ // Get all system apps from the default list.
+ List<ApplicationInfo> candidates = getDefaultCarrierAppCandidates(packageManager, userId);
+ if (candidates == null || candidates.isEmpty()) {
+ return null;
+ }
+
+ // Filter out apps without carrier privileges.
+ // Iterate from the end to avoid creating an Iterator object and because we will be removing
+ // elements from the list as we pass through it.
+ for (int i = candidates.size() - 1; i >= 0; i--) {
+ ApplicationInfo ai = candidates.get(i);
+ String packageName = ai.packageName;
+ boolean hasPrivileges =
+ telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) ==
+ TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+ if (!hasPrivileges) {
+ candidates.remove(i);
+ }
+ }
+
+ return candidates;
+ }
+
+ /**
+ * Returns the list of "default" carrier app candidates.
+ *
+ * These are the apps subject to the hiding/showing logic in
+ * {@link CarrierAppUtils#disableCarrierAppsUntilPrivileged(String, IPackageManager,
+ * TelephonyManager, int)}, as well as the apps which should have default permissions granted,
+ * when a matching SIM is inserted.
+ *
+ * Whether or not the app is actually considered a default app depends on whether the app has
+ * carrier privileges as determined by the SIMs in the device.
+ */
+ public static List<ApplicationInfo> getDefaultCarrierAppCandidates(
+ IPackageManager packageManager, int userId) {
+ String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray(
+ com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps);
+ return getDefaultCarrierAppCandidatesHelper(packageManager, userId,
+ systemCarrierAppsDisabledUntilUsed);
+ }
+
+ private static List<ApplicationInfo> getDefaultCarrierAppCandidatesHelper(
+ IPackageManager packageManager, int userId,
+ String[] systemCarrierAppsDisabledUntilUsed) {
+ if (systemCarrierAppsDisabledUntilUsed == null
+ || systemCarrierAppsDisabledUntilUsed.length == 0) {
+ return null;
+ }
+ List<ApplicationInfo> apps = null;
+ try {
+ apps = new ArrayList<>(systemCarrierAppsDisabledUntilUsed.length);
+ for (String packageName : systemCarrierAppsDisabledUntilUsed) {
+ ApplicationInfo ai = packageManager.getApplicationInfo(packageName,
+ PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, userId);
+ if (ai == null) {
+ // No app found for packageName
+ continue;
+ }
+ if (!ai.isSystemApp()) {
+ continue;
+ }
+ apps.add(ai);
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Could not reach PackageManager", e);
+ }
+ return apps;
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index fcb967f..ccabace 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -102,6 +102,7 @@
public static final int CMD_NET_STAT_POLL = BASE + 40;
public static final int EVENT_DATA_RAT_CHANGED = BASE + 41;
public static final int CMD_CLEAR_PROVISIONING_SPINNER = BASE + 42;
+ public static final int EVENT_DEVICE_PROVISIONED_CHANGE = BASE + 43;
/***** Constants *****/
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 2727319..b41d361 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -360,9 +360,9 @@
int getCallState();
/**
- * Returns the call state for a subId.
+ * Returns the call state for a slot.
*/
- int getCallStateForSubscriber(int subId);
+ int getCallStateForSlot(int slotId);
int getDataActivity();
int getDataState();
@@ -375,12 +375,12 @@
int getActivePhoneType();
/**
- * Returns the current active phone type as integer for particular subId.
+ * Returns the current active phone type as integer for particular slot.
* Returns TelephonyManager.PHONE_TYPE_CDMA if RILConstants.CDMA_PHONE
* and TelephonyManager.PHONE_TYPE_GSM if RILConstants.GSM_PHONE
- * @param subId user preferred subId.
+ * @param slotId - slot to query.
*/
- int getActivePhoneTypeForSubscriber(int subId);
+ int getActivePhoneTypeForSlot(int slotId);
/**
* Returns the CDMA ERI icon index to display
@@ -992,6 +992,26 @@
String getDeviceId(String callingPackage);
/**
+ * Returns the IMEI for the given slot.
+ *
+ * @param slotId - device slot.
+ * @param callingPackage The package making the call.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ */
+ String getImeiForSlot(int slotId, String callingPackage);
+
+ /**
+ * Returns the device software version.
+ *
+ * @param slotId - device slot.
+ * @param callingPackage The package making the call.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ */
+ String getDeviceSoftwareVersionForSlot(int slotId, String callingPackage);
+
+ /**
* Returns the subscription ID associated with the specified PhoneAccount.
*/
int getSubIdForPhoneAccount(in PhoneAccount phoneAccount);
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl b/telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl
deleted file mode 100644
index 069fcbf..0000000
--- a/telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony;
-
-import com.android.internal.telephony.ITelephonyDebugSubscriber;
-
-import android.os.Bundle;
-
-/**
- * Interface used to interact with the Telephony debug service.
- *
- * {@hide}
- */
-interface ITelephonyDebug {
-
- /**
- * Write telephony event
- * @param timestamp returned by System.currentTimeMillis()
- * @param phoneId for which event is written
- * @param tag constant defined in TelephonyEventLog
- * @param param1 optional
- * @param param2 optional
- * @param data optional
- */
- void writeEvent(long timestamp, int phoneId, int tag, int param1, int param2, in Bundle data);
-
- void subscribe(in ITelephonyDebugSubscriber subscriber);
- void unsubscribe(in ITelephonyDebugSubscriber subscriber);
-}
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl b/telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl
deleted file mode 100644
index 64eb0f1..0000000
--- a/telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl
+++ /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.internal.telephony;
-
-import com.android.internal.telephony.TelephonyEvent;
-
-import android.os.Bundle;
-
-/**
- * Interface used to subscribe for events from Telephony debug service.
- *
- * {@hide}
- */
-oneway interface ITelephonyDebugSubscriber {
-
- /**
- * Called when Telephony debug service has events.
- */
- void onEvents(in TelephonyEvent[] events);
-}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 8aa0e34..cfc5305 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -33,8 +33,6 @@
// From the top of ril.cpp
int RIL_ERRNO_INVALID_RESPONSE = -1;
- int MAX_INT = 0x7FFFFFFF;
-
// from RIL_Errno
int SUCCESS = 0;
int RADIO_NOT_AVAILABLE = 1; /* If radio did not start or is resetting */
diff --git a/telephony/java/com/android/internal/telephony/TelephonyEvent.java b/telephony/java/com/android/internal/telephony/TelephonyEvent.java
deleted file mode 100644
index 26d466d..0000000
--- a/telephony/java/com/android/internal/telephony/TelephonyEvent.java
+++ /dev/null
@@ -1,84 +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.internal.telephony;
-
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * A parcelable used in ITelephonyDebugSubscriber.aidl
- */
-public class TelephonyEvent implements Parcelable {
-
- final public long timestamp;
- final public int phoneId;
- final public int tag;
- final public int param1;
- final public int param2;
- final public Bundle data;
-
- public TelephonyEvent(long timestamp, int phoneId, int tag,
- int param1, int param2, Bundle data) {
- this.timestamp = timestamp;
- this.phoneId = phoneId;
- this.tag = tag;
- this.param1 = param1;
- this.param2 = param2;
- this.data = data;
- }
-
- /** Implement the Parcelable interface */
- public static final Parcelable.Creator<TelephonyEvent> CREATOR
- = new Parcelable.Creator<TelephonyEvent> (){
- public TelephonyEvent createFromParcel(Parcel source) {
- final long timestamp = source.readLong();
- final int phoneId = source.readInt();
- final int tag = source.readInt();
- final int param1 = source.readInt();
- final int param2 = source.readInt();
- final Bundle data = source.readBundle();
- return new TelephonyEvent(timestamp, phoneId, tag, param1, param2, data);
- }
-
- public TelephonyEvent[] newArray(int size) {
- return new TelephonyEvent[size];
- }
- };
-
- /** Implement the Parcelable interface */
- @Override
- public int describeContents() {
- return 0;
- }
-
- /** Implement the Parcelable interface */
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(timestamp);
- dest.writeInt(phoneId);
- dest.writeInt(tag);
- dest.writeInt(param1);
- dest.writeInt(param2);
- dest.writeBundle(data);
- }
-
- public String toString() {
- return String.format("%d,%d,%d,%d,%d,%s",
- timestamp, phoneId, tag, param1, param2, data);
- }
-}
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 91e891f..2e5ed3f 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -691,6 +691,15 @@
throw new UnsupportedOperationException();
}
+ /**
+ * @hide - to match hiding in superclass
+ */
+ @Override
+ public void deleteApplicationCacheFilesAsUser(String packageName, int userId,
+ IPackageDataObserver observer) {
+ throw new UnsupportedOperationException();
+ }
+
/** {@hide} */
@Override
public void freeStorageAndNotify(String volumeUuid, long idealStorageSize,
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 18fd985..b9e9ac8 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -374,6 +374,15 @@
</activity>
<activity
+ android:name="GetBitmapSurfaceViewActivity"
+ android:label="SurfaceView/GetBitmap with Camera source">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.test.hwui.TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity
android:name="GLTextureViewActivity"
android:label="TextureView/OpenGL">
<intent-filter>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapSurfaceViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapSurfaceViewActivity.java
new file mode 100644
index 0000000..d3cd7db
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapSurfaceViewActivity.java
@@ -0,0 +1,111 @@
+/*
+ * 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.test.hwui;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.PixelCopy;
+import android.graphics.PixelCopy.OnPixelCopyFinished;
+import android.graphics.PixelCopy.Response;
+import android.hardware.Camera;
+import android.os.Bundle;
+import android.os.Environment;
+import android.view.Gravity;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.Toast;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class GetBitmapSurfaceViewActivity extends Activity implements SurfaceHolder.Callback {
+ private Camera mCamera;
+ private SurfaceView mSurfaceView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ FrameLayout content = new FrameLayout(this);
+
+ mSurfaceView = new SurfaceView(this);
+ mSurfaceView.getHolder().addCallback(this);
+
+ Button button = new Button(this);
+ button.setText("Copy bitmap to /sdcard/surfaceview.png");
+ button.setOnClickListener((View v) -> {
+ Bitmap b = Bitmap.createBitmap(
+ mSurfaceView.getWidth(),
+ mSurfaceView.getHeight(),
+ Bitmap.Config.ARGB_8888);
+ PixelCopy.request(mSurfaceView, b,
+ mOnCopyFinished, mSurfaceView.getHandler());
+ });
+
+ content.addView(mSurfaceView, new FrameLayout.LayoutParams(500, 400, Gravity.CENTER));
+ content.addView(button, new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT,
+ Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM));
+ setContentView(content);
+ }
+
+ private final OnPixelCopyFinished mOnCopyFinished = new OnPixelCopyFinished() {
+ @Override
+ public void onPixelCopyFinished(Response response) {
+ if (!response.success) {
+ Toast.makeText(GetBitmapSurfaceViewActivity.this,
+ "Failed to copy", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ try {
+ try (FileOutputStream out = new FileOutputStream(
+ Environment.getExternalStorageDirectory() + "/surfaceview.png");) {
+ response.bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
+ }
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ };
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ mCamera = Camera.open();
+
+ try {
+ mCamera.setPreviewSurface(holder.getSurface());
+ } catch (IOException t) {
+ android.util.Log.e("TextureView", "Cannot set preview texture target!", t);
+ }
+
+ mCamera.startPreview();
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ mCamera.stopPreview();
+ mCamera.release();
+ }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/HardwareCanvasSurfaceViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/HardwareCanvasSurfaceViewActivity.java
index b1431c5..5c30fab 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/HardwareCanvasSurfaceViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/HardwareCanvasSurfaceViewActivity.java
@@ -17,18 +17,29 @@
package com.android.test.hwui;
import android.app.Activity;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
+import android.graphics.PixelCopy;
+import android.graphics.PixelCopy.OnPixelCopyFinished;
+import android.graphics.PixelCopy.Response;
import android.graphics.PorterDuff;
import android.os.Bundle;
-import android.view.Gravity;
+import android.os.Environment;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
+import android.view.View;
+import android.widget.Button;
import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.Toast;
-@SuppressWarnings({"UnusedDeclaration"})
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
public class HardwareCanvasSurfaceViewActivity extends Activity implements Callback {
private SurfaceView mSurfaceView;
private HardwareCanvasSurfaceViewActivity.RenderingThread mThread;
@@ -42,13 +53,49 @@
mSurfaceView = new SurfaceView(this);
mSurfaceView.getHolder().addCallback(this);
- content.addView(mSurfaceView, new FrameLayout.LayoutParams(
+ Button button = new Button(this);
+ button.setText("Copy bitmap to /sdcard/surfaceview.png");
+ button.setOnClickListener((View v) -> {
+ Bitmap b = Bitmap.createBitmap(
+ mSurfaceView.getWidth(),
+ mSurfaceView.getHeight(),
+ Bitmap.Config.ARGB_8888);
+ PixelCopy.request(mSurfaceView, b,
+ mOnCopyFinished, mSurfaceView.getHandler());
+ });
+
+ LinearLayout layout = new LinearLayout(this);
+ layout.setOrientation(LinearLayout.VERTICAL);
+ layout.addView(button, LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT);
+ layout.addView(mSurfaceView, LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.MATCH_PARENT);
+
+ content.addView(layout, new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
- FrameLayout.LayoutParams.MATCH_PARENT,
- Gravity.CENTER));
+ FrameLayout.LayoutParams.MATCH_PARENT));
setContentView(content);
}
+ private final OnPixelCopyFinished mOnCopyFinished = new OnPixelCopyFinished() {
+ @Override
+ public void onPixelCopyFinished(Response response) {
+ if (!response.success) {
+ Toast.makeText(HardwareCanvasSurfaceViewActivity.this,
+ "Failed to copy", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ try {
+ try (FileOutputStream out = new FileOutputStream(
+ Environment.getExternalStorageDirectory() + "/surfaceview.png");) {
+ response.bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
+ }
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ };
+
@Override
public void surfaceCreated(SurfaceHolder holder) {
mThread = new RenderingThread(holder.getSurface());
diff --git a/tests/SoundTriggerTestApp/res/layout/main.xml b/tests/SoundTriggerTestApp/res/layout/main.xml
index 702be49..06949a0 100644
--- a/tests/SoundTriggerTestApp/res/layout/main.xml
+++ b/tests/SoundTriggerTestApp/res/layout/main.xml
@@ -60,29 +60,22 @@
android:onClick="onUnEnrollButtonClicked"
android:padding="20dp" />
+ <Button
+ android:id="@+id/play_trigger_id"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/play_trigger"
+ android:onClick="onPlayTriggerButtonClicked"
+ android:padding="20dp" />
+
</LinearLayout>
<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/model_group_id"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
- android:checkedButton="@+id/model_one"
android:orientation="vertical">
- <RadioButton android:id="@+id/model_one"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/model_one"
- android:onClick="onRadioButtonClicked"/>
- <RadioButton android:id="@+id/model_two"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/model_two"
- android:onClick="onRadioButtonClicked"/>
- <RadioButton android:id="@+id/model_three"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/model_three"
- android:onClick="onRadioButtonClicked"/>
</RadioGroup>
<ScrollView
@@ -93,7 +86,7 @@
android:fillViewport="true">
<TextView
- android:id="@+id/console"
+ android:id="@+id/console"
android:paddingTop="20pt"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
diff --git a/tests/SoundTriggerTestApp/res/values/strings.xml b/tests/SoundTriggerTestApp/res/values/strings.xml
index b4ca71b..7c1f649 100644
--- a/tests/SoundTriggerTestApp/res/values/strings.xml
+++ b/tests/SoundTriggerTestApp/res/values/strings.xml
@@ -21,8 +21,6 @@
<string name="unenroll">Un-load</string>
<string name="start_recog">Start</string>
<string name="stop_recog">Stop</string>
- <string name="model_one">Model One</string>
- <string name="model_two">Model Two</string>
- <string name="model_three">Model Three</string>
+ <string name="play_trigger">Play Trigger Audio</string>
<string name="none">Debug messages appear here:\n</string>
</resources>
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
index 3ca96d2..5fd38e9 100644
--- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
@@ -16,24 +16,36 @@
package com.android.test.soundtrigger;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
import java.util.Random;
import java.util.UUID;
import android.app.Activity;
-import android.hardware.soundtrigger.SoundTrigger;
import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
+import android.hardware.soundtrigger.SoundTrigger;
import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
import android.media.soundtrigger.SoundTriggerDetector;
import android.media.soundtrigger.SoundTriggerManager;
-import android.text.Editable;
-import android.text.method.ScrollingMovementMethod;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.os.UserManager;
+import android.text.Editable;
+import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
+import android.widget.Button;
import android.widget.RadioButton;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
@@ -44,20 +56,17 @@
private SoundTriggerUtil mSoundTriggerUtil;
private Random mRandom;
- private UUID mModelUuid1 = UUID.randomUUID();
- private UUID mModelUuid2 = UUID.randomUUID();
- private UUID mModelUuid3 = UUID.randomUUID();
- private UUID mVendorUuid = UUID.randomUUID();
- private SoundTriggerDetector mDetector1 = null;
- private SoundTriggerDetector mDetector2 = null;
- private SoundTriggerDetector mDetector3 = null;
+ private Map<Integer, ModelInfo> mModelInfoMap;
+ private Map<View, Integer> mModelIdMap;
private TextView mDebugView = null;
- private int mSelectedModelId = 1;
+ private int mSelectedModelId = -1;
private ScrollView mScrollView = null;
+ private Button mPlayTriggerButton = null;
private PowerManager.WakeLock mScreenWakelock;
private Handler mHandler;
+ private RadioGroup mRadioGroup;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -66,11 +75,108 @@
setContentView(R.layout.main);
mDebugView = (TextView) findViewById(R.id.console);
mScrollView = (ScrollView) findViewById(R.id.scroller_id);
+ mRadioGroup = (RadioGroup) findViewById(R.id.model_group_id);
+ mPlayTriggerButton = (Button) findViewById(R.id.play_trigger_id);
mDebugView.setText(mDebugView.getText(), TextView.BufferType.EDITABLE);
mDebugView.setMovementMethod(new ScrollingMovementMethod());
mSoundTriggerUtil = new SoundTriggerUtil(this);
mRandom = new Random();
mHandler = new Handler();
+
+ mModelInfoMap = new HashMap();
+ mModelIdMap = new HashMap();
+
+ setVolumeControlStream(AudioManager.STREAM_MUSIC);
+
+ // Load all the models in the data dir.
+ for (File file : getFilesDir().listFiles()) {
+ // Find meta-data in .properties files, ignore everything else.
+ if (!file.getName().endsWith(".properties")) {
+ continue;
+ }
+ try {
+ Properties properties = new Properties();
+ properties.load(new FileInputStream(file));
+ createModelInfoAndWidget(properties);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to load properties file " + file.getName());
+ }
+ }
+
+ // Create a few dummy models if we didn't load anything.
+ if (mModelIdMap.isEmpty()) {
+ Properties dummyModelProperties = new Properties();
+ for (String name : new String[]{"One", "Two", "Three"}) {
+ dummyModelProperties.setProperty("name", "Model " + name);
+ createModelInfoAndWidget(dummyModelProperties);
+ }
+ }
+ }
+
+ private void createModelInfoAndWidget(Properties properties) {
+ try {
+ ModelInfo modelInfo = new ModelInfo();
+
+ if (!properties.containsKey("name")) {
+ throw new RuntimeException("must have a 'name' property");
+ }
+ modelInfo.name = properties.getProperty("name");
+
+ if (properties.containsKey("modelUuid")) {
+ modelInfo.modelUuid = UUID.fromString(properties.getProperty("modelUuid"));
+ } else {
+ modelInfo.modelUuid = UUID.randomUUID();
+ }
+
+ if (properties.containsKey("vendorUuid")) {
+ modelInfo.vendorUuid = UUID.fromString(properties.getProperty("vendorUuid"));
+ } else {
+ modelInfo.vendorUuid = UUID.randomUUID();
+ }
+
+ if (properties.containsKey("triggerAudio")) {
+ modelInfo.triggerAudioPlayer = MediaPlayer.create(this, Uri.parse(
+ getFilesDir().getPath() + "/" + properties.getProperty("triggerAudio")));
+ }
+
+ if (properties.containsKey("dataFile")) {
+ File modelDataFile = new File(
+ getFilesDir().getPath() + "/" + properties.getProperty("dataFile"));
+ modelInfo.modelData = new byte[(int) modelDataFile.length()];
+ FileInputStream input = new FileInputStream(modelDataFile);
+ input.read(modelInfo.modelData, 0, modelInfo.modelData.length);
+ } else {
+ modelInfo.modelData = new byte[1024];
+ mRandom.nextBytes(modelInfo.modelData);
+ }
+
+ // TODO: Add property support for keyphrase models when they're exposed by the
+ // service. Also things like how much audio they should record with the capture session
+ // provided in the callback.
+
+ // Add a widget into the radio group.
+ RadioButton button = new RadioButton(this);
+ mRadioGroup.addView(button);
+ button.setText(modelInfo.name);
+ button.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ onRadioButtonClicked(v);
+ }
+ });
+
+ // Update our maps containing the button -> id and id -> modelInfo.
+ int newModelId = mModelIdMap.size() + 1;
+ mModelIdMap.put(button, newModelId);
+ mModelInfoMap.put(newModelId, modelInfo);
+
+ // If we don't have something selected, select this first thing.
+ if (mSelectedModelId < 0) {
+ button.setChecked(true);
+ onRadioButtonClicked(button);
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Error parsing properties for " + properties.getProperty("name"), e);
+ }
}
private void postMessage(String msg) {
@@ -91,27 +197,15 @@
}
private synchronized UUID getSelectedUuid() {
- if (mSelectedModelId == 2) return mModelUuid2;
- if (mSelectedModelId == 3) return mModelUuid3;
- return mModelUuid1; // Default.
+ return mModelInfoMap.get(mSelectedModelId).modelUuid;
}
private synchronized void setDetector(SoundTriggerDetector detector) {
- if (mSelectedModelId == 2) {
- mDetector2 = detector;
- return;
- }
- if (mSelectedModelId == 3) {
- mDetector3 = detector;
- return;
- }
- mDetector1 = detector;
+ mModelInfoMap.get(mSelectedModelId).detector = detector;
}
private synchronized SoundTriggerDetector getDetector() {
- if (mSelectedModelId == 2) return mDetector2;
- if (mSelectedModelId == 3) return mDetector3;
- return mDetector1;
+ return mModelInfoMap.get(mSelectedModelId).detector;
}
private void screenWakeup() {
@@ -127,25 +221,29 @@
mScreenWakelock.release();
}
+ /** TODO: Should return the abstract sound model that can be then sent to the service. */
+ private GenericSoundModel createNewSoundModel() {
+ ModelInfo modelInfo = mModelInfoMap.get(mSelectedModelId);
+ return new GenericSoundModel(modelInfo.modelUuid, modelInfo.vendorUuid,
+ modelInfo.modelData);
+ }
+
/**
* Called when the user clicks the enroll button.
* Performs a fresh enrollment.
*/
public void onEnrollButtonClicked(View v) {
postMessage("Loading model: " + mSelectedModelId);
- // Generate a fake model to push.
- byte[] data = new byte[1024];
- mRandom.nextBytes(data);
- UUID modelUuid = getSelectedUuid();
- GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data);
+
+ GenericSoundModel model = createNewSoundModel();
boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(model);
if (status) {
Toast.makeText(
- this, "Successfully created sound trigger model UUID=" + modelUuid,
+ this, "Successfully created sound trigger model UUID=" + model.uuid,
Toast.LENGTH_SHORT).show();
} else {
- Toast.makeText(this, "Failed to enroll!!!" + modelUuid, Toast.LENGTH_SHORT).show();
+ Toast.makeText(this, "Failed to enroll!!!" + model.uuid, Toast.LENGTH_SHORT).show();
}
// Test the SoundManager API.
@@ -185,11 +283,7 @@
Toast.makeText(this, "Sound model not found!!!", Toast.LENGTH_SHORT).show();
return;
}
- // Generate a fake model to push.
- byte[] data = new byte[2048];
- mRandom.nextBytes(data);
- GenericSoundModel updated = new GenericSoundModel(soundModel.uuid,
- soundModel.vendorUuid, data);
+ GenericSoundModel updated = createNewSoundModel();
boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(updated);
if (status) {
Toast.makeText(this, "Successfully re-enrolled, model UUID=" + updated.uuid,
@@ -237,29 +331,32 @@
public synchronized void onRadioButtonClicked(View view) {
// Is the button now checked?
boolean checked = ((RadioButton) view).isChecked();
- // Check which radio button was clicked
- switch(view.getId()) {
- case R.id.model_one:
- if (checked) {
- mSelectedModelId = 1;
- postMessage("Selected model one.");
- }
- break;
- case R.id.model_two:
- if (checked) {
- mSelectedModelId = 2;
- postMessage("Selected model two.");
- }
- break;
- case R.id.model_three:
- if (checked) {
- mSelectedModelId = 3;
- postMessage("Selected model three.");
- }
- break;
+ if (checked) {
+ mSelectedModelId = mModelIdMap.get(view);
+ ModelInfo modelInfo = mModelInfoMap.get(mSelectedModelId);
+ postMessage("Selected " + modelInfo.name);
+
+ // Set the play trigger button to be enabled only if we actually have some audio.
+ mPlayTriggerButton.setEnabled(modelInfo.triggerAudioPlayer != null);
}
}
+ public synchronized void onPlayTriggerButtonClicked(View v) {
+ ModelInfo modelInfo = mModelInfoMap.get(mSelectedModelId);
+ modelInfo.triggerAudioPlayer.start();
+ postMessage("Playing trigger audio for " + modelInfo.name);
+ }
+
+ // Helper struct for holding information about a model.
+ private static class ModelInfo {
+ public String name;
+ public UUID modelUuid;
+ public UUID vendorUuid;
+ public MediaPlayer triggerAudioPlayer;
+ public SoundTriggerDetector detector;
+ public byte modelData[];
+ };
+
// Implementation of SoundTriggerDetector.Callback.
public class DetectorCallback extends SoundTriggerDetector.Callback {
public void onAvailabilityChanged(int status) {
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 6c8be39..a4aab7c 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -25,6 +25,7 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
+import android.media.AudioAttributes;
import android.os.Bundle;
import android.os.Vibrator;
import android.os.Handler;
@@ -86,6 +87,28 @@
}
private Test[] mTests = new Test[] {
+ new Test("Phone call") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("phone call")
+ .setLights(0xff0000ff, 1, 0)
+ .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
+ .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+ getPackageName() + "/raw/ringer"),
+ new AudioAttributes.Builder().setUsage(
+ AudioAttributes.USAGE_NOTIFICATION_RINGTONE).build())
+ .setPriority(Notification.PRIORITY_MAX)
+ .setVibrate(new long[] {
+ 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
+ 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
+ 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400 })
+ .setFullScreenIntent(makeIntent2(), true)
+ .build();
+ mNM.notify(7001, n);
+ }
+ },
new Test("Post a group") {
public void run()
{
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
index 005a483..c1f0038 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
@@ -37,6 +37,8 @@
final int parentLeft, parentTop;
final Matrix matrix;
final String className;
+ final float textSize;
+ final int textColor;
final CharSequence text;
final int scrollY;
final int[] lineCharOffsets;
@@ -50,6 +52,8 @@
this.parentTop = parentTop;
this.matrix = new Matrix(matrix);
this.className = node.getClassName();
+ this.textSize = node.getTextSize();
+ this.textColor = node.getTextColor();
this.text = node.getText() != null ? node.getText() : node.getContentDescription();
this.scrollY = node.getScrollY();
this.lineCharOffsets = node.getTextLineCharOffsets();
@@ -113,7 +117,9 @@
TextEntry te = mTextRects.get(i);
Log.d(TAG, "View " + te.className + " " + te.bounds.toShortString()
+ " in " + te.parentLeft + "," + te.parentTop
- + " matrix=" + te.matrix.toShortString() + ": "
+ + " matrix=" + te.matrix.toShortString()
+ + " size=" + te.textSize + " color=#" + Integer.toHexString(te.textColor)
+ + ": "
+ te.text);
if (te.lineCharOffsets != null && te.lineBaselines != null) {
final int num = te.lineCharOffsets.length < te.lineBaselines.length
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
index 450334c..5767f11 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
@@ -194,6 +194,18 @@
}
@Override
+ public void onHandleAssistSecondary(final Bundle data, final AssistStructure structure,
+ final AssistContent content, int index, int count) {
+ Log.i(TAG, "Got secondary activity assist data " + index + " of " + count);
+ Log.i(TAG, "Showing assist structure after a few seconds...");
+ mContentView.postDelayed(new Runnable() {
+ public void run() {
+ onHandleAssist(data, structure, content);
+ }
+ }, 2000 * index);
+ }
+
+ @Override
public void onHandleScreenshot(Bitmap screenshot) {
if (screenshot != null) {
mScreenshot.setImageBitmap(screenshot);
diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py
index b5ed1b5..81ab3cc 100755
--- a/tools/fonts/fontchain_lint.py
+++ b/tools/fonts/fontchain_lint.py
@@ -1,13 +1,17 @@
#!/usr/bin/env python
import collections
+import copy
import glob
+import itertools
from os import path
import sys
from xml.etree import ElementTree
from fontTools import ttLib
+EMOJI_VS = 0xFE0F
+
LANG_TO_SCRIPT = {
'as': 'Beng',
'bn': 'Beng',
@@ -57,13 +61,26 @@
return LANG_TO_SCRIPT[lang]
-def get_best_cmap(font):
+def printable(inp):
+ if type(inp) is set: # set of character sequences
+ return '{' + ', '.join([printable(seq) for seq in inp]) + '}'
+ if type(inp) is tuple: # character sequence
+ return '<' + (', '.join([printable(ch) for ch in inp])) + '>'
+ else: # single character
+ return 'U+%04X' % inp
+
+
+def open_font(font):
font_file, index = font
font_path = path.join(_fonts_dir, font_file)
if index is not None:
- ttfont = ttLib.TTFont(font_path, fontNumber=index)
+ return ttLib.TTFont(font_path, fontNumber=index)
else:
- ttfont = ttLib.TTFont(font_path)
+ return ttLib.TTFont(font_path)
+
+
+def get_best_cmap(font):
+ ttfont = open_font(font)
all_unicode_cmap = None
bmp_cmap = None
for cmap in ttfont['cmap'].tables:
@@ -79,6 +96,52 @@
return all_unicode_cmap.cmap if all_unicode_cmap else bmp_cmap.cmap
+def get_variation_sequences_cmap(font):
+ ttfont = open_font(font)
+ vs_cmap = None
+ for cmap in ttfont['cmap'].tables:
+ specifier = (cmap.format, cmap.platformID, cmap.platEncID)
+ if specifier == (14, 0, 5):
+ assert vs_cmap is None, 'More than one VS cmap in %s' % (font, )
+ vs_cmap = cmap
+ return vs_cmap
+
+
+def get_emoji_map(font):
+ # Add normal characters
+ emoji_map = copy.copy(get_best_cmap(font))
+ reverse_cmap = {glyph: code for code, glyph in emoji_map.items()}
+
+ # Add variation sequences
+ vs_dict = get_variation_sequences_cmap(font).uvsDict
+ for vs in vs_dict:
+ for base, glyph in vs_dict[vs]:
+ if glyph is None:
+ emoji_map[(base, vs)] = emoji_map[base]
+ else:
+ emoji_map[(base, vs)] = glyph
+
+ # Add GSUB rules
+ ttfont = open_font(font)
+ for lookup in ttfont['GSUB'].table.LookupList.Lookup:
+ assert lookup.LookupType == 4, 'We only understand type 4 lookups'
+ for subtable in lookup.SubTable:
+ ligatures = subtable.ligatures
+ for first_glyph in ligatures:
+ for ligature in ligatures[first_glyph]:
+ sequence = [first_glyph] + ligature.Component
+ sequence = [reverse_cmap[glyph] for glyph in sequence]
+ sequence = tuple(sequence)
+ # Make sure no starting subsequence of 'sequence' has been
+ # seen before.
+ for sub_len in range(2, len(sequence)+1):
+ subsequence = sequence[:sub_len]
+ assert subsequence not in emoji_map
+ emoji_map[sequence] = ligature.LigGlyph
+
+ return emoji_map
+
+
def assert_font_supports_any_of_chars(font, chars):
best_cmap = get_best_cmap(font)
for char in chars:
@@ -101,6 +164,13 @@
'U+%04X was found in %s' % (char, font))
+def assert_font_supports_all_sequences(font, sequences):
+ vs_dict = get_variation_sequences_cmap(font).uvsDict
+ for base, vs in sorted(sequences):
+ assert vs in vs_dict and (base, None) in vs_dict[vs], (
+ '<U+%04X, U+%04X> was not found in %s' % (base, vs, font))
+
+
def check_hyphens(hyphens_dir):
# Find all the scripts that need automatic hyphenation
scripts = set()
@@ -119,6 +189,16 @@
assert_font_supports_any_of_chars(font, HYPHENS)
+class FontRecord(object):
+ def __init__(self, name, scripts, variant, weight, style, font):
+ self.name = name
+ self.scripts = scripts
+ self.variant = variant
+ self.weight = weight
+ self.style = style
+ self.font = font
+
+
def parse_fonts_xml(fonts_xml_path):
global _script_to_font_map, _fallback_chain
_script_to_font_map = collections.defaultdict(set)
@@ -159,7 +239,7 @@
if index:
index = int(index)
- _fallback_chain.append((
+ _fallback_chain.append(FontRecord(
name,
frozenset(scripts),
variant,
@@ -175,39 +255,72 @@
_script_to_font_map[script].add((font_file, index))
-def check_emoji_availability():
- emoji_fonts = [font[5] for font in _fallback_chain if 'Zsye' in font[1]]
+def check_emoji_coverage(all_emoji, equivalent_emoji):
+ emoji_fonts = [
+ record.font for record in _fallback_chain
+ if 'Zsye' in record.scripts]
assert len(emoji_fonts) == 1, 'There are %d emoji fonts.' % len(emoji_fonts)
emoji_font = emoji_fonts[0]
- emoji_chars = _emoji_properties['Emoji']
- assert_font_supports_all_of_chars(emoji_font, emoji_chars)
+ coverage = get_emoji_map(emoji_font)
+
+ for sequence in all_emoji:
+ assert sequence in coverage, (
+ '%s is not supported in the emoji font.' % printable(sequence))
+
+ for sequence in coverage:
+ if sequence in {0x0000, 0x000D, 0x0020}:
+ # The font needs to support a few extra characters, which is OK
+ continue
+ assert sequence in all_emoji, (
+ 'Emoji font should not support %s.' % printable(sequence))
+
+ for first, second in sorted(equivalent_emoji.items()):
+ assert coverage[first] == coverage[second], (
+ '%s and %s should map to the same glyph.' % (
+ printable(first),
+ printable(second)))
+
+ for glyph in set(coverage.values()):
+ maps_to_glyph = [seq for seq in coverage if coverage[seq] == glyph]
+ if len(maps_to_glyph) > 1:
+ # There are more than one sequences mapping to the same glyph. We
+ # need to make sure they were expected to be equivalent.
+ equivalent_seqs = set()
+ for seq in maps_to_glyph:
+ equivalent_seq = seq
+ while equivalent_seq in equivalent_emoji:
+ equivalent_seq = equivalent_emoji[equivalent_seq]
+ equivalent_seqs.add(equivalent_seq)
+ assert len(equivalent_seqs) == 1, (
+ 'The sequences %s should not result in the same glyph %s' % (
+ printable(equivalent_seqs),
+ glyph))
-def check_emoji_defaults():
- default_emoji_chars = _emoji_properties['Emoji_Presentation']
- missing_text_chars = _emoji_properties['Emoji'] - default_emoji_chars
+def check_emoji_defaults(default_emoji):
+ missing_text_chars = _emoji_properties['Emoji'] - default_emoji
emoji_font_seen = False
- for name, scripts, variant, weight, style, font in _fallback_chain:
- if 'Zsye' in scripts:
+ for record in _fallback_chain:
+ if 'Zsye' in record.scripts:
emoji_font_seen = True
# No need to check the emoji font
continue
# For later fonts, we only check them if they have a script
# defined, since the defined script may get them to a higher
# score even if they appear after the emoji font.
- if emoji_font_seen and not scripts:
+ if emoji_font_seen and not record.scripts:
continue
# Check default emoji-style characters
- assert_font_supports_none_of_chars(font, sorted(default_emoji_chars))
+ assert_font_supports_none_of_chars(record.font, sorted(default_emoji))
# Mark default text-style characters appearing in fonts above the emoji
# font as seen
if not emoji_font_seen:
- missing_text_chars -= set(get_best_cmap(font))
+ missing_text_chars -= set(get_best_cmap(record.font))
- # Noto does not have monochrome symbols for Unicode 7.0 wingdings and
- # webdings
+ # Noto does not have monochrome glyphs for Unicode 7.0 wingdings and
+ # webdings yet.
missing_text_chars -= _chars_by_age['7.0']
# TODO: Remove these after b/26113320 is fixed
missing_text_chars -= {
@@ -236,31 +349,175 @@
line = line.strip()
if not line:
continue
- char_range, prop = line.split(';')
- char_range = char_range.strip()
+
+ chars, prop = line.split(';')
+ chars = chars.strip()
prop = prop.strip()
- if '..' in char_range:
- char_start, char_end = char_range.split('..')
- else:
- char_start = char_end = char_range
- char_start = int(char_start, 16)
- char_end = int(char_end, 16)
- char_range = xrange(char_start, char_end+1)
+
+ if ' ' in chars: # character sequence
+ sequence = [int(ch, 16) for ch in chars.split(' ')]
+ additions = [tuple(sequence)]
+ elif '..' in chars: # character range
+ char_start, char_end = chars.split('..')
+ char_start = int(char_start, 16)
+ char_end = int(char_end, 16)
+ additions = xrange(char_start, char_end+1)
+ else: # singe character
+ additions = [int(chars, 16)]
if reverse:
- output_dict[prop].update(char_range)
+ output_dict[prop].update(additions)
else:
- for char in char_range:
- assert char not in output_dict
- output_dict[char] = prop
+ for addition in additions:
+ assert addition not in output_dict
+ output_dict[addition] = prop
return output_dict
+def parse_standardized_variants(file_path):
+ emoji_set = set()
+ text_set = set()
+ with open(file_path) as datafile:
+ for line in datafile:
+ if '#' in line:
+ line = line[:line.index('#')]
+ line = line.strip()
+ if not line:
+ continue
+ sequence, description, _ = line.split(';')
+ sequence = sequence.strip().split(' ')
+ base = int(sequence[0], 16)
+ vs = int(sequence[1], 16)
+ description = description.strip()
+ if description == 'text style':
+ text_set.add((base, vs))
+ elif description == 'emoji style':
+ emoji_set.add((base, vs))
+ return text_set, emoji_set
+
+
def parse_ucd(ucd_path):
global _emoji_properties, _chars_by_age
+ global _text_variation_sequences, _emoji_variation_sequences
+ global _emoji_sequences, _emoji_zwj_sequences
_emoji_properties = parse_unicode_datafile(
path.join(ucd_path, 'emoji-data.txt'), reverse=True)
_chars_by_age = parse_unicode_datafile(
path.join(ucd_path, 'DerivedAge.txt'), reverse=True)
+ sequences = parse_standardized_variants(
+ path.join(ucd_path, 'StandardizedVariants.txt'))
+ _text_variation_sequences, _emoji_variation_sequences = sequences
+ _emoji_sequences = parse_unicode_datafile(
+ path.join(ucd_path, 'emoji-sequences.txt'))
+ _emoji_zwj_sequences = parse_unicode_datafile(
+ path.join(ucd_path, 'emoji-zwj-sequences.txt'))
+
+
+def flag_sequence(territory_code):
+ return tuple(0x1F1E6 + ord(ch) - ord('A') for ch in territory_code)
+
+
+UNSUPPORTED_FLAGS = frozenset({
+ flag_sequence('BL'), flag_sequence('BQ'), flag_sequence('DG'),
+ flag_sequence('EA'), flag_sequence('EH'), flag_sequence('FK'),
+ flag_sequence('GF'), flag_sequence('GP'), flag_sequence('GS'),
+ flag_sequence('MF'), flag_sequence('MQ'), flag_sequence('NC'),
+ flag_sequence('PM'), flag_sequence('RE'), flag_sequence('TF'),
+ flag_sequence('WF'), flag_sequence('XK'), flag_sequence('YT'),
+})
+
+EQUIVALENT_FLAGS = {
+ flag_sequence('BV'): flag_sequence('NO'),
+ flag_sequence('CP'): flag_sequence('FR'),
+ flag_sequence('HM'): flag_sequence('AU'),
+ flag_sequence('SJ'): flag_sequence('NO'),
+ flag_sequence('UM'): flag_sequence('US'),
+}
+
+COMBINING_KEYCAP = 0x20E3
+
+LEGACY_ANDROID_EMOJI = {
+ 0xFE4E5: flag_sequence('JP'),
+ 0xFE4E6: flag_sequence('US'),
+ 0xFE4E7: flag_sequence('FR'),
+ 0xFE4E8: flag_sequence('DE'),
+ 0xFE4E9: flag_sequence('IT'),
+ 0xFE4EA: flag_sequence('GB'),
+ 0xFE4EB: flag_sequence('ES'),
+ 0xFE4EC: flag_sequence('RU'),
+ 0xFE4ED: flag_sequence('CN'),
+ 0xFE4EE: flag_sequence('KR'),
+ 0xFE82C: (ord('#'), COMBINING_KEYCAP),
+ 0xFE82E: (ord('1'), COMBINING_KEYCAP),
+ 0xFE82F: (ord('2'), COMBINING_KEYCAP),
+ 0xFE830: (ord('3'), COMBINING_KEYCAP),
+ 0xFE831: (ord('4'), COMBINING_KEYCAP),
+ 0xFE832: (ord('5'), COMBINING_KEYCAP),
+ 0xFE833: (ord('6'), COMBINING_KEYCAP),
+ 0xFE834: (ord('7'), COMBINING_KEYCAP),
+ 0xFE835: (ord('8'), COMBINING_KEYCAP),
+ 0xFE836: (ord('9'), COMBINING_KEYCAP),
+ 0xFE837: (ord('0'), COMBINING_KEYCAP),
+}
+
+ZWJ_IDENTICALS = {
+ # KISS
+ (0x1F469, 0x200D, 0x2764, 0x200D, 0x1F48B, 0x200D, 0x1F468): 0x1F48F,
+ # COUPLE WITH HEART
+ (0x1F469, 0x200D, 0x2764, 0x200D, 0x1F468): 0x1F491,
+ # FAMILY
+ (0x1F468, 0x200D, 0x1F469, 0x200D, 0x1F466): 0x1F46A,
+}
+
+def compute_expected_emoji():
+ equivalent_emoji = {}
+ sequence_pieces = set()
+ all_sequences = set()
+ all_sequences.update(_emoji_variation_sequences)
+
+ for sequence in _emoji_sequences.keys():
+ sequence = tuple(ch for ch in sequence if ch != EMOJI_VS)
+ all_sequences.add(sequence)
+ sequence_pieces.update(sequence)
+
+ for sequence in _emoji_zwj_sequences.keys():
+ sequence = tuple(ch for ch in sequence if ch != EMOJI_VS)
+ all_sequences.add(sequence)
+ sequence_pieces.update(sequence)
+ # Add reverse of all emoji ZWJ sequences, which are added to the fonts
+ # as a workaround to get the sequences work in RTL text.
+ reversed_seq = tuple(reversed(sequence))
+ all_sequences.add(reversed_seq)
+ equivalent_emoji[reversed_seq] = sequence
+
+ # Add all two-letter flag sequences, as even the unsupported ones should
+ # resolve to a flag tofu.
+ all_letters = [chr(code) for code in range(ord('A'), ord('Z')+1)]
+ all_two_letter_codes = itertools.product(all_letters, repeat=2)
+ all_flags = {flag_sequence(code) for code in all_two_letter_codes}
+ all_sequences.update(all_flags)
+ tofu_flags = UNSUPPORTED_FLAGS | (all_flags - set(_emoji_sequences.keys()))
+
+ all_emoji = (
+ _emoji_properties['Emoji'] |
+ all_sequences |
+ sequence_pieces |
+ set(LEGACY_ANDROID_EMOJI.keys()))
+ default_emoji = (
+ _emoji_properties['Emoji_Presentation'] |
+ all_sequences |
+ set(LEGACY_ANDROID_EMOJI.keys()))
+
+ first_tofu_flag = sorted(tofu_flags)[0]
+ for flag in tofu_flags:
+ if flag != first_tofu_flag:
+ equivalent_emoji[flag] = first_tofu_flag
+ equivalent_emoji.update(EQUIVALENT_FLAGS)
+ equivalent_emoji.update(LEGACY_ANDROID_EMOJI)
+ equivalent_emoji.update(ZWJ_IDENTICALS)
+ for seq in _emoji_variation_sequences:
+ equivalent_emoji[seq] = seq[0]
+
+ return all_emoji, default_emoji, equivalent_emoji
def main():
@@ -278,8 +535,9 @@
if check_emoji == 'true':
ucd_path = sys.argv[3]
parse_ucd(ucd_path)
- check_emoji_availability()
- check_emoji_defaults()
+ all_emoji, default_emoji, equivalent_emoji = compute_expected_emoji()
+ check_emoji_coverage(all_emoji, equivalent_emoji)
+ check_emoji_defaults(default_emoji)
if __name__ == '__main__':
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index 7412bc2..50efc7f 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -245,6 +245,13 @@
return sFontLocation;
}
+ // ---- delegate methods ----
+ @LayoutlibDelegate
+ /*package*/ static boolean addFont(FontFamily thisFontFamily, String path, int ttcIndex) {
+ final FontFamily_Delegate delegate = getDelegate(thisFontFamily.mNativePtr);
+ return delegate != null && delegate.addFont(path, ttcIndex);
+ }
+
// ---- native methods ----
@LayoutlibDelegate
@@ -270,16 +277,8 @@
}
@LayoutlibDelegate
- /*package*/ static boolean nAddFont(long nativeFamily, final String path, int ttcIndex) {
- // FIXME: support ttc fonts. Hack JRE??
- final FontFamily_Delegate delegate = getDelegate(nativeFamily);
- if (delegate != null) {
- if (sFontLocation == null) {
- delegate.mPostInitRunnables.add(() -> delegate.addFont(path));
- return true;
- }
- return delegate.addFont(path);
- }
+ /*package*/ static boolean nAddFont(long nativeFamily, ByteBuffer font, int ttcIndex) {
+ assert false : "The only client of this method has been overriden.";
return false;
}
@@ -390,6 +389,15 @@
mPostInitRunnables = null;
}
+ private boolean addFont(final String path, int ttcIndex) {
+ // FIXME: support ttc fonts. Hack JRE??
+ if (sFontLocation == null) {
+ mPostInitRunnables.add(() -> addFont(path));
+ return true;
+ }
+ return addFont(path);
+ }
+
private boolean addFont(@NonNull String path) {
return addFont(path, DEFAULT_FONT_WEIGHT, path.endsWith(FONT_SUFFIX_ITALIC));
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
index d8ff57b..7fa7235 100644
--- a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
@@ -90,7 +90,7 @@
}
@LayoutlibDelegate
- static long nCreateRenderer(long rootGroupPtr) {
+ static long nCreateTree(long rootGroupPtr) {
VGroup_Delegate rootGroup = VNativeObject.getDelegate(rootGroupPtr);
return sPathManager.addNewDelegate(new VPathRenderer_Delegate(rootGroup));
}
diff --git a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
index 6c34c70..6d3bb4c 100644
--- a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
@@ -64,15 +64,14 @@
}
@LayoutlibDelegate
- /*package*/ static boolean nParseStringForPath(long pathPtr, @NonNull String pathString, int
+ /*package*/ static void nParseStringForPath(long pathPtr, @NonNull String pathString, int
stringLength) {
Path_Delegate path_delegate = Path_Delegate.getDelegate(pathPtr);
if (path_delegate == null) {
- return false;
+ return;
}
assert pathString.length() == stringLength;
PathDataNode.nodesToPath(createNodesFromPathData(pathString), path_delegate);
- return true;
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 9e50ee8..3b88290 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -537,7 +537,7 @@
* Note that while this can be called several time, the first call to {@link #cleanupThread()}
* will do the clean-up, and make the thread unable to do further scene actions.
*/
- public static void prepareThread() {
+ public synchronized static void prepareThread() {
// we need to make sure the Looper has been initialized for this thread.
// this is required for View that creates Handler objects.
if (Looper.myLooper() == null) {
@@ -551,7 +551,7 @@
* Note that it doesn't matter how many times {@link #prepareThread()} was called, a single
* call to this will prevent the thread from doing further scene actions
*/
- public static void cleanupThread() {
+ public synchronized static void cleanupThread() {
// clean up the looper
Looper_Accessor.cleanupThread();
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
index fea633e..e0d8249 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
@@ -24,6 +24,7 @@
import com.android.ide.common.rendering.api.ViewInfo;
import com.android.layoutlib.bridge.impl.RenderSessionImpl;
import com.android.tools.layoutlib.java.System_Delegate;
+import com.android.util.PropertiesMap;
import android.view.View;
import android.view.ViewGroup;
@@ -70,20 +71,8 @@
}
@Override
- public Map<String, String> getDefaultProperties(Object viewObject) {
- return mSession.getDefaultProperties(viewObject);
- }
-
- @Override
- public Result getProperty(Object objectView, String propertyName) {
- // pass
- return super.getProperty(objectView, propertyName);
- }
-
- @Override
- public Result setProperty(Object objectView, String propertyName, String propertyValue) {
- // pass
- return super.setProperty(objectView, propertyName, propertyValue);
+ public Map<Object, PropertiesMap> getDefaultProperties() {
+ return mSession.getDefaultProperties();
}
@Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 89272fa..80e230c 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
@@ -32,6 +32,8 @@
import com.android.layoutlib.bridge.impl.Stack;
import com.android.resources.ResourceType;
import com.android.util.Pair;
+import com.android.util.PropertiesMap;
+import com.android.util.PropertiesMap.Property;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -152,7 +154,6 @@
private IBinder mBinder;
private PackageManager mPackageManager;
-
/**
* Some applications that target both pre API 17 and post API 17, set the newer attrs to
* reference the older ones. For example, android:paddingStart will resolve to
@@ -275,8 +276,8 @@
return mRenderResources;
}
- public Map<String, String> getDefaultPropMap(Object key) {
- return mDefaultPropMaps.get(key);
+ public Map<Object, PropertiesMap> getDefaultProperties() {
+ return mDefaultPropMaps;
}
public Configuration getConfiguration() {
@@ -731,16 +732,10 @@
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE,
"Failed to find the style corresponding to the id " + defStyleAttr, null);
} else {
- if (defaultPropMap != null) {
- String defStyleName = defStyleAttribute.getFirst();
- if (defStyleAttribute.getSecond()) {
- defStyleName = "android:" + defStyleName;
- }
- defaultPropMap.put("style", defStyleName);
- }
+ String defStyleName = defStyleAttribute.getFirst();
// look for the style in the current theme, and its parent:
- ResourceValue item = mRenderResources.findItemInTheme(defStyleAttribute.getFirst(),
+ ResourceValue item = mRenderResources.findItemInTheme(defStyleName,
defStyleAttribute.getSecond());
if (item != null) {
@@ -750,6 +745,12 @@
if (item instanceof StyleResourceValue) {
defStyleValues = (StyleResourceValue) item;
}
+ if (defaultPropMap != null) {
+ if (defStyleAttribute.getSecond()) {
+ defStyleName = "android:" + defStyleName;
+ }
+ defaultPropMap.put("style", new Property(defStyleName, item.getValue()));
+ }
} else {
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR,
String.format(
@@ -776,7 +777,8 @@
item = mRenderResources.getStyle(value.getSecond(), isFrameworkRes);
if (item != null) {
if (defaultPropMap != null) {
- defaultPropMap.put("style", item.getName());
+ String name = item.getName();
+ defaultPropMap.put("style", new Property(name, name));
}
defStyleValues = item;
@@ -855,13 +857,14 @@
// if we found a value, we make sure this doesn't reference another value.
// So we resolve it.
if (resValue != null) {
- // put the first default value, before the resolution.
- if (defaultPropMap != null) {
- defaultPropMap.put(attrName, resValue.getValue());
- }
-
+ String preResolve = resValue.getValue();
resValue = mRenderResources.resolveResValue(resValue);
+ if (defaultPropMap != null) {
+ defaultPropMap.put(attrName,
+ new Property(preResolve, resValue.getValue()));
+ }
+
// If the value is a reference to another theme attribute that doesn't
// exist, we should log a warning and omit it.
String val = resValue.getValue();
@@ -949,10 +952,11 @@
if (resValue != null) {
// Add it to defaultPropMap before resolving
- defaultPropMap.put(attrName, resValue.getValue());
+ String preResolve = resValue.getValue();
// resolve it to make sure there are no references left.
- ta.bridgeSetValue(i, attrName, attribute.getSecond(),
- mRenderResources.resolveResValue(resValue));
+ resValue = mRenderResources.resolveResValue(resValue);
+ ta.bridgeSetValue(i, attrName, attribute.getSecond(), resValue);
+ defaultPropMap.put(attrName, new Property(preResolve, resValue.getValue()));
}
}
}
@@ -1858,7 +1862,6 @@
return false;
}
-
/**
* The cached value depends on
* <ol>
@@ -1915,11 +1918,4 @@
}
}
-
- /**
- * An alias used for the value in {@code {@link #mDefaultPropMaps}}
- */
- private static class PropertiesMap extends HashMap<String, String> {
- }
-
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 42c0ae0..0a64b63 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -645,6 +645,11 @@
}
@Override
+ public void deleteApplicationCacheFilesAsUser(String packageName, int userId,
+ IPackageDataObserver observer) {
+ }
+
+ @Override
public void freeStorageAndNotify(String volumeUuid, long freeStorageSize,
IPackageDataObserver observer) {
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 866b248..3ef568c 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -48,6 +48,7 @@
import com.android.resources.ResourceType;
import com.android.tools.layoutlib.java.System_Delegate;
import com.android.util.Pair;
+import com.android.util.PropertiesMap;
import android.animation.AnimationThread;
import android.animation.Animator;
@@ -1415,8 +1416,8 @@
return mSystemViewInfoList;
}
- public Map<String, String> getDefaultProperties(Object viewObject) {
- return getContext().getDefaultPropMap(viewObject);
+ public Map<Object, PropertiesMap> getDefaultProperties() {
+ return getContext().getDefaultProperties();
}
public void setScene(RenderSession session) {
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 483bddc..061bed7 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -192,6 +192,7 @@
"android.graphics.BitmapFactory#setDensityFromOptions",
"android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT#useLastSeenTarget",
"android.graphics.drawable.GradientDrawable#buildRing",
+ "android.graphics.FontFamily#addFont",
"android.graphics.Typeface#getSystemFontConfigLocation",
"android.graphics.Typeface#makeFamilyFromParsed",
"android.os.Handler#sendMessageAtTime",
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 0f84506..be5b8fc 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -149,7 +149,7 @@
void setAllowScansWithTraffic(int enabled);
int getAllowScansWithTraffic();
- boolean enableAutoJoinWhenAssociated(boolean enabled);
+ boolean setEnableAutoJoinWhenAssociated(boolean enabled);
boolean getEnableAutoJoinWhenAssociated();
void enableWifiConnectivityManager(boolean enabled);
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index fb2bdd4..b8ef150 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1636,6 +1636,9 @@
if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
keyMgmt = KeyMgmt.strings[KeyMgmt.WPA_EAP];
}
+ if (allowedKeyManagement.get(KeyMgmt.OSEN)) {
+ keyMgmt = KeyMgmt.strings[KeyMgmt.OSEN];
+ }
if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X];
}
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 394934f..b614a86 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -437,6 +437,7 @@
switch (eapMethod) {
/** Valid methods */
case Eap.TLS:
+ case Eap.UNAUTH_TLS:
setPhase2Method(Phase2.NONE);
/* fall through */
case Eap.PEAP:
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 6984fe2..1cd32b6 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -2700,9 +2700,9 @@
* @return true -- if set successful false -- if set failed
* @hide
*/
- public boolean enableAutoJoinWhenAssociated(boolean enabled) {
+ public boolean setEnableAutoJoinWhenAssociated(boolean enabled) {
try {
- return mService.enableAutoJoinWhenAssociated(enabled);
+ return mService.setEnableAutoJoinWhenAssociated(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 f8c1ea3..1a8197c 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -687,7 +687,7 @@
Bundle scanParams = new Bundle();
scanParams.putParcelable(SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
scanParams.putParcelable(SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
- sAsyncChannel.sendMessage(CMD_START_BACKGROUND_SCAN, 0, key, scanParams);
+ mAsyncChannel.sendMessage(CMD_START_BACKGROUND_SCAN, 0, key, scanParams);
}
/**
@@ -700,7 +700,7 @@
int key = removeListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
- sAsyncChannel.sendMessage(CMD_STOP_BACKGROUND_SCAN, 0, key);
+ mAsyncChannel.sendMessage(CMD_STOP_BACKGROUND_SCAN, 0, key);
}
/**
* reports currently available scan results on appropriate listeners
@@ -708,7 +708,7 @@
*/
public boolean getScanResults() {
validateChannel();
- Message reply = sAsyncChannel.sendMessageSynchronously(CMD_GET_SCAN_RESULTS, 0);
+ Message reply = mAsyncChannel.sendMessageSynchronously(CMD_GET_SCAN_RESULTS, 0);
return reply.what == CMD_OP_SUCCEEDED;
}
@@ -741,7 +741,7 @@
Bundle scanParams = new Bundle();
scanParams.putParcelable(SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
scanParams.putParcelable(SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
- sAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, key, scanParams);
+ mAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, key, scanParams);
}
/**
@@ -754,7 +754,7 @@
int key = removeListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
- sAsyncChannel.sendMessage(CMD_STOP_SINGLE_SCAN, 0, key);
+ mAsyncChannel.sendMessage(CMD_STOP_SINGLE_SCAN, 0, key);
}
private void startPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings, int key) {
@@ -764,7 +764,7 @@
scanSettings.isPnoScan = true;
pnoParams.putParcelable(PNO_PARAMS_SCAN_SETTINGS_KEY, scanSettings);
pnoParams.putParcelable(PNO_PARAMS_PNO_SETTINGS_KEY, pnoSettings);
- sAsyncChannel.sendMessage(CMD_START_PNO_SCAN, 0, key, pnoParams);
+ mAsyncChannel.sendMessage(CMD_START_PNO_SCAN, 0, key, pnoParams);
}
/**
* Start wifi connected PNO scan
@@ -820,7 +820,7 @@
int key = removeListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
- sAsyncChannel.sendMessage(CMD_STOP_PNO_SCAN, 0, key);
+ mAsyncChannel.sendMessage(CMD_STOP_PNO_SCAN, 0, key);
}
/** specifies information about an access point of interest */
@@ -956,7 +956,7 @@
int key = addListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
- sAsyncChannel.sendMessage(CMD_START_TRACKING_CHANGE, 0, key);
+ mAsyncChannel.sendMessage(CMD_START_TRACKING_CHANGE, 0, key);
}
/**
@@ -968,14 +968,14 @@
int key = removeListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
- sAsyncChannel.sendMessage(CMD_STOP_TRACKING_CHANGE, 0, key);
+ mAsyncChannel.sendMessage(CMD_STOP_TRACKING_CHANGE, 0, key);
}
/** @hide */
@SystemApi
public void configureWifiChange(WifiChangeSettings settings) {
validateChannel();
- sAsyncChannel.sendMessage(CMD_CONFIGURE_WIFI_CHANGE, 0, 0, settings);
+ mAsyncChannel.sendMessage(CMD_CONFIGURE_WIFI_CHANGE, 0, 0, settings);
}
/** interface to receive hotlist events on; use this on {@link #setHotlist} */
@@ -1060,7 +1060,7 @@
HotlistSettings settings = new HotlistSettings();
settings.bssidInfos = bssidInfos;
settings.apLostThreshold = apLostThreshold;
- sAsyncChannel.sendMessage(CMD_SET_HOTLIST, 0, key, settings);
+ mAsyncChannel.sendMessage(CMD_SET_HOTLIST, 0, key, settings);
}
/**
@@ -1072,7 +1072,7 @@
int key = removeListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
- sAsyncChannel.sendMessage(CMD_RESET_HOTLIST, 0, key);
+ mAsyncChannel.sendMessage(CMD_RESET_HOTLIST, 0, key);
}
@@ -1137,17 +1137,14 @@
private IWifiScanner mService;
private static final int INVALID_KEY = 0;
- private static int sListenerKey = 1;
+ private int mListenerKey = 1;
- private static final SparseArray sListenerMap = new SparseArray();
- private static final Object sListenerMapLock = new Object();
+ private final SparseArray mListenerMap = new SparseArray();
+ private final Object mListenerMapLock = new Object();
- private static AsyncChannel sAsyncChannel;
- private static CountDownLatch sConnected;
-
- private static final Object sThreadRefLock = new Object();
- private static int sThreadRefCount;
- private static Handler sInternalHandler;
+ private AsyncChannel mAsyncChannel;
+ private final CountDownLatch mConnected;
+ private final Handler mInternalHandler;
/**
* Create a new WifiScanner instance.
@@ -1156,10 +1153,11 @@
* the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
* @param context the application context
* @param service the Binder interface
+ * @param looper the Looper used to deliver callbacks
* @hide
*/
- public WifiScanner(Context context, IWifiScanner service) {
- this(context, service, null, true);
+ public WifiScanner(Context context, IWifiScanner service, Looper looper) {
+ this(context, service, looper, true);
}
/**
@@ -1167,8 +1165,7 @@
*
* @param context The application context.
* @param service The IWifiScanner Binder interface
- * @param looper Looper for running WifiScanner operations. If null, a handler thread will be
- * created for running WifiScanner operations.
+ * @param looper the Looper used to deliver callbacks
* @param waitForConnection If true, this will not return until a connection to Wifi Scanner
* service is established.
* @hide
@@ -1178,50 +1175,34 @@
boolean waitForConnection) {
mContext = context;
mService = service;
- init(looper, waitForConnection);
- }
- private void init(Looper looper, boolean waitForConnection) {
- synchronized (sThreadRefLock) {
- if (++sThreadRefCount == 1) {
- Messenger messenger = null;
- try {
- messenger = mService.getMessenger();
- } catch (RemoteException e) {
- /* do nothing */
- } catch (SecurityException e) {
- /* do nothing */
- }
+ Messenger messenger = null;
+ try {
+ messenger = mService.getMessenger();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
- if (messenger == null) {
- sAsyncChannel = null;
- return;
- }
+ if (messenger == null) {
+ throw new IllegalStateException("getMessenger() returned null! This is invalid.");
+ }
- sAsyncChannel = new AsyncChannel();
- sConnected = new CountDownLatch(1);
+ mAsyncChannel = new AsyncChannel();
+ mConnected = new CountDownLatch(1);
- if (looper == null) {
- HandlerThread thread = new HandlerThread("WifiScanner");
- thread.start();
- sInternalHandler = new ServiceHandler(thread.getLooper());
- } else {
- sInternalHandler = new ServiceHandler(looper);
- }
- sAsyncChannel.connect(mContext, sInternalHandler, messenger);
- if (waitForConnection) {
- try {
- sConnected.await();
- } catch (InterruptedException e) {
- Log.e(TAG, "interrupted wait at init");
- }
- }
+ mInternalHandler = new ServiceHandler(looper);
+ mAsyncChannel.connect(mContext, mInternalHandler, messenger);
+ if (waitForConnection) {
+ try {
+ mConnected.await();
+ } catch (InterruptedException e) {
+ Log.e(TAG, "interrupted wait at init");
}
}
}
private void validateChannel() {
- if (sAsyncChannel == null) throw new IllegalStateException(
+ if (mAsyncChannel == null) throw new IllegalStateException(
"No permission to access and change wifi or a bad initialization");
}
@@ -1229,7 +1210,7 @@
// send an error message to internal handler; Otherwise add the listener to the listener map and
// return the key of the listener.
private int addListener(ActionListener listener) {
- synchronized (sListenerMap) {
+ synchronized (mListenerMapLock) {
boolean keyExists = (getListenerKey(listener) != INVALID_KEY);
// Note we need to put the listener into listener map even if it's a duplicate as the
// internal handler will need the key to find the listener. In case of duplicates,
@@ -1239,7 +1220,7 @@
if (DBG) Log.d(TAG, "listener key already exists");
OperationResult operationResult = new OperationResult(REASON_DUPLICATE_REQEUST,
"Outstanding request with same key not stopped yet");
- Message message = Message.obtain(sInternalHandler, CMD_OP_FAILED, 0, key,
+ Message message = Message.obtain(mInternalHandler, CMD_OP_FAILED, 0, key,
operationResult);
message.sendToTarget();
return INVALID_KEY;
@@ -1249,55 +1230,55 @@
}
}
- private static int putListener(Object listener) {
+ private int putListener(Object listener) {
if (listener == null) return INVALID_KEY;
int key;
- synchronized (sListenerMapLock) {
+ synchronized (mListenerMapLock) {
do {
- key = sListenerKey++;
+ key = mListenerKey++;
} while (key == INVALID_KEY);
- sListenerMap.put(key, listener);
+ mListenerMap.put(key, listener);
}
return key;
}
- private static Object getListener(int key) {
+ private Object getListener(int key) {
if (key == INVALID_KEY) return null;
- synchronized (sListenerMapLock) {
- Object listener = sListenerMap.get(key);
+ synchronized (mListenerMapLock) {
+ Object listener = mListenerMap.get(key);
return listener;
}
}
- private static int getListenerKey(Object listener) {
+ private int getListenerKey(Object listener) {
if (listener == null) return INVALID_KEY;
- synchronized (sListenerMapLock) {
- int index = sListenerMap.indexOfValue(listener);
+ synchronized (mListenerMapLock) {
+ int index = mListenerMap.indexOfValue(listener);
if (index == -1) {
return INVALID_KEY;
} else {
- return sListenerMap.keyAt(index);
+ return mListenerMap.keyAt(index);
}
}
}
- private static Object removeListener(int key) {
+ private Object removeListener(int key) {
if (key == INVALID_KEY) return null;
- synchronized (sListenerMapLock) {
- Object listener = sListenerMap.get(key);
- sListenerMap.remove(key);
+ synchronized (mListenerMapLock) {
+ Object listener = mListenerMap.get(key);
+ mListenerMap.remove(key);
return listener;
}
}
- private static int removeListener(Object listener) {
+ private int removeListener(Object listener) {
int key = getListenerKey(listener);
if (key == INVALID_KEY) {
Log.e(TAG, "listener cannot be found");
return key;
}
- synchronized (sListenerMapLock) {
- sListenerMap.remove(key);
+ synchronized (mListenerMapLock) {
+ mListenerMap.remove(key);
return key;
}
}
@@ -1338,7 +1319,7 @@
};
}
- private static class ServiceHandler extends Handler {
+ private class ServiceHandler extends Handler {
ServiceHandler(Looper looper) {
super(looper);
}
@@ -1347,14 +1328,14 @@
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
- sAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+ mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
} else {
Log.e(TAG, "Failed to set up channel connection");
// This will cause all further async API calls on the WifiManager
// to fail and throw an exception
- sAsyncChannel = null;
+ mAsyncChannel = null;
}
- sConnected.countDown();
+ mConnected.countDown();
return;
case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
return;
@@ -1362,7 +1343,7 @@
Log.e(TAG, "Channel connection lost");
// This will cause all further async API calls on the WifiManager
// to fail and throw an exception
- sAsyncChannel = null;
+ mAsyncChannel = null;
getLooper().quit();
return;
}