Merge "Fix issue where menu items visible on 'closed' notification on lockscreen" into oc-dev
diff --git a/Android.mk b/Android.mk
index 915f103..991d185 100644
--- a/Android.mk
+++ b/Android.mk
@@ -273,7 +273,6 @@
core/java/android/security/IKeystoreService.aidl \
core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl \
core/java/android/service/autofill/IAutoFillService.aidl \
- core/java/android/service/autofill/IAutoFillServiceConnection.aidl \
core/java/android/service/autofill/IFillCallback.aidl \
core/java/android/service/autofill/ISaveCallback.aidl \
core/java/android/service/carrier/ICarrierService.aidl \
@@ -310,6 +309,7 @@
core/java/android/companion/IFindDeviceCallback.aidl \
core/java/android/service/dreams/IDreamManager.aidl \
core/java/android/service/dreams/IDreamService.aidl \
+ core/java/android/service/oemlock/IOemLockService.aidl \
core/java/android/service/persistentdata/IPersistentDataBlockService.aidl \
core/java/android/service/trust/ITrustAgentService.aidl \
core/java/android/service/trust/ITrustAgentServiceCallback.aidl \
@@ -570,11 +570,11 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
framework-protos \
- android.hardware.health@1.0-java-constants \
- android.hardware.thermal@1.0-java-constants \
- android.hardware.tv.input@1.0-java-constants \
- android.hardware.usb@1.0-java-constants \
- android.hardware.vibrator@1.0-java-constants \
+ android.hardware.health-V1.0-java-constants \
+ android.hardware.thermal-V1.0-java-constants \
+ android.hardware.tv.input-V1.0-java-constants \
+ android.hardware.usb-V1.0-java-constants \
+ android.hardware.vibrator-V1.0-java-constants \
# Loaded with System.loadLibrary by android.view.textclassifier
LOCAL_REQUIRED_MODULES += libtextclassifier
diff --git a/api/current.txt b/api/current.txt
index 7c532d4..4149d03 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -210,6 +210,7 @@
public static final class R.attr {
ctor public R.attr();
field public static final int __removed1 = 16844099; // 0x1010543
+ field public static final int __removed2 = 16844104; // 0x1010548
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -471,6 +472,7 @@
field public static final deprecated int dayOfWeekBackground = 16843924; // 0x1010494
field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
field public static final int debuggable = 16842767; // 0x101000f
+ field public static final int defaultFocusHighlightEnabled = 16844133; // 0x1010565
field public static final int defaultHeight = 16844021; // 0x10104f5
field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
field public static final int defaultValue = 16843245; // 0x10101ed
@@ -991,6 +993,7 @@
field public static final int persistableMode = 16843821; // 0x101042d
field public static final int persistent = 16842765; // 0x101000d
field public static final int persistentDrawingCache = 16842990; // 0x10100ee
+ field public static final int persistentFeature = 16844134; // 0x1010566
field public static final deprecated int phoneNumber = 16843111; // 0x1010167
field public static final int pivotX = 16843189; // 0x10101b5
field public static final int pivotY = 16843190; // 0x10101b6
@@ -1269,7 +1272,6 @@
field public static final int summaryOff = 16843248; // 0x10101f0
field public static final int summaryOn = 16843247; // 0x10101ef
field public static final int supportsAssist = 16844016; // 0x10104f0
- field public static final int supportsDismissingWindow = 16844104; // 0x1010548
field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
field public static final int supportsLocalInteraction = 16844047; // 0x101050f
field public static final int supportsPictureInPicture = 16844023; // 0x10104f7
@@ -1539,6 +1541,7 @@
field public static final int windowShowAnimation = 16842934; // 0x10100b6
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
+ field public static final int windowSplashscreenContent = 16844135; // 0x1010567
field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
field public static final int windowTitleSize = 16842842; // 0x101005a
@@ -1951,6 +1954,7 @@
field public static final int no = 17039369; // 0x1040009
field public static final int ok = 17039370; // 0x104000a
field public static final int paste = 17039371; // 0x104000b
+ field public static final int paste_as_plain_text = 17039385; // 0x1040019
field public static final int search_go = 17039372; // 0x104000c
field public static final int selectAll = 17039373; // 0x104000d
field public static final int selectTextMode = 17039382; // 0x1040016
@@ -2996,6 +3000,7 @@
method public android.accounts.AccountManagerFuture<android.os.Bundle> startAddAccountSession(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> startUpdateCredentialsSession(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> updateCredentials(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+ field public static final java.lang.String ACTION_ACCOUNT_REMOVED = "android.accounts.action.ACCOUNT_REMOVED";
field public static final java.lang.String ACTION_AUTHENTICATOR_INTENT = "android.accounts.AccountAuthenticator";
field public static final java.lang.String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
field public static final java.lang.String AUTHENTICATOR_META_DATA_NAME = "android.accounts.AccountAuthenticator";
@@ -4695,7 +4700,7 @@
public abstract class FragmentContainer {
ctor public FragmentContainer();
method public android.app.Fragment instantiate(android.content.Context, java.lang.String, android.os.Bundle);
- method public abstract android.view.View onFindViewById(int);
+ method public abstract <T extends android.view.View> T onFindViewById(int);
method public abstract boolean onHasView();
}
@@ -4746,7 +4751,7 @@
ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
method public void onAttachFragment(android.app.Fragment);
method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
- method public android.view.View onFindViewById(int);
+ method public <T extends android.view.View> T onFindViewById(int);
method public abstract E onGetHost();
method public android.view.LayoutInflater onGetLayoutInflater();
method public int onGetWindowAnimations();
@@ -6788,6 +6793,7 @@
field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
field public static final int NETWORK_TYPE_ANY = 1; // 0x1
+ field public static final int NETWORK_TYPE_METERED = 4; // 0x4
field public static final int NETWORK_TYPE_NONE = 0; // 0x0
field public static final int NETWORK_TYPE_NOT_ROAMING = 3; // 0x3
field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
@@ -6826,6 +6832,8 @@
}
public class JobParameters implements android.os.Parcelable {
+ method public void completeWork(android.app.job.JobWorkItem);
+ method public android.app.job.JobWorkItem dequeueWork();
method public int describeContents();
method public android.content.ClipData getClipData();
method public int getClipGrantFlags();
@@ -6843,6 +6851,7 @@
ctor public JobScheduler();
method public abstract void cancel(int);
method public abstract void cancelAll();
+ method public abstract int enqueue(android.app.job.JobInfo, android.app.job.JobWorkItem);
method public abstract java.util.List<android.app.job.JobInfo> getAllPendingJobs();
method public abstract android.app.job.JobInfo getPendingJob(int);
method public abstract int schedule(android.app.job.JobInfo);
@@ -6859,6 +6868,15 @@
field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE";
}
+ public final class JobWorkItem implements android.os.Parcelable {
+ ctor public JobWorkItem(android.content.Intent);
+ ctor public JobWorkItem(android.os.Parcel);
+ method public int describeContents();
+ method public android.content.Intent getIntent();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.job.JobWorkItem> CREATOR;
+ }
+
}
package android.app.usage {
@@ -7591,9 +7609,11 @@
field public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; // 0x2
field public static final int PAIRING_VARIANT_PIN = 0; // 0x0
field public static final int PHY_LE_1M = 1; // 0x1
+ field public static final int PHY_LE_1M_MASK = 1; // 0x1
field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_ANY = 7; // 0x7
- field public static final int PHY_LE_CODED = 4; // 0x4
+ field public static final int PHY_LE_2M_MASK = 2; // 0x2
+ field public static final int PHY_LE_CODED = 3; // 0x3
+ field public static final int PHY_LE_CODED_MASK = 4; // 0x4
field public static final int PHY_OPTION_NO_PREFERRED = 0; // 0x0
field public static final int PHY_OPTION_S2 = 1; // 0x1
field public static final int PHY_OPTION_S8 = 2; // 0x2
@@ -8011,9 +8031,6 @@
field public static final int INTERVAL_MAX = 16777215; // 0xffffff
field public static final int INTERVAL_MEDIUM = 400; // 0x190
field public static final int INTERVAL_MIN = 160; // 0xa0
- field public static final int PHY_LE_1M = 1; // 0x1
- field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int TX_POWER_HIGH = 1; // 0x1
field public static final int TX_POWER_LOW = -15; // 0xfffffff1
field public static final int TX_POWER_MAX = 1; // 0x1
@@ -8056,7 +8073,6 @@
public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
method public int describeContents();
- method public boolean getEnable();
method public boolean getIncludeTxPower();
method public int getInterval();
method public void writeToParcel(android.os.Parcel, int);
@@ -8066,7 +8082,6 @@
public static final class PeriodicAdvertisingParameters.Builder {
ctor public PeriodicAdvertisingParameters.Builder();
method public android.bluetooth.le.PeriodicAdvertisingParameters build();
- method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setEnable(boolean);
method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setIncludeTxPower(boolean);
method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
}
@@ -8144,9 +8159,6 @@
field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR;
field public static final int DATA_COMPLETE = 0; // 0x0
field public static final int DATA_TRUNCATED = 2; // 0x2
- field public static final int PHY_LE_1M = 1; // 0x1
- field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int PHY_UNUSED = 0; // 0x0
field public static final int SID_NOT_PRESENT = 255; // 0xff
}
@@ -8169,9 +8181,7 @@
field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2
field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3
field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1
- field public static final int PHY_LE_1M = 1; // 0x1
field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int SCAN_MODE_BALANCED = 1; // 0x1
field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
@@ -9313,6 +9323,7 @@
field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
+ field public static final deprecated java.lang.String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
field public static final java.lang.String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
field public static final java.lang.String ACTION_MEDIA_CHECKING = "android.intent.action.MEDIA_CHECKING";
@@ -9335,6 +9346,7 @@
field public static final java.lang.String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
field public static final java.lang.String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
field public static final java.lang.String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
+ field public static final java.lang.String ACTION_PACKAGE_FIRST_ADDED = "android.intent.action.PACKAGE_FIRST_ADDED";
field public static final java.lang.String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
field public static final java.lang.String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
field public static final deprecated java.lang.String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
@@ -9451,6 +9463,7 @@
field public static final java.lang.String EXTRA_DONT_KILL_APP = "android.intent.extra.DONT_KILL_APP";
field public static final java.lang.String EXTRA_EMAIL = "android.intent.extra.EMAIL";
field public static final java.lang.String EXTRA_EXCLUDE_COMPONENTS = "android.intent.extra.EXCLUDE_COMPONENTS";
+ field public static final java.lang.String EXTRA_FROM_STORAGE = "android.intent.extra.FROM_STORAGE";
field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
field public static final java.lang.String EXTRA_INDEX = "android.intent.extra.INDEX";
field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
@@ -10348,12 +10361,10 @@
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
- method public deprecated android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
- field public static final deprecated int FLAG_MATCH_CHOOSER = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10621,6 +10632,7 @@
field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency";
field public static final java.lang.String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
field public static final java.lang.String FEATURE_AUDIO_PRO = "android.hardware.audio.pro";
+ field public static final java.lang.String FEATURE_AUTOFILL = "android.software.autofill";
field public static final java.lang.String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
field public static final java.lang.String FEATURE_BACKUP = "android.software.backup";
field public static final java.lang.String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
@@ -10906,9 +10918,6 @@
method public int describeContents();
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
- method public deprecated android.content.ComponentName[] getChooserComponentNames();
- method public deprecated android.os.PersistableBundle getChooserExtras();
- method public deprecated android.content.IntentFilter[] getChooserIntentFilters();
method public java.lang.CharSequence getDisabledMessage();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
@@ -10921,7 +10930,6 @@
method public java.lang.CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
- method public deprecated boolean isChooser();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -10934,11 +10942,9 @@
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
- method public deprecated android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
- method public deprecated android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -12821,7 +12827,6 @@
method public static android.graphics.ColorSpace.Connector connect(android.graphics.ColorSpace, android.graphics.ColorSpace, android.graphics.ColorSpace.RenderIntent);
method public static android.graphics.ColorSpace.Connector connect(android.graphics.ColorSpace);
method public static android.graphics.ColorSpace.Connector connect(android.graphics.ColorSpace, android.graphics.ColorSpace.RenderIntent);
- method public static android.graphics.ColorSpace.Renderer createRenderer();
method public float[] fromXyz(float, float, float);
method public abstract float[] fromXyz(float[]);
method public static android.graphics.ColorSpace get(android.graphics.ColorSpace.Named);
@@ -12905,16 +12910,6 @@
enum_constant public static final android.graphics.ColorSpace.RenderIntent SATURATION;
}
- public static class ColorSpace.Renderer {
- method public android.graphics.ColorSpace.Renderer add(android.graphics.ColorSpace, int);
- method public android.graphics.ColorSpace.Renderer add(android.graphics.ColorSpace, float, float, float, int);
- method public android.graphics.ColorSpace.Renderer clip(boolean);
- method public android.graphics.Bitmap render();
- method public android.graphics.ColorSpace.Renderer showWhitePoint(boolean);
- method public android.graphics.ColorSpace.Renderer size(int);
- method public android.graphics.ColorSpace.Renderer uniformChromaticityScale(boolean);
- }
-
public static class ColorSpace.Rgb extends android.graphics.ColorSpace {
ctor public ColorSpace.Rgb(java.lang.String, float[], java.util.function.DoubleUnaryOperator, java.util.function.DoubleUnaryOperator);
ctor public ColorSpace.Rgb(java.lang.String, float[], float[], java.util.function.DoubleUnaryOperator, java.util.function.DoubleUnaryOperator, float, float);
@@ -13759,7 +13754,7 @@
}
public class Typeface {
- method public static void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
+ method public static deprecated void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
method public static android.graphics.Typeface create(java.lang.String, int);
method public static android.graphics.Typeface create(android.graphics.Typeface, int);
method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String);
@@ -13781,26 +13776,20 @@
}
public static final class Typeface.Builder {
- ctor public Typeface.Builder();
+ ctor public Typeface.Builder(java.io.File);
+ ctor public Typeface.Builder(java.io.FileDescriptor);
+ ctor public Typeface.Builder(java.lang.String);
+ ctor public Typeface.Builder(android.content.res.AssetManager, java.lang.String);
method public android.graphics.Typeface build();
- method public static android.graphics.Typeface.Builder obtain();
- method public void recycle();
- method public void reset();
+ method public android.graphics.Typeface.Builder setFallback(java.lang.String);
method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
- method public android.graphics.Typeface.Builder setItalic(int);
- method public android.graphics.Typeface.Builder setSourceFromAsset(android.content.res.AssetManager, java.lang.String);
- method public android.graphics.Typeface.Builder setSourceFromFile(java.io.File);
- method public android.graphics.Typeface.Builder setSourceFromFile(java.io.FileDescriptor);
- method public android.graphics.Typeface.Builder setSourceFromFilePath(java.lang.String);
+ method public android.graphics.Typeface.Builder setItalic(boolean);
method public android.graphics.Typeface.Builder setTtcIndex(int);
method public android.graphics.Typeface.Builder setWeight(int);
- field public static final int ITALIC = 1; // 0x1
- field public static final int NORMAL = 0; // 0x0
- field public static final int RESOLVE_BY_FONT_TABLE = -1; // 0xffffffff
}
- public static abstract interface Typeface.FontRequestCallback {
+ public static abstract deprecated interface Typeface.FontRequestCallback {
method public abstract void onTypefaceRequestFailed(int);
method public abstract void onTypefaceRetrieved(android.graphics.Typeface);
field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
@@ -13832,7 +13821,7 @@
public class AdaptiveIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
method public void draw(android.graphics.Canvas);
method public android.graphics.drawable.Drawable getBackground();
- method public static float getExtraInsetPercentage();
+ method public static float getExtraInsetFraction();
method public android.graphics.drawable.Drawable getForeground();
method public android.graphics.Path getIconMask();
method public int getOpacity();
@@ -14397,15 +14386,12 @@
field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR;
}
- public final class FontVariationAxis implements android.os.Parcelable {
+ public final class FontVariationAxis {
ctor public FontVariationAxis(java.lang.String, float) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
- method public int describeContents();
method public static android.graphics.fonts.FontVariationAxis[] fromFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
method public float getStyleValue();
method public java.lang.String getTag();
method public static java.lang.String toFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontVariationAxis> CREATOR;
}
public static class FontVariationAxis.InvalidFormatException extends java.lang.Exception {
@@ -14871,15 +14857,16 @@
field public final int type;
}
- public final class SensorDirectChannel implements java.lang.AutoCloseable {
+ public final class SensorDirectChannel implements java.nio.channels.Channel {
method public void close();
- method public boolean isValid();
+ method public int configure(android.hardware.Sensor, int);
+ method public boolean isOpen();
field public static final int RATE_FAST = 2; // 0x2
field public static final int RATE_NORMAL = 1; // 0x1
field public static final int RATE_STOP = 0; // 0x0
field public static final int RATE_VERY_FAST = 3; // 0x3
- field public static final int TYPE_ASHMEM = 1; // 0x1
field public static final int TYPE_HARDWARE_BUFFER = 2; // 0x2
+ field public static final int TYPE_MEMORY_FILE = 1; // 0x1
}
public class SensorEvent {
@@ -14913,7 +14900,6 @@
public abstract class SensorManager {
method public boolean cancelTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
- method public int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
method public android.hardware.SensorDirectChannel createDirectChannel(android.os.MemoryFile);
method public android.hardware.SensorDirectChannel createDirectChannel(android.hardware.HardwareBuffer);
method public boolean flush(android.hardware.SensorEventListener);
@@ -15762,7 +15748,6 @@
method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
field public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 16; // 0x10
- field public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
field public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 8; // 0x8
field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2
field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1
@@ -20590,7 +20575,7 @@
method public double getAccumulatedDeltaRangeMeters();
method public int getAccumulatedDeltaRangeState();
method public double getAccumulatedDeltaRangeUncertaintyMeters();
- method public double getAutomaticGainControlLevelInDb();
+ method public double getAutomaticGainControlLevelDb();
method public long getCarrierCycles();
method public float getCarrierFrequencyHz();
method public double getCarrierPhase();
@@ -20606,7 +20591,7 @@
method public int getState();
method public int getSvid();
method public double getTimeOffsetNanos();
- method public boolean hasAutomaticGainControlLevelInDb();
+ method public boolean hasAutomaticGainControlLevelDb();
method public boolean hasCarrierCycles();
method public boolean hasCarrierFrequencyHz();
method public boolean hasCarrierPhase();
@@ -20700,7 +20685,7 @@
method public int getSatelliteCount();
method public int getSvid(int);
method public boolean hasAlmanacData(int);
- method public boolean hasCarrierFrequency(int);
+ method public boolean hasCarrierFrequencyHz(int);
method public boolean hasEphemerisData(int);
method public boolean usedInFix(int);
field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
@@ -21818,24 +21803,19 @@
field public static final int STOP_VIDEO_RECORDING = 3; // 0x3
}
- public final class MediaCas {
+ public final class MediaCas implements java.lang.AutoCloseable {
ctor public MediaCas(int) throws android.media.MediaCasException.UnsupportedCasException;
- method public void closeSession(byte[]);
+ method public void close();
method public static android.media.MediaCas.PluginDescriptor[] enumeratePlugins();
method public static boolean isSystemIdSupported(int);
- method public byte[] openSession(int) throws android.media.MediaCasException;
- method public byte[] openSession(int, int) throws android.media.MediaCasException;
- method public void processEcm(byte[], byte[], int, int) throws android.media.MediaCasException;
- method public void processEcm(byte[], byte[]) throws android.media.MediaCasException;
+ method public android.media.MediaCas.Session openSession() throws android.media.MediaCasException;
method public void processEmm(byte[], int, int) throws android.media.MediaCasException;
method public void processEmm(byte[]) throws android.media.MediaCasException;
method public void provision(java.lang.String) throws android.media.MediaCasException;
method public void refreshEntitlements(int, byte[]) throws android.media.MediaCasException;
- method public void release();
method public void sendEvent(int, int, byte[]) throws android.media.MediaCasException;
method public void setEventListener(android.media.MediaCas.EventListener, android.os.Handler);
method public void setPrivateData(byte[]) throws android.media.MediaCasException;
- method public void setSessionPrivateData(byte[], byte[]) throws android.media.MediaCasException;
}
public static abstract interface MediaCas.EventListener {
@@ -21847,6 +21827,13 @@
method public int getSystemId();
}
+ public final class MediaCas.Session implements java.lang.AutoCloseable {
+ method public void close();
+ method public void processEcm(byte[], int, int) throws android.media.MediaCasException;
+ method public void processEcm(byte[]) throws android.media.MediaCasException;
+ method public void setPrivateData(byte[]) throws android.media.MediaCasException;
+ }
+
public class MediaCasException extends java.lang.Exception {
}
@@ -22290,12 +22277,12 @@
method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
}
- public final class MediaDescrambler {
+ public final class MediaDescrambler implements java.lang.AutoCloseable {
ctor public MediaDescrambler(int) throws android.media.MediaCasException.UnsupportedCasException;
- method public final int descramble(java.nio.ByteBuffer, int, java.nio.ByteBuffer, int, android.media.MediaCodec.CryptoInfo);
- method public final void release();
+ method public void close();
+ method public final int descramble(java.nio.ByteBuffer, java.nio.ByteBuffer, android.media.MediaCodec.CryptoInfo);
method public final boolean requiresSecureDecoderComponent(java.lang.String);
- method public final void setMediaCasSession(byte[]);
+ method public final void setMediaCasSession(android.media.MediaCas.Session);
}
public class MediaDescription implements android.os.Parcelable {
@@ -22359,7 +22346,7 @@
method public void setOnKeyStatusChangeListener(android.media.MediaDrm.OnKeyStatusChangeListener, android.os.Handler);
method public void setPropertyByteArray(java.lang.String, byte[]);
method public void setPropertyString(java.lang.String, java.lang.String);
- field public static final int EVENT_KEY_EXPIRED = 3; // 0x3
+ field public static final deprecated int EVENT_KEY_EXPIRED = 3; // 0x3
field public static final int EVENT_KEY_REQUIRED = 2; // 0x2
field public static final deprecated int EVENT_PROVISION_REQUIRED = 1; // 0x1
field public static final int EVENT_SESSION_RECLAIMED = 5; // 0x5
@@ -22433,6 +22420,7 @@
ctor public MediaExtractor();
method public boolean advance();
method public long getCachedDuration();
+ method public android.media.MediaExtractor.CasInfo getCasInfo(int);
method public android.media.DrmInitData getDrmInitData();
method public android.media.MediaMetricsSet getMetrics();
method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
@@ -22464,6 +22452,11 @@
field public static final int SEEK_TO_PREVIOUS_SYNC = 0; // 0x0
}
+ public static final class MediaExtractor.CasInfo {
+ method public android.media.MediaCas.Session getSession();
+ method public int getSystemId();
+ }
+
public final class MediaFormat {
ctor public MediaFormat();
method public final boolean containsKey(java.lang.String);
@@ -23632,7 +23625,7 @@
public static final class VolumeShaper.Configuration implements android.os.Parcelable {
method public int describeContents();
- method public double getDurationMs();
+ method public double getDurationMillis();
method public int getInterpolatorType();
method public static int getMaximumCurvePoints();
method public float[] getTimes();
@@ -23658,7 +23651,7 @@
method public android.media.VolumeShaper.Configuration.Builder scaleToEndVolume(float);
method public android.media.VolumeShaper.Configuration.Builder scaleToStartVolume(float);
method public android.media.VolumeShaper.Configuration.Builder setCurve(float[], float[]);
- method public android.media.VolumeShaper.Configuration.Builder setDurationMs(double);
+ method public android.media.VolumeShaper.Configuration.Builder setDurationMillis(double);
method public android.media.VolumeShaper.Configuration.Builder setInterpolatorType(int);
}
@@ -24520,14 +24513,14 @@
method public static boolean isChannelUriForPassthroughInput(android.net.Uri);
method public static boolean isChannelUriForTunerInput(android.net.Uri);
method public static boolean isProgramUri(android.net.Uri);
+ method public static void requestChannelBrowsable(android.content.Context, long);
field public static final java.lang.String ACTION_INITIALIZE_PROGRAMS = "android.media.tv.action.INITIALIZE_PROGRAMS";
- field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
field public static final java.lang.String ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT = "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT";
field public static final java.lang.String ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED";
+ field public static final java.lang.String ACTION_REQUEST_CHANNEL_BROWSABLE = "android.media.tv.action.REQUEST_CHANNEL_BROWSABLE";
field public static final java.lang.String ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED";
field public static final java.lang.String AUTHORITY = "android.media.tv";
field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
- field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
field public static final java.lang.String EXTRA_PREVIEW_PROGRAM_ID = "android.media.tv.extra.PREVIEW_PROGRAM_ID";
field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
}
@@ -24620,9 +24613,10 @@
public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseTvColumns {
field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
- field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
- field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_1_1 = 3; // 0x3
+ field public static final int ASPECT_RATIO_2_3 = 4; // 0x4
field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int ASPECT_RATIO_4_3 = 2; // 0x2
field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
@@ -24717,6 +24711,8 @@
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_REVIEW_RATING = "review_rating";
+ field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
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";
@@ -24731,6 +24727,9 @@
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
field public static final android.net.Uri CONTENT_URI;
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
}
public static final class TvContract.Programs.Genres {
@@ -24777,6 +24776,8 @@
field public static final java.lang.String COLUMN_RECORDING_DATA_URI = "recording_data_uri";
field public static final java.lang.String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis";
field public static final java.lang.String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis";
+ field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+ field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
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 java.lang.String COLUMN_SEASON_TITLE = "season_title";
@@ -24790,14 +24791,18 @@
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/recorded_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/recorded_program";
field public static final android.net.Uri CONTENT_URI;
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
}
public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BaseTvColumns {
ctor public TvContract.WatchNextPrograms();
field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
- field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
- field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_1_1 = 3; // 0x3
+ field public static final int ASPECT_RATIO_2_3 = 4; // 0x4
field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int ASPECT_RATIO_4_3 = 2; // 0x2
field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
@@ -25516,22 +25521,25 @@
method public java.lang.String getName();
method public int getTruncationLengthBits();
method public void writeToParcel(android.os.Parcel, int);
- field public static final java.lang.String ALGO_AUTH_HMAC_MD5 = "hmac(md5)";
- field public static final java.lang.String ALGO_AUTH_HMAC_SHA1 = "hmac(sha1)";
- field public static final java.lang.String ALGO_AUTH_HMAC_SHA256 = "hmac(sha256)";
- field public static final java.lang.String ALGO_AUTH_HMAC_SHA384 = "hmac(sha384)";
- field public static final java.lang.String ALGO_AUTH_HMAC_SHA512 = "hmac(sha512)";
- field public static final java.lang.String ALGO_CRYPT_AES_CBC = "cbc(aes)";
+ field public static final java.lang.String AUTH_HMAC_MD5 = "hmac(md5)";
+ field public static final java.lang.String AUTH_HMAC_SHA1 = "hmac(sha1)";
+ field public static final java.lang.String AUTH_HMAC_SHA256 = "hmac(sha256)";
+ field public static final java.lang.String AUTH_HMAC_SHA384 = "hmac(sha384)";
+ field public static final java.lang.String AUTH_HMAC_SHA512 = "hmac(sha512)";
field public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR;
+ field public static final java.lang.String CRYPT_AES_CBC = "cbc(aes)";
}
public final class IpSecManager {
method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
+ method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
+ method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform);
+ method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
}
@@ -31916,7 +31924,7 @@
field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726
field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b
field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e
- field public static final int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750
+ field public static final deprecated int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750
field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728
field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b
field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740
@@ -34491,10 +34499,15 @@
}
public class FontsContract {
+ method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[], int, boolean, java.lang.String);
+ method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[]);
+ method public static android.provider.FontsContract.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal, android.graphics.fonts.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static void requestFont(android.content.Context, android.graphics.fonts.FontRequest, android.provider.FontsContract.FontRequestCallback, android.os.Handler);
}
public static final class FontsContract.Columns implements android.provider.BaseColumns {
ctor public FontsContract.Columns();
+ field public static final java.lang.String FILE_ID = "file_id";
field public static final java.lang.String ITALIC = "font_italic";
field public static final java.lang.String RESULT_CODE = "result_code";
field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
@@ -34506,6 +34519,35 @@
field public static final java.lang.String WEIGHT = "font_weight";
}
+ public static class FontsContract.FontFamilyResult {
+ method public android.provider.FontsContract.FontInfo[] getFonts();
+ method public int getStatusCode();
+ field public static final int STATUS_OK = 0; // 0x0
+ field public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2; // 0x2
+ field public static final int STATUS_WRONG_CERTIFICATES = 1; // 0x1
+ }
+
+ public static class FontsContract.FontInfo {
+ method public android.graphics.fonts.FontVariationAxis[] getAxes();
+ method public int getResultCode();
+ method public int getTtcIndex();
+ method public android.net.Uri getUri();
+ method public int getWeight();
+ method public boolean isItalic();
+ }
+
+ public static class FontsContract.FontRequestCallback {
+ ctor public FontsContract.FontRequestCallback();
+ method public void onTypefaceRequestFailed(int);
+ method public void onTypefaceRetrieved(android.graphics.Typeface);
+ field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+ field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+ field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+ field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
+ }
+
public final deprecated class LiveFolders implements android.provider.BaseColumns {
field public static final java.lang.String ACTION_CREATE_LIVE_FOLDER = "android.intent.action.CREATE_LIVE_FOLDER";
field public static final java.lang.String DESCRIPTION = "description";
@@ -34890,8 +34932,8 @@
field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
field public static final java.lang.String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
field public static final java.lang.String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
- field public static final java.lang.String ACTION_MANAGE_EXTERNAL_SOURCES = "android.settings.action.MANAGE_EXTERNAL_SOURCES";
field public static final java.lang.String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
+ field public static final java.lang.String ACTION_MANAGE_UNKNOWN_APP_SOURCES = "android.settings.action.MANAGE_UNKNOWN_APP_SOURCES";
field public static final java.lang.String ACTION_MANAGE_WRITE_SETTINGS = "android.settings.action.MANAGE_WRITE_SETTINGS";
field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
field public static final java.lang.String ACTION_NETWORK_OPERATOR_SETTINGS = "android.settings.NETWORK_OPERATOR_SETTINGS";
@@ -36986,7 +37028,7 @@
public abstract class AutofillService extends android.app.Service {
ctor public AutofillService();
- method public final void disableSelf();
+ method public final deprecated void disableSelf();
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConnected();
method public void onDisconnected();
@@ -37175,7 +37217,7 @@
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public boolean dispatchTouchEvent(android.view.MotionEvent);
method public boolean dispatchTrackballEvent(android.view.MotionEvent);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public final void finish();
method public android.view.Window getWindow();
method public android.view.WindowManager getWindowManager();
@@ -37317,12 +37359,16 @@
method public final int getCurrentInterruptionFilter();
method public final int getCurrentListenerHints();
method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
+ method public final java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(java.lang.String);
+ method public final java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String);
method public final android.service.notification.StatusBarNotification[] getSnoozedNotifications();
method public android.os.IBinder onBind(android.content.Intent);
method public void onInterruptionFilterChanged(int);
method public void onListenerConnected();
method public void onListenerDisconnected();
method public void onListenerHintsChanged(int);
+ method public void onNotificationChannelGroupModified(java.lang.String, android.app.NotificationChannelGroup, int);
+ method public void onNotificationChannelModified(java.lang.String, android.app.NotificationChannel, int);
method public void onNotificationPosted(android.service.notification.StatusBarNotification);
method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap);
@@ -37335,6 +37381,7 @@
method public final void requestUnbind();
method public final void setNotificationsShown(java.lang.String[]);
method public final void snoozeNotification(java.lang.String, long);
+ method public final void updateNotificationChannel(java.lang.String, android.app.NotificationChannel);
field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
@@ -37343,6 +37390,9 @@
field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
+ field public static final int NOTIFICATION_CHANNEL_OR_GROUP_ADDED = 1; // 0x1
+ field public static final int NOTIFICATION_CHANNEL_OR_GROUP_DELETED = 3; // 0x3
+ field public static final int NOTIFICATION_CHANNEL_OR_GROUP_UPDATED = 2; // 0x2
field public static final int REASON_APP_CANCEL = 8; // 0x8
field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
field public static final int REASON_CANCEL = 2; // 0x2
@@ -39339,6 +39389,7 @@
method public android.telecom.PhoneAccountHandle getDefaultOutgoingPhoneAccount(java.lang.String);
method public java.lang.String getLine1Number(android.telecom.PhoneAccountHandle);
method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
+ method public java.util.List<android.telecom.PhoneAccountHandle> getSelfManagedPhoneAccounts();
method public android.telecom.PhoneAccountHandle getSimCallManager();
method public java.lang.String getVoiceMailNumber(android.telecom.PhoneAccountHandle);
method public boolean handleMmi(java.lang.String);
@@ -40067,7 +40118,7 @@
method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
method public int getCallState();
method public android.os.PersistableBundle getCarrierConfig();
- method public android.telephony.CellLocation getCellLocation();
+ method public deprecated android.telephony.CellLocation getCellLocation();
method public int getDataActivity();
method public int getDataNetworkType();
method public int getDataState();
@@ -40109,7 +40160,8 @@
method public boolean hasIccCard();
method public boolean iccCloseLogicalChannel(int);
method public byte[] iccExchangeSimIO(int, int, int, int, int, java.lang.String);
- method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
+ method public deprecated android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
+ method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String, int);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
method public boolean isConcurrentVoiceAndDataSupported();
@@ -42620,7 +42672,7 @@
method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, java.lang.String[], android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter);
field public static final int ALL = 15; // 0xf
field public static final int EMAIL_ADDRESSES = 2; // 0x2
- field public static final int MAP_ADDRESSES = 8; // 0x8
+ field public static final deprecated int MAP_ADDRESSES = 8; // 0x8
field public static final int PHONE_NUMBERS = 4; // 0x4
field public static final int WEB_URLS = 1; // 0x1
field public static final android.text.util.Linkify.MatchFilter sPhoneNumberMatchFilter;
@@ -43833,7 +43885,6 @@
method public boolean isValid();
method public boolean isWideColorGamut();
field public static final int DEFAULT_DISPLAY = 0; // 0x0
- field public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
field public static final int FLAG_PRESENTATION = 8; // 0x8
field public static final int FLAG_PRIVATE = 4; // 0x4
field public static final int FLAG_ROUND = 16; // 0x10
@@ -45331,6 +45382,7 @@
method public java.lang.CharSequence getContentDescription();
method public final android.content.Context getContext();
method protected android.view.ContextMenu.ContextMenuInfo getContextMenuInfo();
+ method public final boolean getDefaultFocusHighlightEnabled();
method public static int getDefaultSize(int, int);
method public android.view.Display getDisplay();
method public final int[] getDrawableState();
@@ -45649,6 +45701,7 @@
method public void setClipToOutline(boolean);
method public void setContentDescription(java.lang.CharSequence);
method public void setContextClickable(boolean);
+ method public void setDefaultFocusHighlightEnabled(boolean);
method public void setDrawingCacheBackgroundColor(int);
method public void setDrawingCacheEnabled(boolean);
method public void setDrawingCacheQuality(int);
@@ -47732,6 +47785,7 @@
public final class AutofillManager {
method public void cancel();
method public void commit();
+ method public void disableOwnedAutofillServices();
method public boolean isEnabled();
method public void notifyValueChanged(android.view.View);
method public void notifyValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
@@ -48889,7 +48943,7 @@
method public void documentHasImages(android.os.Message);
method public static void enableSlowWholeDocumentDraw();
method public void evaluateJavascript(java.lang.String, android.webkit.ValueCallback<java.lang.String>);
- method public static java.lang.String findAddress(java.lang.String);
+ method public static deprecated java.lang.String findAddress(java.lang.String);
method public deprecated int findAll(java.lang.String);
method public void findAllAsync(java.lang.String);
method public void findNext(boolean);
diff --git a/api/removed.txt b/api/removed.txt
index d20c08c..82705fd 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -100,6 +100,18 @@
}
+package android.hardware {
+
+ public final class SensorDirectChannel implements java.nio.channels.Channel {
+ method public deprecated boolean isValid();
+ }
+
+ public abstract class SensorManager {
+ method public deprecated int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
+ }
+
+}
+
package android.media {
public final class AudioFormat implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 99a5793..4fa96ae 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -142,12 +142,14 @@
field public static final java.lang.String MANAGE_APP_OPS_RESTRICTIONS = "android.permission.MANAGE_APP_OPS_RESTRICTIONS";
field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
field public static final java.lang.String MANAGE_AUTO_FILL = "android.permission.MANAGE_AUTO_FILL";
+ field public static final java.lang.String MANAGE_CARRIER_OEM_UNLOCK_STATE = "android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE";
field public static final java.lang.String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES";
field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS";
field public static final java.lang.String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS";
field public static final java.lang.String MANAGE_OWN_CALLS = "android.permission.MANAGE_OWN_CALLS";
field public static final java.lang.String MANAGE_USB = "android.permission.MANAGE_USB";
field public static final java.lang.String MANAGE_USERS = "android.permission.MANAGE_USERS";
+ field public static final java.lang.String MANAGE_USER_OEM_UNLOCK_STATE = "android.permission.MANAGE_USER_OEM_UNLOCK_STATE";
field public static final java.lang.String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
field public static final java.lang.String MEDIA_CONTENT_CONTROL = "android.permission.MEDIA_CONTENT_CONTROL";
field public static final java.lang.String MODIFY_APPWIDGET_BIND_PERMISSIONS = "android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS";
@@ -163,6 +165,7 @@
field public static final java.lang.String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE";
field public static final java.lang.String NFC = "android.permission.NFC";
field public static final java.lang.String NOTIFICATION_DURING_SETUP = "android.permission.NOTIFICATION_DURING_SETUP";
+ field public static final java.lang.String NOTIFY_TV_INPUTS = "android.permission.NOTIFY_TV_INPUTS";
field public static final java.lang.String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG";
field public static final java.lang.String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS";
field public static final java.lang.String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
@@ -325,6 +328,7 @@
public static final class R.attr {
ctor public R.attr();
field public static final int __removed1 = 16844099; // 0x1010543
+ field public static final int __removed2 = 16844104; // 0x1010548
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -586,6 +590,7 @@
field public static final deprecated int dayOfWeekBackground = 16843924; // 0x1010494
field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
field public static final int debuggable = 16842767; // 0x101000f
+ field public static final int defaultFocusHighlightEnabled = 16844133; // 0x1010565
field public static final int defaultHeight = 16844021; // 0x10104f5
field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
field public static final int defaultValue = 16843245; // 0x10101ed
@@ -1106,6 +1111,7 @@
field public static final int persistableMode = 16843821; // 0x101042d
field public static final int persistent = 16842765; // 0x101000d
field public static final int persistentDrawingCache = 16842990; // 0x10100ee
+ field public static final int persistentFeature = 16844134; // 0x1010566
field public static final deprecated int phoneNumber = 16843111; // 0x1010167
field public static final int pivotX = 16843189; // 0x10101b5
field public static final int pivotY = 16843190; // 0x10101b6
@@ -1388,7 +1394,6 @@
field public static final int summaryOff = 16843248; // 0x10101f0
field public static final int summaryOn = 16843247; // 0x10101ef
field public static final int supportsAssist = 16844016; // 0x10104f0
- field public static final int supportsDismissingWindow = 16844104; // 0x1010548
field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
field public static final int supportsLocalInteraction = 16844047; // 0x101050f
field public static final int supportsPictureInPicture = 16844023; // 0x10104f7
@@ -1658,6 +1663,7 @@
field public static final int windowShowAnimation = 16842934; // 0x10100b6
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
+ field public static final int windowSplashscreenContent = 16844135; // 0x1010567
field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
field public static final int windowTitleSize = 16842842; // 0x101005a
@@ -2072,6 +2078,7 @@
field public static final int no = 17039369; // 0x1040009
field public static final int ok = 17039370; // 0x104000a
field public static final int paste = 17039371; // 0x104000b
+ field public static final int paste_as_plain_text = 17039385; // 0x1040019
field public static final int search_go = 17039372; // 0x104000c
field public static final int selectAll = 17039373; // 0x104000d
field public static final int selectTextMode = 17039382; // 0x1040016
@@ -3119,6 +3126,7 @@
method public android.accounts.AccountManagerFuture<android.os.Bundle> startAddAccountSession(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> startUpdateCredentialsSession(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> updateCredentials(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+ field public static final java.lang.String ACTION_ACCOUNT_REMOVED = "android.accounts.action.ACCOUNT_REMOVED";
field public static final java.lang.String ACTION_AUTHENTICATOR_INTENT = "android.accounts.AccountAuthenticator";
field public static final java.lang.String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
field public static final java.lang.String AUTHENTICATOR_META_DATA_NAME = "android.accounts.AccountAuthenticator";
@@ -3980,6 +3988,7 @@
method public android.app.PendingIntent getRunningServiceControlPanel(android.content.ComponentName) throws java.lang.SecurityException;
method public java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException;
method public deprecated java.util.List<android.app.ActivityManager.RunningTaskInfo> getRunningTasks(int) throws java.lang.SecurityException;
+ method public int getUidImportance(int);
method public deprecated boolean isInLockTaskMode();
method public boolean isLowRamDevice();
method public static boolean isRunningInTestHarness();
@@ -4856,7 +4865,7 @@
public abstract class FragmentContainer {
ctor public FragmentContainer();
method public android.app.Fragment instantiate(android.content.Context, java.lang.String, android.os.Bundle);
- method public abstract android.view.View onFindViewById(int);
+ method public abstract <T extends android.view.View> T onFindViewById(int);
method public abstract boolean onHasView();
}
@@ -4907,7 +4916,7 @@
ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
method public void onAttachFragment(android.app.Fragment);
method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
- method public android.view.View onFindViewById(int);
+ method public <T extends android.view.View> T onFindViewById(int);
method public abstract E onGetHost();
method public android.view.LayoutInflater onGetLayoutInflater();
method public int onGetWindowAnimations();
@@ -7217,6 +7226,7 @@
field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
field public static final int NETWORK_TYPE_ANY = 1; // 0x1
+ field public static final int NETWORK_TYPE_METERED = 4; // 0x4
field public static final int NETWORK_TYPE_NONE = 0; // 0x0
field public static final int NETWORK_TYPE_NOT_ROAMING = 3; // 0x3
field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
@@ -7255,6 +7265,8 @@
}
public class JobParameters implements android.os.Parcelable {
+ method public void completeWork(android.app.job.JobWorkItem);
+ method public android.app.job.JobWorkItem dequeueWork();
method public int describeContents();
method public android.content.ClipData getClipData();
method public int getClipGrantFlags();
@@ -7272,6 +7284,7 @@
ctor public JobScheduler();
method public abstract void cancel(int);
method public abstract void cancelAll();
+ method public abstract int enqueue(android.app.job.JobInfo, android.app.job.JobWorkItem);
method public abstract java.util.List<android.app.job.JobInfo> getAllPendingJobs();
method public abstract android.app.job.JobInfo getPendingJob(int);
method public abstract int schedule(android.app.job.JobInfo);
@@ -7289,6 +7302,15 @@
field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE";
}
+ public final class JobWorkItem implements android.os.Parcelable {
+ ctor public JobWorkItem(android.content.Intent);
+ ctor public JobWorkItem(android.os.Parcel);
+ method public int describeContents();
+ method public android.content.Intent getIntent();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.job.JobWorkItem> CREATOR;
+ }
+
}
package android.app.usage {
@@ -8059,9 +8081,11 @@
field public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; // 0x2
field public static final int PAIRING_VARIANT_PIN = 0; // 0x0
field public static final int PHY_LE_1M = 1; // 0x1
+ field public static final int PHY_LE_1M_MASK = 1; // 0x1
field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_ANY = 7; // 0x7
- field public static final int PHY_LE_CODED = 4; // 0x4
+ field public static final int PHY_LE_2M_MASK = 2; // 0x2
+ field public static final int PHY_LE_CODED = 3; // 0x3
+ field public static final int PHY_LE_CODED_MASK = 4; // 0x4
field public static final int PHY_OPTION_NO_PREFERRED = 0; // 0x0
field public static final int PHY_OPTION_S2 = 1; // 0x1
field public static final int PHY_OPTION_S8 = 2; // 0x2
@@ -8479,9 +8503,6 @@
field public static final int INTERVAL_MAX = 16777215; // 0xffffff
field public static final int INTERVAL_MEDIUM = 400; // 0x190
field public static final int INTERVAL_MIN = 160; // 0xa0
- field public static final int PHY_LE_1M = 1; // 0x1
- field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int TX_POWER_HIGH = 1; // 0x1
field public static final int TX_POWER_LOW = -15; // 0xfffffff1
field public static final int TX_POWER_MAX = 1; // 0x1
@@ -8527,7 +8548,6 @@
public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
method public int describeContents();
- method public boolean getEnable();
method public boolean getIncludeTxPower();
method public int getInterval();
method public void writeToParcel(android.os.Parcel, int);
@@ -8537,7 +8557,6 @@
public static final class PeriodicAdvertisingParameters.Builder {
ctor public PeriodicAdvertisingParameters.Builder();
method public android.bluetooth.le.PeriodicAdvertisingParameters build();
- method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setEnable(boolean);
method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setIncludeTxPower(boolean);
method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
}
@@ -8625,9 +8644,6 @@
field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR;
field public static final int DATA_COMPLETE = 0; // 0x0
field public static final int DATA_TRUNCATED = 2; // 0x2
- field public static final int PHY_LE_1M = 1; // 0x1
- field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int PHY_UNUSED = 0; // 0x0
field public static final int SID_NOT_PRESENT = 255; // 0xff
}
@@ -8650,9 +8666,7 @@
field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2
field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3
field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1
- field public static final int PHY_LE_1M = 1; // 0x1
field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int SCAN_MODE_BALANCED = 1; // 0x1
field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
@@ -9420,6 +9434,7 @@
field public static final java.lang.String NFC_SERVICE = "nfc";
field public static final java.lang.String NOTIFICATION_SERVICE = "notification";
field public static final java.lang.String NSD_SERVICE = "servicediscovery";
+ field public static final java.lang.String OEM_LOCK_SERVICE = "oem_lock";
field public static final java.lang.String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
field public static final java.lang.String POWER_SERVICE = "power";
field public static final java.lang.String PRINT_SERVICE = "print";
@@ -9797,6 +9812,7 @@
field public static final java.lang.String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED";
field public static final java.lang.String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_SUBSCRIPTION_CHANGED";
field public static final java.lang.String ACTION_DELETE = "android.intent.action.DELETE";
+ field public static final deprecated java.lang.String ACTION_DEVICE_INITIALIZATION_WIZARD = "android.intent.action.DEVICE_INITIALIZATION_WIZARD";
field public static final deprecated java.lang.String ACTION_DEVICE_STORAGE_LOW = "android.intent.action.DEVICE_STORAGE_LOW";
field public static final deprecated java.lang.String ACTION_DEVICE_STORAGE_OK = "android.intent.action.DEVICE_STORAGE_OK";
field public static final java.lang.String ACTION_DIAL = "android.intent.action.DIAL";
@@ -9835,6 +9851,7 @@
field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
field public static final java.lang.String ACTION_MANAGE_PERMISSIONS = "android.intent.action.MANAGE_PERMISSIONS";
field public static final java.lang.String ACTION_MANAGE_PERMISSION_APPS = "android.intent.action.MANAGE_PERMISSION_APPS";
+ field public static final deprecated java.lang.String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
field public static final java.lang.String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
field public static final java.lang.String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
@@ -9858,6 +9875,7 @@
field public static final java.lang.String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
field public static final java.lang.String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
field public static final java.lang.String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
+ field public static final java.lang.String ACTION_PACKAGE_FIRST_ADDED = "android.intent.action.PACKAGE_FIRST_ADDED";
field public static final java.lang.String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
field public static final java.lang.String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
field public static final deprecated java.lang.String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
@@ -9904,6 +9922,7 @@
field public static final deprecated java.lang.String ACTION_UMS_CONNECTED = "android.intent.action.UMS_CONNECTED";
field public static final deprecated java.lang.String ACTION_UMS_DISCONNECTED = "android.intent.action.UMS_DISCONNECTED";
field public static final java.lang.String ACTION_UNINSTALL_PACKAGE = "android.intent.action.UNINSTALL_PACKAGE";
+ field public static final java.lang.String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP";
field public static final java.lang.String ACTION_USER_BACKGROUND = "android.intent.action.USER_BACKGROUND";
field public static final java.lang.String ACTION_USER_FOREGROUND = "android.intent.action.USER_FOREGROUND";
field public static final java.lang.String ACTION_USER_INITIALIZE = "android.intent.action.USER_INITIALIZE";
@@ -9995,6 +10014,7 @@
field public static final deprecated java.lang.String EXTRA_EMERGENCY_ONLY = "emergencyOnly";
field public static final java.lang.String EXTRA_EXCLUDE_COMPONENTS = "android.intent.extra.EXCLUDE_COMPONENTS";
field public static final java.lang.String EXTRA_FORCE_FACTORY_RESET = "android.intent.extra.FORCE_FACTORY_RESET";
+ field public static final java.lang.String EXTRA_FROM_STORAGE = "android.intent.extra.FROM_STORAGE";
field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
field public static final java.lang.String EXTRA_INDEX = "android.intent.extra.INDEX";
field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
@@ -11003,12 +11023,10 @@
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
- method public deprecated android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
- field public static final deprecated int FLAG_MATCH_CHOOSER = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -11305,6 +11323,7 @@
field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency";
field public static final java.lang.String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
field public static final java.lang.String FEATURE_AUDIO_PRO = "android.hardware.audio.pro";
+ field public static final java.lang.String FEATURE_AUTOFILL = "android.software.autofill";
field public static final java.lang.String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
field public static final java.lang.String FEATURE_BACKUP = "android.software.backup";
field public static final java.lang.String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
@@ -11655,9 +11674,6 @@
method public int describeContents();
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
- method public deprecated android.content.ComponentName[] getChooserComponentNames();
- method public deprecated android.os.PersistableBundle getChooserExtras();
- method public deprecated android.content.IntentFilter[] getChooserIntentFilters();
method public java.lang.CharSequence getDisabledMessage();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
@@ -11670,7 +11686,6 @@
method public java.lang.CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
- method public deprecated boolean isChooser();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -11683,11 +11698,9 @@
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
- method public deprecated android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
- method public deprecated android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -13584,7 +13597,6 @@
method public static android.graphics.ColorSpace.Connector connect(android.graphics.ColorSpace, android.graphics.ColorSpace, android.graphics.ColorSpace.RenderIntent);
method public static android.graphics.ColorSpace.Connector connect(android.graphics.ColorSpace);
method public static android.graphics.ColorSpace.Connector connect(android.graphics.ColorSpace, android.graphics.ColorSpace.RenderIntent);
- method public static android.graphics.ColorSpace.Renderer createRenderer();
method public float[] fromXyz(float, float, float);
method public abstract float[] fromXyz(float[]);
method public static android.graphics.ColorSpace get(android.graphics.ColorSpace.Named);
@@ -13668,16 +13680,6 @@
enum_constant public static final android.graphics.ColorSpace.RenderIntent SATURATION;
}
- public static class ColorSpace.Renderer {
- method public android.graphics.ColorSpace.Renderer add(android.graphics.ColorSpace, int);
- method public android.graphics.ColorSpace.Renderer add(android.graphics.ColorSpace, float, float, float, int);
- method public android.graphics.ColorSpace.Renderer clip(boolean);
- method public android.graphics.Bitmap render();
- method public android.graphics.ColorSpace.Renderer showWhitePoint(boolean);
- method public android.graphics.ColorSpace.Renderer size(int);
- method public android.graphics.ColorSpace.Renderer uniformChromaticityScale(boolean);
- }
-
public static class ColorSpace.Rgb extends android.graphics.ColorSpace {
ctor public ColorSpace.Rgb(java.lang.String, float[], java.util.function.DoubleUnaryOperator, java.util.function.DoubleUnaryOperator);
ctor public ColorSpace.Rgb(java.lang.String, float[], float[], java.util.function.DoubleUnaryOperator, java.util.function.DoubleUnaryOperator, float, float);
@@ -14522,7 +14524,7 @@
}
public class Typeface {
- method public static void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
+ method public static deprecated void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
method public static android.graphics.Typeface create(java.lang.String, int);
method public static android.graphics.Typeface create(android.graphics.Typeface, int);
method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String);
@@ -14544,26 +14546,20 @@
}
public static final class Typeface.Builder {
- ctor public Typeface.Builder();
+ ctor public Typeface.Builder(java.io.File);
+ ctor public Typeface.Builder(java.io.FileDescriptor);
+ ctor public Typeface.Builder(java.lang.String);
+ ctor public Typeface.Builder(android.content.res.AssetManager, java.lang.String);
method public android.graphics.Typeface build();
- method public static android.graphics.Typeface.Builder obtain();
- method public void recycle();
- method public void reset();
+ method public android.graphics.Typeface.Builder setFallback(java.lang.String);
method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
- method public android.graphics.Typeface.Builder setItalic(int);
- method public android.graphics.Typeface.Builder setSourceFromAsset(android.content.res.AssetManager, java.lang.String);
- method public android.graphics.Typeface.Builder setSourceFromFile(java.io.File);
- method public android.graphics.Typeface.Builder setSourceFromFile(java.io.FileDescriptor);
- method public android.graphics.Typeface.Builder setSourceFromFilePath(java.lang.String);
+ method public android.graphics.Typeface.Builder setItalic(boolean);
method public android.graphics.Typeface.Builder setTtcIndex(int);
method public android.graphics.Typeface.Builder setWeight(int);
- field public static final int ITALIC = 1; // 0x1
- field public static final int NORMAL = 0; // 0x0
- field public static final int RESOLVE_BY_FONT_TABLE = -1; // 0xffffffff
}
- public static abstract interface Typeface.FontRequestCallback {
+ public static abstract deprecated interface Typeface.FontRequestCallback {
method public abstract void onTypefaceRequestFailed(int);
method public abstract void onTypefaceRetrieved(android.graphics.Typeface);
field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
@@ -14595,7 +14591,7 @@
public class AdaptiveIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
method public void draw(android.graphics.Canvas);
method public android.graphics.drawable.Drawable getBackground();
- method public static float getExtraInsetPercentage();
+ method public static float getExtraInsetFraction();
method public android.graphics.drawable.Drawable getForeground();
method public android.graphics.Path getIconMask();
method public int getOpacity();
@@ -15160,15 +15156,12 @@
field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR;
}
- public final class FontVariationAxis implements android.os.Parcelable {
+ public final class FontVariationAxis {
ctor public FontVariationAxis(java.lang.String, float) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
- method public int describeContents();
method public static android.graphics.fonts.FontVariationAxis[] fromFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
method public float getStyleValue();
method public java.lang.String getTag();
method public static java.lang.String toFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontVariationAxis> CREATOR;
}
public static class FontVariationAxis.InvalidFormatException extends java.lang.Exception {
@@ -15640,15 +15633,16 @@
field public final int type;
}
- public final class SensorDirectChannel implements java.lang.AutoCloseable {
+ public final class SensorDirectChannel implements java.nio.channels.Channel {
method public void close();
- method public boolean isValid();
+ method public int configure(android.hardware.Sensor, int);
+ method public boolean isOpen();
field public static final int RATE_FAST = 2; // 0x2
field public static final int RATE_NORMAL = 1; // 0x1
field public static final int RATE_STOP = 0; // 0x0
field public static final int RATE_VERY_FAST = 3; // 0x3
- field public static final int TYPE_ASHMEM = 1; // 0x1
field public static final int TYPE_HARDWARE_BUFFER = 2; // 0x2
+ field public static final int TYPE_MEMORY_FILE = 1; // 0x1
}
public class SensorEvent {
@@ -15682,7 +15676,6 @@
public abstract class SensorManager {
method public boolean cancelTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
- method public int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
method public android.hardware.SensorDirectChannel createDirectChannel(android.os.MemoryFile);
method public android.hardware.SensorDirectChannel createDirectChannel(android.hardware.HardwareBuffer);
method public boolean flush(android.hardware.SensorEventListener);
@@ -16544,7 +16537,6 @@
method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
field public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 16; // 0x10
- field public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
field public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 8; // 0x8
field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2
field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1
@@ -22086,7 +22078,7 @@
method public double getAccumulatedDeltaRangeMeters();
method public int getAccumulatedDeltaRangeState();
method public double getAccumulatedDeltaRangeUncertaintyMeters();
- method public double getAutomaticGainControlLevelInDb();
+ method public double getAutomaticGainControlLevelDb();
method public long getCarrierCycles();
method public float getCarrierFrequencyHz();
method public double getCarrierPhase();
@@ -22102,7 +22094,7 @@
method public int getState();
method public int getSvid();
method public double getTimeOffsetNanos();
- method public boolean hasAutomaticGainControlLevelInDb();
+ method public boolean hasAutomaticGainControlLevelDb();
method public boolean hasCarrierCycles();
method public boolean hasCarrierFrequencyHz();
method public boolean hasCarrierPhase();
@@ -22196,7 +22188,7 @@
method public int getSatelliteCount();
method public int getSvid(int);
method public boolean hasAlmanacData(int);
- method public boolean hasCarrierFrequency(int);
+ method public boolean hasCarrierFrequencyHz(int);
method public boolean hasEphemerisData(int);
method public boolean usedInFix(int);
field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
@@ -23643,24 +23635,19 @@
field public static final int STOP_VIDEO_RECORDING = 3; // 0x3
}
- public final class MediaCas {
+ public final class MediaCas implements java.lang.AutoCloseable {
ctor public MediaCas(int) throws android.media.MediaCasException.UnsupportedCasException;
- method public void closeSession(byte[]);
+ method public void close();
method public static android.media.MediaCas.PluginDescriptor[] enumeratePlugins();
method public static boolean isSystemIdSupported(int);
- method public byte[] openSession(int) throws android.media.MediaCasException;
- method public byte[] openSession(int, int) throws android.media.MediaCasException;
- method public void processEcm(byte[], byte[], int, int) throws android.media.MediaCasException;
- method public void processEcm(byte[], byte[]) throws android.media.MediaCasException;
+ method public android.media.MediaCas.Session openSession() throws android.media.MediaCasException;
method public void processEmm(byte[], int, int) throws android.media.MediaCasException;
method public void processEmm(byte[]) throws android.media.MediaCasException;
method public void provision(java.lang.String) throws android.media.MediaCasException;
method public void refreshEntitlements(int, byte[]) throws android.media.MediaCasException;
- method public void release();
method public void sendEvent(int, int, byte[]) throws android.media.MediaCasException;
method public void setEventListener(android.media.MediaCas.EventListener, android.os.Handler);
method public void setPrivateData(byte[]) throws android.media.MediaCasException;
- method public void setSessionPrivateData(byte[], byte[]) throws android.media.MediaCasException;
}
public static abstract interface MediaCas.EventListener {
@@ -23672,6 +23659,13 @@
method public int getSystemId();
}
+ public final class MediaCas.Session implements java.lang.AutoCloseable {
+ method public void close();
+ method public void processEcm(byte[], int, int) throws android.media.MediaCasException;
+ method public void processEcm(byte[]) throws android.media.MediaCasException;
+ method public void setPrivateData(byte[]) throws android.media.MediaCasException;
+ }
+
public class MediaCasException extends java.lang.Exception {
}
@@ -24115,12 +24109,12 @@
method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
}
- public final class MediaDescrambler {
+ public final class MediaDescrambler implements java.lang.AutoCloseable {
ctor public MediaDescrambler(int) throws android.media.MediaCasException.UnsupportedCasException;
- method public final int descramble(java.nio.ByteBuffer, int, java.nio.ByteBuffer, int, android.media.MediaCodec.CryptoInfo);
- method public final void release();
+ method public void close();
+ method public final int descramble(java.nio.ByteBuffer, java.nio.ByteBuffer, android.media.MediaCodec.CryptoInfo);
method public final boolean requiresSecureDecoderComponent(java.lang.String);
- method public final void setMediaCasSession(byte[]);
+ method public final void setMediaCasSession(android.media.MediaCas.Session);
}
public class MediaDescription implements android.os.Parcelable {
@@ -24184,7 +24178,7 @@
method public void setOnKeyStatusChangeListener(android.media.MediaDrm.OnKeyStatusChangeListener, android.os.Handler);
method public void setPropertyByteArray(java.lang.String, byte[]);
method public void setPropertyString(java.lang.String, java.lang.String);
- field public static final int EVENT_KEY_EXPIRED = 3; // 0x3
+ field public static final deprecated int EVENT_KEY_EXPIRED = 3; // 0x3
field public static final int EVENT_KEY_REQUIRED = 2; // 0x2
field public static final deprecated int EVENT_PROVISION_REQUIRED = 1; // 0x1
field public static final int EVENT_SESSION_RECLAIMED = 5; // 0x5
@@ -24258,6 +24252,7 @@
ctor public MediaExtractor();
method public boolean advance();
method public long getCachedDuration();
+ method public android.media.MediaExtractor.CasInfo getCasInfo(int);
method public android.media.DrmInitData getDrmInitData();
method public android.media.MediaMetricsSet getMetrics();
method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
@@ -24289,6 +24284,11 @@
field public static final int SEEK_TO_PREVIOUS_SYNC = 0; // 0x0
}
+ public static final class MediaExtractor.CasInfo {
+ method public android.media.MediaCas.Session getSession();
+ method public int getSystemId();
+ }
+
public final class MediaFormat {
ctor public MediaFormat();
method public final boolean containsKey(java.lang.String);
@@ -25468,7 +25468,7 @@
public static final class VolumeShaper.Configuration implements android.os.Parcelable {
method public int describeContents();
- method public double getDurationMs();
+ method public double getDurationMillis();
method public int getInterpolatorType();
method public static int getMaximumCurvePoints();
method public float[] getTimes();
@@ -25494,7 +25494,7 @@
method public android.media.VolumeShaper.Configuration.Builder scaleToEndVolume(float);
method public android.media.VolumeShaper.Configuration.Builder scaleToStartVolume(float);
method public android.media.VolumeShaper.Configuration.Builder setCurve(float[], float[]);
- method public android.media.VolumeShaper.Configuration.Builder setDurationMs(double);
+ method public android.media.VolumeShaper.Configuration.Builder setDurationMillis(double);
method public android.media.VolumeShaper.Configuration.Builder setInterpolatorType(int);
}
@@ -26490,12 +26490,15 @@
method public static boolean isChannelUriForPassthroughInput(android.net.Uri);
method public static boolean isChannelUriForTunerInput(android.net.Uri);
method public static boolean isProgramUri(android.net.Uri);
+ method public static void requestChannelBrowsable(android.content.Context, long);
+ field public static final java.lang.String ACTION_CHANNEL_BROWSABLE_REQUESTED = "android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED";
field public static final java.lang.String ACTION_INITIALIZE_PROGRAMS = "android.media.tv.action.INITIALIZE_PROGRAMS";
- field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
field public static final java.lang.String ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT = "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT";
field public static final java.lang.String ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED";
+ field public static final java.lang.String ACTION_REQUEST_CHANNEL_BROWSABLE = "android.media.tv.action.REQUEST_CHANNEL_BROWSABLE";
field public static final java.lang.String ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED";
field public static final java.lang.String AUTHORITY = "android.media.tv";
+ field public static final java.lang.String EXTRA_BLOCKED_PACKAGES = "android.media.tv.extra.BLOCKED_PACKAGES";
field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
field public static final java.lang.String EXTRA_COLUMN_NAME = "android.media.tv.extra.COLUMN_NAME";
field public static final java.lang.String EXTRA_DATA_TYPE = "android.media.tv.extra.DATA_TYPE";
@@ -26503,9 +26506,16 @@
field public static final java.lang.String EXTRA_EXISTING_COLUMN_NAMES = "android.media.tv.extra.EXISTING_COLUMN_NAMES";
field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
field public static final java.lang.String EXTRA_PREVIEW_PROGRAM_ID = "android.media.tv.extra.PREVIEW_PROGRAM_ID";
+ field public static final java.lang.String EXTRA_RESULT_CODE = "android.media.tv.extra.RESULT_CODE";
field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
field public static final java.lang.String METHOD_ADD_COLUMN = "add_column";
+ field public static final java.lang.String METHOD_BLOCK_PACKAGE = "block_package";
+ field public static final java.lang.String METHOD_GET_BLOCKED_PACKAGES = "get_blocked_packages";
field public static final java.lang.String METHOD_GET_COLUMNS = "get_columns";
+ field public static final java.lang.String METHOD_UNBLOCK_PACKAGE = "unblock_package";
+ field public static final int RESULT_ERROR_INVALID_ARGUMENT = 2; // 0x2
+ field public static final int RESULT_ERROR_IO = 1; // 0x1
+ field public static final int RESULT_OK = 0; // 0x0
}
public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns {
@@ -26536,7 +26546,6 @@
field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
field public static final java.lang.String COLUMN_SERVICE_ID = "service_id";
field public static final java.lang.String COLUMN_SERVICE_TYPE = "service_type";
- field public static final java.lang.String COLUMN_SYSTEM_APPROVED = "system_approved";
field public static final java.lang.String COLUMN_TRANSIENT = "transient";
field public static final java.lang.String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id";
field public static final java.lang.String COLUMN_TYPE = "type";
@@ -26597,9 +26606,10 @@
public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseTvColumns {
field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
- field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
- field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_1_1 = 3; // 0x3
+ field public static final int ASPECT_RATIO_2_3 = 4; // 0x4
field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int ASPECT_RATIO_4_3 = 2; // 0x2
field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
@@ -26694,6 +26704,8 @@
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_REVIEW_RATING = "review_rating";
+ field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
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";
@@ -26708,6 +26720,9 @@
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
field public static final android.net.Uri CONTENT_URI;
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
}
public static final class TvContract.Programs.Genres {
@@ -26754,6 +26769,8 @@
field public static final java.lang.String COLUMN_RECORDING_DATA_URI = "recording_data_uri";
field public static final java.lang.String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis";
field public static final java.lang.String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis";
+ field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+ field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
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 java.lang.String COLUMN_SEASON_TITLE = "season_title";
@@ -26767,14 +26784,18 @@
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/recorded_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/recorded_program";
field public static final android.net.Uri CONTENT_URI;
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
}
public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BaseTvColumns {
ctor public TvContract.WatchNextPrograms();
field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
- field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
- field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_1_1 = 3; // 0x3
+ field public static final int ASPECT_RATIO_2_3 = 4; // 0x4
field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int ASPECT_RATIO_4_3 = 2; // 0x2
field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
@@ -26982,6 +27003,9 @@
method public boolean isParentalControlsEnabled();
method public boolean isRatingBlocked(android.media.tv.TvContentRating);
method public boolean isSingleSessionActive();
+ method public void notifyPreviewProgramAddedToWatchNext(java.lang.String, long, long);
+ method public void notifyPreviewProgramBrowsableDisabled(java.lang.String, long);
+ method public void notifyWatchNextProgramBrowsableDisabled(java.lang.String, long);
method public void registerCallback(android.media.tv.TvInputManager.TvInputCallback, android.os.Handler);
method public void releaseTvInputHardware(int, android.media.tv.TvInputManager.Hardware);
method public void removeBlockedRating(android.media.tv.TvContentRating);
@@ -27682,22 +27706,25 @@
method public java.lang.String getName();
method public int getTruncationLengthBits();
method public void writeToParcel(android.os.Parcel, int);
- field public static final java.lang.String ALGO_AUTH_HMAC_MD5 = "hmac(md5)";
- field public static final java.lang.String ALGO_AUTH_HMAC_SHA1 = "hmac(sha1)";
- field public static final java.lang.String ALGO_AUTH_HMAC_SHA256 = "hmac(sha256)";
- field public static final java.lang.String ALGO_AUTH_HMAC_SHA384 = "hmac(sha384)";
- field public static final java.lang.String ALGO_AUTH_HMAC_SHA512 = "hmac(sha512)";
- field public static final java.lang.String ALGO_CRYPT_AES_CBC = "cbc(aes)";
+ field public static final java.lang.String AUTH_HMAC_MD5 = "hmac(md5)";
+ field public static final java.lang.String AUTH_HMAC_SHA1 = "hmac(sha1)";
+ field public static final java.lang.String AUTH_HMAC_SHA256 = "hmac(sha256)";
+ field public static final java.lang.String AUTH_HMAC_SHA384 = "hmac(sha384)";
+ field public static final java.lang.String AUTH_HMAC_SHA512 = "hmac(sha512)";
field public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR;
+ field public static final java.lang.String CRYPT_AES_CBC = "cbc(aes)";
}
public final class IpSecManager {
method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
+ method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
+ method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform);
+ method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
}
@@ -34642,7 +34669,7 @@
field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
field public static final java.lang.String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
field public static final java.lang.String DISALLOW_NETWORK_RESET = "no_network_reset";
- field public static final java.lang.String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
+ field public static final deprecated java.lang.String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
field public static final java.lang.String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
field public static final java.lang.String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
field public static final java.lang.String DISALLOW_REMOVE_MANAGED_PROFILE = "no_remove_managed_profile";
@@ -34794,7 +34821,7 @@
field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726
field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b
field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e
- field public static final int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750
+ field public static final deprecated int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750
field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728
field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b
field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740
@@ -37461,10 +37488,15 @@
}
public class FontsContract {
+ method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[], int, boolean, java.lang.String);
+ method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[]);
+ method public static android.provider.FontsContract.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal, android.graphics.fonts.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static void requestFont(android.content.Context, android.graphics.fonts.FontRequest, android.provider.FontsContract.FontRequestCallback, android.os.Handler);
}
public static final class FontsContract.Columns implements android.provider.BaseColumns {
ctor public FontsContract.Columns();
+ field public static final java.lang.String FILE_ID = "file_id";
field public static final java.lang.String ITALIC = "font_italic";
field public static final java.lang.String RESULT_CODE = "result_code";
field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
@@ -37476,6 +37508,35 @@
field public static final java.lang.String WEIGHT = "font_weight";
}
+ public static class FontsContract.FontFamilyResult {
+ method public android.provider.FontsContract.FontInfo[] getFonts();
+ method public int getStatusCode();
+ field public static final int STATUS_OK = 0; // 0x0
+ field public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2; // 0x2
+ field public static final int STATUS_WRONG_CERTIFICATES = 1; // 0x1
+ }
+
+ public static class FontsContract.FontInfo {
+ method public android.graphics.fonts.FontVariationAxis[] getAxes();
+ method public int getResultCode();
+ method public int getTtcIndex();
+ method public android.net.Uri getUri();
+ method public int getWeight();
+ method public boolean isItalic();
+ }
+
+ public static class FontsContract.FontRequestCallback {
+ ctor public FontsContract.FontRequestCallback();
+ method public void onTypefaceRequestFailed(int);
+ method public void onTypefaceRetrieved(android.graphics.Typeface);
+ field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+ field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+ field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+ field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
+ }
+
public final deprecated class LiveFolders implements android.provider.BaseColumns {
field public static final java.lang.String ACTION_CREATE_LIVE_FOLDER = "android.intent.action.CREATE_LIVE_FOLDER";
field public static final java.lang.String DESCRIPTION = "description";
@@ -37963,8 +38024,8 @@
field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
field public static final java.lang.String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
field public static final java.lang.String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
- field public static final java.lang.String ACTION_MANAGE_EXTERNAL_SOURCES = "android.settings.action.MANAGE_EXTERNAL_SOURCES";
field public static final java.lang.String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
+ field public static final java.lang.String ACTION_MANAGE_UNKNOWN_APP_SOURCES = "android.settings.action.MANAGE_UNKNOWN_APP_SOURCES";
field public static final java.lang.String ACTION_MANAGE_WRITE_SETTINGS = "android.settings.action.MANAGE_WRITE_SETTINGS";
field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
field public static final java.lang.String ACTION_NETWORK_OPERATOR_SETTINGS = "android.settings.NETWORK_OPERATOR_SETTINGS";
@@ -38124,6 +38185,7 @@
field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
field public static final java.lang.String INPUT_METHOD_SELECTOR_VISIBILITY = "input_method_selector_visibility";
field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+ field public static final java.lang.String INSTANT_APPS_ENABLED = "instant_apps_enabled";
field public static final java.lang.String LOCATION_MODE = "location_mode";
field public static final int LOCATION_MODE_BATTERY_SAVING = 2; // 0x2
field public static final int LOCATION_MODE_HIGH_ACCURACY = 3; // 0x3
@@ -40082,7 +40144,7 @@
public abstract class AutofillService extends android.app.Service {
ctor public AutofillService();
- method public final void disableSelf();
+ method public final deprecated void disableSelf();
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConnected();
method public void onDisconnected();
@@ -40271,7 +40333,7 @@
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public boolean dispatchTouchEvent(android.view.MotionEvent);
method public boolean dispatchTrackballEvent(android.view.MotionEvent);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public final void finish();
method public android.view.Window getWindow();
method public android.view.WindowManager getWindowManager();
@@ -40441,12 +40503,16 @@
method public final int getCurrentInterruptionFilter();
method public final int getCurrentListenerHints();
method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
+ method public final java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(java.lang.String);
+ method public final java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String);
method public final android.service.notification.StatusBarNotification[] getSnoozedNotifications();
method public android.os.IBinder onBind(android.content.Intent);
method public void onInterruptionFilterChanged(int);
method public void onListenerConnected();
method public void onListenerDisconnected();
method public void onListenerHintsChanged(int);
+ method public void onNotificationChannelGroupModified(java.lang.String, android.app.NotificationChannelGroup, int);
+ method public void onNotificationChannelModified(java.lang.String, android.app.NotificationChannel, int);
method public void onNotificationPosted(android.service.notification.StatusBarNotification);
method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap);
@@ -40463,6 +40529,7 @@
method public final void snoozeNotification(java.lang.String, java.lang.String);
method public final void snoozeNotification(java.lang.String, long);
method public void unregisterAsSystemService() throws android.os.RemoteException;
+ method public final void updateNotificationChannel(java.lang.String, android.app.NotificationChannel);
field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
@@ -40471,6 +40538,9 @@
field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
+ field public static final int NOTIFICATION_CHANNEL_OR_GROUP_ADDED = 1; // 0x1
+ field public static final int NOTIFICATION_CHANNEL_OR_GROUP_DELETED = 3; // 0x3
+ field public static final int NOTIFICATION_CHANNEL_OR_GROUP_UPDATED = 2; // 0x2
field public static final int REASON_APP_CANCEL = 8; // 0x8
field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
field public static final int REASON_CANCEL = 2; // 0x2
@@ -40557,15 +40627,26 @@
}
+package android.service.oemlock {
+
+ public class OemLockManager {
+ method public boolean isOemUnlockAllowedByCarrier();
+ method public boolean isOemUnlockAllowedByUser();
+ method public void setOemUnlockAllowedByCarrier(boolean, byte[]);
+ method public void setOemUnlockAllowedByUser(boolean);
+ }
+
+}
+
package android.service.persistentdata {
public class PersistentDataBlockManager {
method public int getDataBlockSize();
method public int getFlashLockState();
method public long getMaximumDataBlockSize();
- method public boolean getOemUnlockEnabled();
+ method public deprecated boolean getOemUnlockEnabled();
method public byte[] read();
- method public void setOemUnlockEnabled(boolean);
+ method public deprecated void setOemUnlockEnabled(boolean);
method public void wipe();
method public int write(byte[]);
field public static final int FLASH_LOCK_LOCKED = 1; // 0x1
@@ -42777,6 +42858,7 @@
method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(java.lang.String);
+ method public java.util.List<android.telecom.PhoneAccountHandle> getSelfManagedPhoneAccounts();
method public android.telecom.PhoneAccountHandle getSimCallManager();
method public java.lang.String getVoiceMailNumber(android.telecom.PhoneAccountHandle);
method public boolean handleMmi(java.lang.String);
@@ -43552,7 +43634,7 @@
method public java.lang.String getCdmaMdn(int);
method public java.lang.String getCdmaMin();
method public java.lang.String getCdmaMin(int);
- method public android.telephony.CellLocation getCellLocation();
+ method public deprecated android.telephony.CellLocation getCellLocation();
method public int getCurrentPhoneType();
method public int getCurrentPhoneType(int);
method public int getDataActivity();
@@ -43601,7 +43683,8 @@
method public boolean hasIccCard();
method public boolean iccCloseLogicalChannel(int);
method public byte[] iccExchangeSimIO(int, int, int, int, int, java.lang.String);
- method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
+ method public deprecated android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
+ method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String, int);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
method public boolean isConcurrentVoiceAndDataSupported();
@@ -43616,7 +43699,7 @@
method public boolean isSmsCapable();
method public boolean isTtyModeSupported();
method public boolean isVideoCallingEnabled();
- method public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
+ method public deprecated boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
method public boolean isVoiceCapable();
method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
method public boolean isWorldPhone();
@@ -43633,7 +43716,7 @@
method public boolean setPreferredNetworkTypeToGlobal();
method public boolean setRadio(boolean);
method public boolean setRadioPower(boolean);
- method public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
+ method public deprecated void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
method public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
method public void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean);
@@ -43886,8 +43969,8 @@
package android.telephony.ims {
- public class ImsServiceBase extends android.app.Service {
- ctor public ImsServiceBase();
+ public class ImsService extends android.app.Service {
+ ctor public ImsService();
method public android.os.IBinder onBind(android.content.Intent);
}
@@ -46168,7 +46251,7 @@
method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, java.lang.String[], android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter);
field public static final int ALL = 15; // 0xf
field public static final int EMAIL_ADDRESSES = 2; // 0x2
- field public static final int MAP_ADDRESSES = 8; // 0x8
+ field public static final deprecated int MAP_ADDRESSES = 8; // 0x8
field public static final int PHONE_NUMBERS = 4; // 0x4
field public static final int WEB_URLS = 1; // 0x1
field public static final android.text.util.Linkify.MatchFilter sPhoneNumberMatchFilter;
@@ -47382,7 +47465,6 @@
method public boolean isValid();
method public boolean isWideColorGamut();
field public static final int DEFAULT_DISPLAY = 0; // 0x0
- field public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
field public static final int FLAG_PRESENTATION = 8; // 0x8
field public static final int FLAG_PRIVATE = 4; // 0x4
field public static final int FLAG_ROUND = 16; // 0x10
@@ -48880,6 +48962,7 @@
method public java.lang.CharSequence getContentDescription();
method public final android.content.Context getContext();
method protected android.view.ContextMenu.ContextMenuInfo getContextMenuInfo();
+ method public final boolean getDefaultFocusHighlightEnabled();
method public static int getDefaultSize(int, int);
method public android.view.Display getDisplay();
method public final int[] getDrawableState();
@@ -49198,6 +49281,7 @@
method public void setClipToOutline(boolean);
method public void setContentDescription(java.lang.CharSequence);
method public void setContextClickable(boolean);
+ method public void setDefaultFocusHighlightEnabled(boolean);
method public void setDrawingCacheBackgroundColor(int);
method public void setDrawingCacheEnabled(boolean);
method public void setDrawingCacheQuality(int);
@@ -51284,6 +51368,7 @@
public final class AutofillManager {
method public void cancel();
method public void commit();
+ method public void disableOwnedAutofillServices();
method public boolean isEnabled();
method public void notifyValueChanged(android.view.View);
method public void notifyValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
@@ -52534,7 +52619,7 @@
method public void documentHasImages(android.os.Message);
method public static void enableSlowWholeDocumentDraw();
method public void evaluateJavascript(java.lang.String, android.webkit.ValueCallback<java.lang.String>);
- method public static java.lang.String findAddress(java.lang.String);
+ method public static deprecated java.lang.String findAddress(java.lang.String);
method public deprecated int findAll(java.lang.String);
method public void findAllAsync(java.lang.String);
method public void findNext(boolean);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 1effe9c..bdcafae 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -98,6 +98,18 @@
}
+package android.hardware {
+
+ public final class SensorDirectChannel implements java.nio.channels.Channel {
+ method public deprecated boolean isValid();
+ }
+
+ public abstract class SensorManager {
+ method public deprecated int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
+ }
+
+}
+
package android.media {
public final class AudioFormat implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 570855f..1fed007 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -210,6 +210,7 @@
public static final class R.attr {
ctor public R.attr();
field public static final int __removed1 = 16844099; // 0x1010543
+ field public static final int __removed2 = 16844104; // 0x1010548
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -471,6 +472,7 @@
field public static final deprecated int dayOfWeekBackground = 16843924; // 0x1010494
field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
field public static final int debuggable = 16842767; // 0x101000f
+ field public static final int defaultFocusHighlightEnabled = 16844133; // 0x1010565
field public static final int defaultHeight = 16844021; // 0x10104f5
field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
field public static final int defaultValue = 16843245; // 0x10101ed
@@ -991,6 +993,7 @@
field public static final int persistableMode = 16843821; // 0x101042d
field public static final int persistent = 16842765; // 0x101000d
field public static final int persistentDrawingCache = 16842990; // 0x10100ee
+ field public static final int persistentFeature = 16844134; // 0x1010566
field public static final deprecated int phoneNumber = 16843111; // 0x1010167
field public static final int pivotX = 16843189; // 0x10101b5
field public static final int pivotY = 16843190; // 0x10101b6
@@ -1269,7 +1272,6 @@
field public static final int summaryOff = 16843248; // 0x10101f0
field public static final int summaryOn = 16843247; // 0x10101ef
field public static final int supportsAssist = 16844016; // 0x10104f0
- field public static final int supportsDismissingWindow = 16844104; // 0x1010548
field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
field public static final int supportsLocalInteraction = 16844047; // 0x101050f
field public static final int supportsPictureInPicture = 16844023; // 0x10104f7
@@ -1539,6 +1541,7 @@
field public static final int windowShowAnimation = 16842934; // 0x10100b6
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
+ field public static final int windowSplashscreenContent = 16844135; // 0x1010567
field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
field public static final int windowTitleSize = 16842842; // 0x101005a
@@ -1951,6 +1954,7 @@
field public static final int no = 17039369; // 0x1040009
field public static final int ok = 17039370; // 0x104000a
field public static final int paste = 17039371; // 0x104000b
+ field public static final int paste_as_plain_text = 17039385; // 0x1040019
field public static final int search_go = 17039372; // 0x104000c
field public static final int selectAll = 17039373; // 0x104000d
field public static final int selectTextMode = 17039382; // 0x1040016
@@ -2996,6 +3000,7 @@
method public android.accounts.AccountManagerFuture<android.os.Bundle> startAddAccountSession(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> startUpdateCredentialsSession(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> updateCredentials(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+ field public static final java.lang.String ACTION_ACCOUNT_REMOVED = "android.accounts.action.ACCOUNT_REMOVED";
field public static final java.lang.String ACTION_AUTHENTICATOR_INTENT = "android.accounts.AccountAuthenticator";
field public static final java.lang.String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
field public static final java.lang.String AUTHENTICATOR_META_DATA_NAME = "android.accounts.AccountAuthenticator";
@@ -3848,6 +3853,7 @@
method public android.app.PendingIntent getRunningServiceControlPanel(android.content.ComponentName) throws java.lang.SecurityException;
method public java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException;
method public deprecated java.util.List<android.app.ActivityManager.RunningTaskInfo> getRunningTasks(int) throws java.lang.SecurityException;
+ method public int getUidImportance(int);
method public deprecated boolean isInLockTaskMode();
method public boolean isLowRamDevice();
method public static boolean isRunningInTestHarness();
@@ -4707,7 +4713,7 @@
public abstract class FragmentContainer {
ctor public FragmentContainer();
method public android.app.Fragment instantiate(android.content.Context, java.lang.String, android.os.Bundle);
- method public abstract android.view.View onFindViewById(int);
+ method public abstract <T extends android.view.View> T onFindViewById(int);
method public abstract boolean onHasView();
}
@@ -4758,7 +4764,7 @@
ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
method public void onAttachFragment(android.app.Fragment);
method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
- method public android.view.View onFindViewById(int);
+ method public <T extends android.view.View> T onFindViewById(int);
method public abstract E onGetHost();
method public android.view.LayoutInflater onGetLayoutInflater();
method public int onGetWindowAnimations();
@@ -6817,6 +6823,7 @@
field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
field public static final int NETWORK_TYPE_ANY = 1; // 0x1
+ field public static final int NETWORK_TYPE_METERED = 4; // 0x4
field public static final int NETWORK_TYPE_NONE = 0; // 0x0
field public static final int NETWORK_TYPE_NOT_ROAMING = 3; // 0x3
field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
@@ -6855,6 +6862,8 @@
}
public class JobParameters implements android.os.Parcelable {
+ method public void completeWork(android.app.job.JobWorkItem);
+ method public android.app.job.JobWorkItem dequeueWork();
method public int describeContents();
method public android.content.ClipData getClipData();
method public int getClipGrantFlags();
@@ -6872,6 +6881,7 @@
ctor public JobScheduler();
method public abstract void cancel(int);
method public abstract void cancelAll();
+ method public abstract int enqueue(android.app.job.JobInfo, android.app.job.JobWorkItem);
method public abstract java.util.List<android.app.job.JobInfo> getAllPendingJobs();
method public abstract android.app.job.JobInfo getPendingJob(int);
method public abstract int schedule(android.app.job.JobInfo);
@@ -6888,6 +6898,15 @@
field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE";
}
+ public final class JobWorkItem implements android.os.Parcelable {
+ ctor public JobWorkItem(android.content.Intent);
+ ctor public JobWorkItem(android.os.Parcel);
+ method public int describeContents();
+ method public android.content.Intent getIntent();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.job.JobWorkItem> CREATOR;
+ }
+
}
package android.app.usage {
@@ -7621,9 +7640,11 @@
field public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; // 0x2
field public static final int PAIRING_VARIANT_PIN = 0; // 0x0
field public static final int PHY_LE_1M = 1; // 0x1
+ field public static final int PHY_LE_1M_MASK = 1; // 0x1
field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_ANY = 7; // 0x7
- field public static final int PHY_LE_CODED = 4; // 0x4
+ field public static final int PHY_LE_2M_MASK = 2; // 0x2
+ field public static final int PHY_LE_CODED = 3; // 0x3
+ field public static final int PHY_LE_CODED_MASK = 4; // 0x4
field public static final int PHY_OPTION_NO_PREFERRED = 0; // 0x0
field public static final int PHY_OPTION_S2 = 1; // 0x1
field public static final int PHY_OPTION_S8 = 2; // 0x2
@@ -8041,9 +8062,6 @@
field public static final int INTERVAL_MAX = 16777215; // 0xffffff
field public static final int INTERVAL_MEDIUM = 400; // 0x190
field public static final int INTERVAL_MIN = 160; // 0xa0
- field public static final int PHY_LE_1M = 1; // 0x1
- field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int TX_POWER_HIGH = 1; // 0x1
field public static final int TX_POWER_LOW = -15; // 0xfffffff1
field public static final int TX_POWER_MAX = 1; // 0x1
@@ -8086,7 +8104,6 @@
public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
method public int describeContents();
- method public boolean getEnable();
method public boolean getIncludeTxPower();
method public int getInterval();
method public void writeToParcel(android.os.Parcel, int);
@@ -8096,7 +8113,6 @@
public static final class PeriodicAdvertisingParameters.Builder {
ctor public PeriodicAdvertisingParameters.Builder();
method public android.bluetooth.le.PeriodicAdvertisingParameters build();
- method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setEnable(boolean);
method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setIncludeTxPower(boolean);
method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
}
@@ -8174,9 +8190,6 @@
field public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR;
field public static final int DATA_COMPLETE = 0; // 0x0
field public static final int DATA_TRUNCATED = 2; // 0x2
- field public static final int PHY_LE_1M = 1; // 0x1
- field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int PHY_UNUSED = 0; // 0x0
field public static final int SID_NOT_PRESENT = 255; // 0xff
}
@@ -8199,9 +8212,7 @@
field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2
field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3
field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1
- field public static final int PHY_LE_1M = 1; // 0x1
field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff
- field public static final int PHY_LE_CODED = 3; // 0x3
field public static final int SCAN_MODE_BALANCED = 1; // 0x1
field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
@@ -9346,6 +9357,7 @@
field public static final java.lang.String ACTION_MANAGED_PROFILE_UNLOCKED = "android.intent.action.MANAGED_PROFILE_UNLOCKED";
field public static final java.lang.String ACTION_MANAGE_NETWORK_USAGE = "android.intent.action.MANAGE_NETWORK_USAGE";
field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
+ field public static final deprecated java.lang.String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
field public static final java.lang.String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
field public static final java.lang.String ACTION_MEDIA_CHECKING = "android.intent.action.MEDIA_CHECKING";
@@ -9368,6 +9380,7 @@
field public static final java.lang.String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
field public static final java.lang.String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
field public static final java.lang.String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
+ field public static final java.lang.String ACTION_PACKAGE_FIRST_ADDED = "android.intent.action.PACKAGE_FIRST_ADDED";
field public static final java.lang.String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
field public static final java.lang.String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
field public static final deprecated java.lang.String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
@@ -9484,6 +9497,7 @@
field public static final java.lang.String EXTRA_DONT_KILL_APP = "android.intent.extra.DONT_KILL_APP";
field public static final java.lang.String EXTRA_EMAIL = "android.intent.extra.EMAIL";
field public static final java.lang.String EXTRA_EXCLUDE_COMPONENTS = "android.intent.extra.EXCLUDE_COMPONENTS";
+ field public static final java.lang.String EXTRA_FROM_STORAGE = "android.intent.extra.FROM_STORAGE";
field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
field public static final java.lang.String EXTRA_INDEX = "android.intent.extra.INDEX";
field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
@@ -10384,12 +10398,10 @@
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
- method public deprecated android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
- field public static final deprecated int FLAG_MATCH_CHOOSER = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10660,6 +10672,7 @@
field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency";
field public static final java.lang.String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
field public static final java.lang.String FEATURE_AUDIO_PRO = "android.hardware.audio.pro";
+ field public static final java.lang.String FEATURE_AUTOFILL = "android.software.autofill";
field public static final java.lang.String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
field public static final java.lang.String FEATURE_BACKUP = "android.software.backup";
field public static final java.lang.String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
@@ -10946,9 +10959,6 @@
method public int describeContents();
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
- method public deprecated android.content.ComponentName[] getChooserComponentNames();
- method public deprecated android.os.PersistableBundle getChooserExtras();
- method public deprecated android.content.IntentFilter[] getChooserIntentFilters();
method public java.lang.CharSequence getDisabledMessage();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
@@ -10961,7 +10971,6 @@
method public java.lang.CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
- method public deprecated boolean isChooser();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -10974,11 +10983,9 @@
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
- method public deprecated android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
- method public deprecated android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -11766,15 +11773,6 @@
field protected final java.util.ArrayList<T> mObservers;
}
- public final class PageViewCursor extends android.database.CursorWrapper implements android.database.CrossProcessCursor {
- ctor public PageViewCursor(android.database.Cursor, android.os.Bundle);
- method public void fillWindow(int, android.database.CursorWindow);
- method public android.database.CursorWindow getWindow();
- method public boolean onMove(int, int);
- method public static android.database.Cursor wrap(android.database.Cursor, android.os.Bundle);
- field public static final java.lang.String EXTRA_AUTO_PAGED = "android.content.extra.AUTO_PAGED";
- }
-
public class SQLException extends java.lang.RuntimeException {
ctor public SQLException();
ctor public SQLException(java.lang.String);
@@ -12871,7 +12869,6 @@
method public static android.graphics.ColorSpace.Connector connect(android.graphics.ColorSpace, android.graphics.ColorSpace, android.graphics.ColorSpace.RenderIntent);
method public static android.graphics.ColorSpace.Connector connect(android.graphics.ColorSpace);
method public static android.graphics.ColorSpace.Connector connect(android.graphics.ColorSpace, android.graphics.ColorSpace.RenderIntent);
- method public static android.graphics.ColorSpace.Renderer createRenderer();
method public float[] fromXyz(float, float, float);
method public abstract float[] fromXyz(float[]);
method public static android.graphics.ColorSpace get(android.graphics.ColorSpace.Named);
@@ -12955,16 +12952,6 @@
enum_constant public static final android.graphics.ColorSpace.RenderIntent SATURATION;
}
- public static class ColorSpace.Renderer {
- method public android.graphics.ColorSpace.Renderer add(android.graphics.ColorSpace, int);
- method public android.graphics.ColorSpace.Renderer add(android.graphics.ColorSpace, float, float, float, int);
- method public android.graphics.ColorSpace.Renderer clip(boolean);
- method public android.graphics.Bitmap render();
- method public android.graphics.ColorSpace.Renderer showWhitePoint(boolean);
- method public android.graphics.ColorSpace.Renderer size(int);
- method public android.graphics.ColorSpace.Renderer uniformChromaticityScale(boolean);
- }
-
public static class ColorSpace.Rgb extends android.graphics.ColorSpace {
ctor public ColorSpace.Rgb(java.lang.String, float[], java.util.function.DoubleUnaryOperator, java.util.function.DoubleUnaryOperator);
ctor public ColorSpace.Rgb(java.lang.String, float[], float[], java.util.function.DoubleUnaryOperator, java.util.function.DoubleUnaryOperator, float, float);
@@ -13809,7 +13796,7 @@
}
public class Typeface {
- method public static void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
+ method public static deprecated void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
method public static android.graphics.Typeface create(java.lang.String, int);
method public static android.graphics.Typeface create(android.graphics.Typeface, int);
method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String);
@@ -13831,26 +13818,20 @@
}
public static final class Typeface.Builder {
- ctor public Typeface.Builder();
+ ctor public Typeface.Builder(java.io.File);
+ ctor public Typeface.Builder(java.io.FileDescriptor);
+ ctor public Typeface.Builder(java.lang.String);
+ ctor public Typeface.Builder(android.content.res.AssetManager, java.lang.String);
method public android.graphics.Typeface build();
- method public static android.graphics.Typeface.Builder obtain();
- method public void recycle();
- method public void reset();
+ method public android.graphics.Typeface.Builder setFallback(java.lang.String);
method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
- method public android.graphics.Typeface.Builder setItalic(int);
- method public android.graphics.Typeface.Builder setSourceFromAsset(android.content.res.AssetManager, java.lang.String);
- method public android.graphics.Typeface.Builder setSourceFromFile(java.io.File);
- method public android.graphics.Typeface.Builder setSourceFromFile(java.io.FileDescriptor);
- method public android.graphics.Typeface.Builder setSourceFromFilePath(java.lang.String);
+ method public android.graphics.Typeface.Builder setItalic(boolean);
method public android.graphics.Typeface.Builder setTtcIndex(int);
method public android.graphics.Typeface.Builder setWeight(int);
- field public static final int ITALIC = 1; // 0x1
- field public static final int NORMAL = 0; // 0x0
- field public static final int RESOLVE_BY_FONT_TABLE = -1; // 0xffffffff
}
- public static abstract interface Typeface.FontRequestCallback {
+ public static abstract deprecated interface Typeface.FontRequestCallback {
method public abstract void onTypefaceRequestFailed(int);
method public abstract void onTypefaceRetrieved(android.graphics.Typeface);
field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
@@ -13882,7 +13863,7 @@
public class AdaptiveIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
method public void draw(android.graphics.Canvas);
method public android.graphics.drawable.Drawable getBackground();
- method public static float getExtraInsetPercentage();
+ method public static float getExtraInsetFraction();
method public android.graphics.drawable.Drawable getForeground();
method public android.graphics.Path getIconMask();
method public int getOpacity();
@@ -14034,6 +14015,7 @@
method public boolean getPadding(android.graphics.Rect);
method public int[] getState();
method public android.graphics.Region getTransparentRegion();
+ method public boolean hasFocusStateSpecified();
method public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public void invalidateSelf();
@@ -14362,6 +14344,7 @@
method public void setPadding(android.graphics.Rect);
method public void setShaderFactory(android.graphics.drawable.ShapeDrawable.ShaderFactory);
method public void setShape(android.graphics.drawable.shapes.Shape);
+ method public void setXfermode(android.graphics.Xfermode);
}
public static abstract class ShapeDrawable.ShaderFactory {
@@ -14448,15 +14431,12 @@
field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR;
}
- public final class FontVariationAxis implements android.os.Parcelable {
+ public final class FontVariationAxis {
ctor public FontVariationAxis(java.lang.String, float) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
- method public int describeContents();
method public static android.graphics.fonts.FontVariationAxis[] fromFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
method public float getStyleValue();
method public java.lang.String getTag();
method public static java.lang.String toFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontVariationAxis> CREATOR;
}
public static class FontVariationAxis.InvalidFormatException extends java.lang.Exception {
@@ -14922,15 +14902,16 @@
field public final int type;
}
- public final class SensorDirectChannel implements java.lang.AutoCloseable {
+ public final class SensorDirectChannel implements java.nio.channels.Channel {
method public void close();
- method public boolean isValid();
+ method public int configure(android.hardware.Sensor, int);
+ method public boolean isOpen();
field public static final int RATE_FAST = 2; // 0x2
field public static final int RATE_NORMAL = 1; // 0x1
field public static final int RATE_STOP = 0; // 0x0
field public static final int RATE_VERY_FAST = 3; // 0x3
- field public static final int TYPE_ASHMEM = 1; // 0x1
field public static final int TYPE_HARDWARE_BUFFER = 2; // 0x2
+ field public static final int TYPE_MEMORY_FILE = 1; // 0x1
}
public class SensorEvent {
@@ -14964,7 +14945,6 @@
public abstract class SensorManager {
method public boolean cancelTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
- method public int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
method public android.hardware.SensorDirectChannel createDirectChannel(android.os.MemoryFile);
method public android.hardware.SensorDirectChannel createDirectChannel(android.hardware.HardwareBuffer);
method public boolean flush(android.hardware.SensorEventListener);
@@ -15817,7 +15797,6 @@
method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
field public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 16; // 0x10
- field public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
field public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 8; // 0x8
field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2
field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1
@@ -20665,7 +20644,7 @@
method public double getAccumulatedDeltaRangeMeters();
method public int getAccumulatedDeltaRangeState();
method public double getAccumulatedDeltaRangeUncertaintyMeters();
- method public double getAutomaticGainControlLevelInDb();
+ method public double getAutomaticGainControlLevelDb();
method public long getCarrierCycles();
method public float getCarrierFrequencyHz();
method public double getCarrierPhase();
@@ -20681,7 +20660,7 @@
method public int getState();
method public int getSvid();
method public double getTimeOffsetNanos();
- method public boolean hasAutomaticGainControlLevelInDb();
+ method public boolean hasAutomaticGainControlLevelDb();
method public boolean hasCarrierCycles();
method public boolean hasCarrierFrequencyHz();
method public boolean hasCarrierPhase();
@@ -20812,7 +20791,7 @@
method public int getSatelliteCount();
method public int getSvid(int);
method public boolean hasAlmanacData(int);
- method public boolean hasCarrierFrequency(int);
+ method public boolean hasCarrierFrequencyHz(int);
method public boolean hasEphemerisData(int);
method public boolean usedInFix(int);
field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
@@ -21931,24 +21910,19 @@
field public static final int STOP_VIDEO_RECORDING = 3; // 0x3
}
- public final class MediaCas {
+ public final class MediaCas implements java.lang.AutoCloseable {
ctor public MediaCas(int) throws android.media.MediaCasException.UnsupportedCasException;
- method public void closeSession(byte[]);
+ method public void close();
method public static android.media.MediaCas.PluginDescriptor[] enumeratePlugins();
method public static boolean isSystemIdSupported(int);
- method public byte[] openSession(int) throws android.media.MediaCasException;
- method public byte[] openSession(int, int) throws android.media.MediaCasException;
- method public void processEcm(byte[], byte[], int, int) throws android.media.MediaCasException;
- method public void processEcm(byte[], byte[]) throws android.media.MediaCasException;
+ method public android.media.MediaCas.Session openSession() throws android.media.MediaCasException;
method public void processEmm(byte[], int, int) throws android.media.MediaCasException;
method public void processEmm(byte[]) throws android.media.MediaCasException;
method public void provision(java.lang.String) throws android.media.MediaCasException;
method public void refreshEntitlements(int, byte[]) throws android.media.MediaCasException;
- method public void release();
method public void sendEvent(int, int, byte[]) throws android.media.MediaCasException;
method public void setEventListener(android.media.MediaCas.EventListener, android.os.Handler);
method public void setPrivateData(byte[]) throws android.media.MediaCasException;
- method public void setSessionPrivateData(byte[], byte[]) throws android.media.MediaCasException;
}
public static abstract interface MediaCas.EventListener {
@@ -21960,6 +21934,13 @@
method public int getSystemId();
}
+ public final class MediaCas.Session implements java.lang.AutoCloseable {
+ method public void close();
+ method public void processEcm(byte[], int, int) throws android.media.MediaCasException;
+ method public void processEcm(byte[]) throws android.media.MediaCasException;
+ method public void setPrivateData(byte[]) throws android.media.MediaCasException;
+ }
+
public class MediaCasException extends java.lang.Exception {
}
@@ -22403,12 +22384,12 @@
method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
}
- public final class MediaDescrambler {
+ public final class MediaDescrambler implements java.lang.AutoCloseable {
ctor public MediaDescrambler(int) throws android.media.MediaCasException.UnsupportedCasException;
- method public final int descramble(java.nio.ByteBuffer, int, java.nio.ByteBuffer, int, android.media.MediaCodec.CryptoInfo);
- method public final void release();
+ method public void close();
+ method public final int descramble(java.nio.ByteBuffer, java.nio.ByteBuffer, android.media.MediaCodec.CryptoInfo);
method public final boolean requiresSecureDecoderComponent(java.lang.String);
- method public final void setMediaCasSession(byte[]);
+ method public final void setMediaCasSession(android.media.MediaCas.Session);
}
public class MediaDescription implements android.os.Parcelable {
@@ -22472,7 +22453,7 @@
method public void setOnKeyStatusChangeListener(android.media.MediaDrm.OnKeyStatusChangeListener, android.os.Handler);
method public void setPropertyByteArray(java.lang.String, byte[]);
method public void setPropertyString(java.lang.String, java.lang.String);
- field public static final int EVENT_KEY_EXPIRED = 3; // 0x3
+ field public static final deprecated int EVENT_KEY_EXPIRED = 3; // 0x3
field public static final int EVENT_KEY_REQUIRED = 2; // 0x2
field public static final deprecated int EVENT_PROVISION_REQUIRED = 1; // 0x1
field public static final int EVENT_SESSION_RECLAIMED = 5; // 0x5
@@ -22546,6 +22527,7 @@
ctor public MediaExtractor();
method public boolean advance();
method public long getCachedDuration();
+ method public android.media.MediaExtractor.CasInfo getCasInfo(int);
method public android.media.DrmInitData getDrmInitData();
method public android.media.MediaMetricsSet getMetrics();
method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
@@ -22577,6 +22559,11 @@
field public static final int SEEK_TO_PREVIOUS_SYNC = 0; // 0x0
}
+ public static final class MediaExtractor.CasInfo {
+ method public android.media.MediaCas.Session getSession();
+ method public int getSystemId();
+ }
+
public final class MediaFormat {
ctor public MediaFormat();
method public final boolean containsKey(java.lang.String);
@@ -23745,7 +23732,7 @@
public static final class VolumeShaper.Configuration implements android.os.Parcelable {
method public int describeContents();
- method public double getDurationMs();
+ method public double getDurationMillis();
method public int getInterpolatorType();
method public static int getMaximumCurvePoints();
method public float[] getTimes();
@@ -23771,7 +23758,7 @@
method public android.media.VolumeShaper.Configuration.Builder scaleToEndVolume(float);
method public android.media.VolumeShaper.Configuration.Builder scaleToStartVolume(float);
method public android.media.VolumeShaper.Configuration.Builder setCurve(float[], float[]);
- method public android.media.VolumeShaper.Configuration.Builder setDurationMs(double);
+ method public android.media.VolumeShaper.Configuration.Builder setDurationMillis(double);
method public android.media.VolumeShaper.Configuration.Builder setInterpolatorType(int);
}
@@ -24633,14 +24620,14 @@
method public static boolean isChannelUriForPassthroughInput(android.net.Uri);
method public static boolean isChannelUriForTunerInput(android.net.Uri);
method public static boolean isProgramUri(android.net.Uri);
+ method public static void requestChannelBrowsable(android.content.Context, long);
field public static final java.lang.String ACTION_INITIALIZE_PROGRAMS = "android.media.tv.action.INITIALIZE_PROGRAMS";
- field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
field public static final java.lang.String ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT = "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT";
field public static final java.lang.String ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED";
+ field public static final java.lang.String ACTION_REQUEST_CHANNEL_BROWSABLE = "android.media.tv.action.REQUEST_CHANNEL_BROWSABLE";
field public static final java.lang.String ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED";
field public static final java.lang.String AUTHORITY = "android.media.tv";
field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
- field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
field public static final java.lang.String EXTRA_PREVIEW_PROGRAM_ID = "android.media.tv.extra.PREVIEW_PROGRAM_ID";
field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
}
@@ -24733,9 +24720,10 @@
public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseTvColumns {
field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
- field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
- field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_1_1 = 3; // 0x3
+ field public static final int ASPECT_RATIO_2_3 = 4; // 0x4
field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int ASPECT_RATIO_4_3 = 2; // 0x2
field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
@@ -24830,6 +24818,8 @@
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_REVIEW_RATING = "review_rating";
+ field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
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";
@@ -24844,6 +24834,9 @@
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
field public static final android.net.Uri CONTENT_URI;
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
}
public static final class TvContract.Programs.Genres {
@@ -24890,6 +24883,8 @@
field public static final java.lang.String COLUMN_RECORDING_DATA_URI = "recording_data_uri";
field public static final java.lang.String COLUMN_RECORDING_DURATION_MILLIS = "recording_duration_millis";
field public static final java.lang.String COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS = "recording_expire_time_utc_millis";
+ field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+ field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
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 java.lang.String COLUMN_SEASON_TITLE = "season_title";
@@ -24903,14 +24898,18 @@
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/recorded_program";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/recorded_program";
field public static final android.net.Uri CONTENT_URI;
+ field public static final int REVIEW_RATING_STYLE_PERCENTAGE = 2; // 0x2
+ field public static final int REVIEW_RATING_STYLE_STARS = 0; // 0x0
+ field public static final int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1; // 0x1
}
public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BaseTvColumns {
ctor public TvContract.WatchNextPrograms();
field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
- field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
- field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+ field public static final int ASPECT_RATIO_1_1 = 3; // 0x3
+ field public static final int ASPECT_RATIO_2_3 = 4; // 0x4
field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+ field public static final int ASPECT_RATIO_4_3 = 2; // 0x2
field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
@@ -25629,22 +25628,25 @@
method public java.lang.String getName();
method public int getTruncationLengthBits();
method public void writeToParcel(android.os.Parcel, int);
- field public static final java.lang.String ALGO_AUTH_HMAC_MD5 = "hmac(md5)";
- field public static final java.lang.String ALGO_AUTH_HMAC_SHA1 = "hmac(sha1)";
- field public static final java.lang.String ALGO_AUTH_HMAC_SHA256 = "hmac(sha256)";
- field public static final java.lang.String ALGO_AUTH_HMAC_SHA384 = "hmac(sha384)";
- field public static final java.lang.String ALGO_AUTH_HMAC_SHA512 = "hmac(sha512)";
- field public static final java.lang.String ALGO_CRYPT_AES_CBC = "cbc(aes)";
+ field public static final java.lang.String AUTH_HMAC_MD5 = "hmac(md5)";
+ field public static final java.lang.String AUTH_HMAC_SHA1 = "hmac(sha1)";
+ field public static final java.lang.String AUTH_HMAC_SHA256 = "hmac(sha256)";
+ field public static final java.lang.String AUTH_HMAC_SHA384 = "hmac(sha384)";
+ field public static final java.lang.String AUTH_HMAC_SHA512 = "hmac(sha512)";
field public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR;
+ field public static final java.lang.String CRYPT_AES_CBC = "cbc(aes)";
}
public final class IpSecManager {
method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
+ method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
+ method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform);
+ method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
}
@@ -31859,6 +31861,7 @@
ctor public UserHandle(android.os.Parcel);
method public int describeContents();
method public static int getAppId(int);
+ method public int getIdentifier();
method public static android.os.UserHandle getUserHandleForUid(int);
method public static android.os.UserHandle readFromParcel(android.os.Parcel);
method public void writeToParcel(android.os.Parcel, int);
@@ -32053,7 +32056,7 @@
field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726
field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b
field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e
- field public static final int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750
+ field public static final deprecated int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750
field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728
field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b
field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740
@@ -34631,10 +34634,15 @@
}
public class FontsContract {
+ method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[], int, boolean, java.lang.String);
+ method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[]);
+ method public static android.provider.FontsContract.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal, android.graphics.fonts.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static void requestFont(android.content.Context, android.graphics.fonts.FontRequest, android.provider.FontsContract.FontRequestCallback, android.os.Handler);
}
public static final class FontsContract.Columns implements android.provider.BaseColumns {
ctor public FontsContract.Columns();
+ field public static final java.lang.String FILE_ID = "file_id";
field public static final java.lang.String ITALIC = "font_italic";
field public static final java.lang.String RESULT_CODE = "result_code";
field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
@@ -34646,6 +34654,35 @@
field public static final java.lang.String WEIGHT = "font_weight";
}
+ public static class FontsContract.FontFamilyResult {
+ method public android.provider.FontsContract.FontInfo[] getFonts();
+ method public int getStatusCode();
+ field public static final int STATUS_OK = 0; // 0x0
+ field public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2; // 0x2
+ field public static final int STATUS_WRONG_CERTIFICATES = 1; // 0x1
+ }
+
+ public static class FontsContract.FontInfo {
+ method public android.graphics.fonts.FontVariationAxis[] getAxes();
+ method public int getResultCode();
+ method public int getTtcIndex();
+ method public android.net.Uri getUri();
+ method public int getWeight();
+ method public boolean isItalic();
+ }
+
+ public static class FontsContract.FontRequestCallback {
+ ctor public FontsContract.FontRequestCallback();
+ method public void onTypefaceRequestFailed(int);
+ method public void onTypefaceRetrieved(android.graphics.Typeface);
+ field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+ field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+ field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+ field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
+ }
+
public final deprecated class LiveFolders implements android.provider.BaseColumns {
field public static final java.lang.String ACTION_CREATE_LIVE_FOLDER = "android.intent.action.CREATE_LIVE_FOLDER";
field public static final java.lang.String DESCRIPTION = "description";
@@ -35031,8 +35068,8 @@
field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
field public static final java.lang.String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
field public static final java.lang.String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
- field public static final java.lang.String ACTION_MANAGE_EXTERNAL_SOURCES = "android.settings.action.MANAGE_EXTERNAL_SOURCES";
field public static final java.lang.String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
+ field public static final java.lang.String ACTION_MANAGE_UNKNOWN_APP_SOURCES = "android.settings.action.MANAGE_UNKNOWN_APP_SOURCES";
field public static final java.lang.String ACTION_MANAGE_WRITE_SETTINGS = "android.settings.action.MANAGE_WRITE_SETTINGS";
field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
field public static final java.lang.String ACTION_NETWORK_OPERATOR_SETTINGS = "android.settings.NETWORK_OPERATOR_SETTINGS";
@@ -37144,7 +37181,7 @@
public abstract class AutofillService extends android.app.Service {
ctor public AutofillService();
- method public final void disableSelf();
+ method public final deprecated void disableSelf();
method public final android.os.IBinder onBind(android.content.Intent);
method public void onConnected();
method public void onDisconnected();
@@ -37333,7 +37370,7 @@
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public boolean dispatchTouchEvent(android.view.MotionEvent);
method public boolean dispatchTrackballEvent(android.view.MotionEvent);
- method public android.view.View findViewById(int);
+ method public <T extends android.view.View> T findViewById(int);
method public final void finish();
method public android.view.Window getWindow();
method public android.view.WindowManager getWindowManager();
@@ -37501,12 +37538,16 @@
method public final int getCurrentInterruptionFilter();
method public final int getCurrentListenerHints();
method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
+ method public final java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(java.lang.String);
+ method public final java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String);
method public final android.service.notification.StatusBarNotification[] getSnoozedNotifications();
method public android.os.IBinder onBind(android.content.Intent);
method public void onInterruptionFilterChanged(int);
method public void onListenerConnected();
method public void onListenerDisconnected();
method public void onListenerHintsChanged(int);
+ method public void onNotificationChannelGroupModified(java.lang.String, android.app.NotificationChannelGroup, int);
+ method public void onNotificationChannelModified(java.lang.String, android.app.NotificationChannel, int);
method public void onNotificationPosted(android.service.notification.StatusBarNotification);
method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap);
@@ -37520,6 +37561,7 @@
method public final void setNotificationsShown(java.lang.String[]);
method public final void snoozeNotification(java.lang.String, java.lang.String);
method public final void snoozeNotification(java.lang.String, long);
+ method public final void updateNotificationChannel(java.lang.String, android.app.NotificationChannel);
field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
@@ -37528,6 +37570,9 @@
field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
+ field public static final int NOTIFICATION_CHANNEL_OR_GROUP_ADDED = 1; // 0x1
+ field public static final int NOTIFICATION_CHANNEL_OR_GROUP_DELETED = 3; // 0x3
+ field public static final int NOTIFICATION_CHANNEL_OR_GROUP_UPDATED = 2; // 0x2
field public static final int REASON_APP_CANCEL = 8; // 0x8
field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
field public static final int REASON_CANCEL = 2; // 0x2
@@ -39538,6 +39583,7 @@
method public android.telecom.PhoneAccountHandle getDefaultOutgoingPhoneAccount(java.lang.String);
method public java.lang.String getLine1Number(android.telecom.PhoneAccountHandle);
method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
+ method public java.util.List<android.telecom.PhoneAccountHandle> getSelfManagedPhoneAccounts();
method public android.telecom.PhoneAccountHandle getSimCallManager();
method public java.lang.String getVoiceMailNumber(android.telecom.PhoneAccountHandle);
method public boolean handleMmi(java.lang.String);
@@ -40266,7 +40312,7 @@
method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
method public int getCallState();
method public android.os.PersistableBundle getCarrierConfig();
- method public android.telephony.CellLocation getCellLocation();
+ method public deprecated android.telephony.CellLocation getCellLocation();
method public int getDataActivity();
method public int getDataNetworkType();
method public int getDataState();
@@ -40308,7 +40354,8 @@
method public boolean hasIccCard();
method public boolean iccCloseLogicalChannel(int);
method public byte[] iccExchangeSimIO(int, int, int, int, int, java.lang.String);
- method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
+ method public deprecated android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String);
+ method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(java.lang.String, int);
method public java.lang.String iccTransmitApduBasicChannel(int, int, int, int, int, java.lang.String);
method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
method public boolean isConcurrentVoiceAndDataSupported();
@@ -42823,7 +42870,7 @@
method public static final boolean addLinks(android.text.Spannable, java.util.regex.Pattern, java.lang.String, java.lang.String[], android.text.util.Linkify.MatchFilter, android.text.util.Linkify.TransformFilter);
field public static final int ALL = 15; // 0xf
field public static final int EMAIL_ADDRESSES = 2; // 0x2
- field public static final int MAP_ADDRESSES = 8; // 0x8
+ field public static final deprecated int MAP_ADDRESSES = 8; // 0x8
field public static final int PHONE_NUMBERS = 4; // 0x4
field public static final int WEB_URLS = 1; // 0x1
field public static final android.text.util.Linkify.MatchFilter sPhoneNumberMatchFilter;
@@ -44201,7 +44248,6 @@
method public boolean isValid();
method public boolean isWideColorGamut();
field public static final int DEFAULT_DISPLAY = 0; // 0x0
- field public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
field public static final int FLAG_PRESENTATION = 8; // 0x8
field public static final int FLAG_PRIVATE = 4; // 0x4
field public static final int FLAG_ROUND = 16; // 0x10
@@ -44272,6 +44318,7 @@
method public android.view.View findNextFocusFromRect(android.view.ViewGroup, android.graphics.Rect, int);
method public android.view.View findNextKeyboardNavigationCluster(android.view.View, android.view.View, int);
method public static android.view.FocusFinder getInstance();
+ method public static void sort(android.view.View[], int, int, android.view.ViewGroup, boolean);
}
public final class FrameMetrics {
@@ -45701,6 +45748,7 @@
method public java.lang.CharSequence getContentDescription();
method public final android.content.Context getContext();
method protected android.view.ContextMenu.ContextMenuInfo getContextMenuInfo();
+ method public final boolean getDefaultFocusHighlightEnabled();
method public static int getDefaultSize(int, int);
method public android.view.Display getDisplay();
method public final int[] getDrawableState();
@@ -46023,6 +46071,7 @@
method public void setClipToOutline(boolean);
method public void setContentDescription(java.lang.CharSequence);
method public void setContextClickable(boolean);
+ method public void setDefaultFocusHighlightEnabled(boolean);
method public void setDrawingCacheBackgroundColor(int);
method public void setDrawingCacheEnabled(boolean);
method public void setDrawingCacheQuality(int);
@@ -48114,6 +48163,7 @@
public final class AutofillManager {
method public void cancel();
method public void commit();
+ method public void disableOwnedAutofillServices();
method public boolean isEnabled();
method public void notifyValueChanged(android.view.View);
method public void notifyValueChanged(android.view.View, int, android.view.autofill.AutofillValue);
@@ -49271,7 +49321,7 @@
method public void documentHasImages(android.os.Message);
method public static void enableSlowWholeDocumentDraw();
method public void evaluateJavascript(java.lang.String, android.webkit.ValueCallback<java.lang.String>);
- method public static java.lang.String findAddress(java.lang.String);
+ method public static deprecated java.lang.String findAddress(java.lang.String);
method public deprecated int findAll(java.lang.String);
method public void findAllAsync(java.lang.String);
method public void findNext(boolean);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index d20c08c..82705fd 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -100,6 +100,18 @@
}
+package android.hardware {
+
+ public final class SensorDirectChannel implements java.nio.channels.Channel {
+ method public deprecated boolean isValid();
+ }
+
+ public abstract class SensorManager {
+ method public deprecated int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
+ }
+
+}
+
package android.media {
public final class AudioFormat implements android.os.Parcelable {
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index bfcad1b..1bcfb22 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -580,6 +580,11 @@
}
}
+ /**
+ * Wait until either {@link #restoreFinished} or {@link #restoreStarting} is called.
+ * Once one is called, it clears the internal flag again, so that the same observer intance
+ * can be reused for a next operation.
+ */
public void waitForCompletion() {
// The restoreFinished() callback will throw the 'done' flag; we
// just sit and wait on that notification.
@@ -590,6 +595,7 @@
} catch (InterruptedException ex) {
}
}
+ done = false;
}
}
}
diff --git a/cmds/bu/src/com/android/commands/bu/Backup.java b/cmds/bu/src/com/android/commands/bu/Backup.java
index ce114fd..345895b 100644
--- a/cmds/bu/src/com/android/commands/bu/Backup.java
+++ b/cmds/bu/src/com/android/commands/bu/Backup.java
@@ -57,7 +57,7 @@
} else if (arg.equals("restore")) {
doRestore(OsConstants.STDIN_FILENO);
} else {
- Log.e(TAG, "Invalid operation '" + arg + "'");
+ showUsage();
}
}
@@ -158,6 +158,21 @@
}
}
+ private static void showUsage() {
+ System.err.println(" backup [-f FILE] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all]");
+ System.err.println(" [-system|-nosystem] [-keyvalue|-nokeyvalue] [PACKAGE...]");
+ System.err.println(" write an archive of the device's data to FILE [default=backup.adb]");
+ System.err.println(" package list optional if -all/-shared are supplied");
+ System.err.println(" -apk/-noapk: do/don't back up .apk files (default -noapk)");
+ System.err.println(" -obb/-noobb: do/don't back up .obb files (default -noobb)");
+ System.err.println(" -shared|-noshared: do/don't back up shared storage (default -noshared)");
+ System.err.println(" -all: back up all installed applications");
+ System.err.println(" -system|-nosystem: include system apps in -all (default -system)");
+ System.err.println(" -keyvalue|-nokeyvalue: include apps that perform key/value backups.");
+ System.err.println(" (default -nokeyvalue)");
+ System.err.println(" restore FILE restore device contents from FILE");
+ }
+
private String nextArg() {
if (mNextArg >= mArgs.length) {
return null;
diff --git a/cmds/svc/src/com/android/commands/svc/PowerCommand.java b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
index 6ce29cb..920a52d 100644
--- a/cmds/svc/src/com/android/commands/svc/PowerCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
@@ -22,6 +22,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.os.SystemProperties;
public class PowerCommand extends Svc.Command {
public PowerCommand() {
@@ -87,7 +88,7 @@
// no confirm, wait till device is rebooted
pm.reboot(false, mode, true);
} catch (RemoteException e) {
- System.err.println("Failed to reboot.");
+ maybeLogRemoteException("Failed to reboot.");
}
return;
} else if ("shutdown".equals(args[1])) {
@@ -95,7 +96,7 @@
// no confirm, wait till device is off
pm.shutdown(false, null, true);
} catch (RemoteException e) {
- System.err.println("Failed to shutdown.");
+ maybeLogRemoteException("Failed to shutdown.");
}
return;
}
@@ -103,4 +104,14 @@
}
System.err.println(longHelp());
}
+
+ // Check if remote exception is benign during shutdown. Pm can be killed
+ // before system server during shutdown, so remote exception can be ignored
+ // if it is already in shutdown flow.
+ private void maybeLogRemoteException(String msg) {
+ String powerProp = SystemProperties.get("sys.powerctl");
+ if (powerProp.isEmpty()) {
+ System.err.println(msg);
+ }
+ }
}
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 8052288..b320d5d 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -335,6 +335,7 @@
* are removed, or an account's credentials (saved password, etc) are changed.
*
* @see #addOnAccountsUpdatedListener
+ * @see #ACTION_ACCOUNT_REMOVED
*
* @deprecated use {@link #addOnAccountsUpdatedListener} to get account updates in runtime.
*/
@@ -344,6 +345,14 @@
"android.accounts.LOGIN_ACCOUNTS_CHANGED";
/**
+ * Action sent as a broadcast Intent by the AccountsService when any account is removed.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @BroadcastBehavior(includeBackground = true)
+ public static final String ACTION_ACCOUNT_REMOVED =
+ "android.accounts.action.ACCOUNT_REMOVED";
+
+ /**
* Action sent as a broadcast Intent to specific package by the AccountsService
* when account visibility or account's credentials (saved password, etc) are changed.
*
diff --git a/core/java/android/accounts/ChooseAccountActivity.java b/core/java/android/accounts/ChooseAccountActivity.java
index 16a45ba..9f2c39b 100644
--- a/core/java/android/accounts/ChooseAccountActivity.java
+++ b/core/java/android/accounts/ChooseAccountActivity.java
@@ -77,7 +77,7 @@
setContentView(R.layout.choose_account);
// Setup the list
- ListView list = (ListView) findViewById(android.R.id.list);
+ ListView list = findViewById(android.R.id.list);
// Use an existing ListAdapter that will map an array of strings to TextViews
list.setAdapter(new AccountArrayAdapter(this,
android.R.layout.simple_list_item_1, mAccountInfos));
diff --git a/core/java/android/accounts/ChooseAccountTypeActivity.java b/core/java/android/accounts/ChooseAccountTypeActivity.java
index a3222d8..e3352bc 100644
--- a/core/java/android/accounts/ChooseAccountTypeActivity.java
+++ b/core/java/android/accounts/ChooseAccountTypeActivity.java
@@ -99,7 +99,7 @@
setContentView(R.layout.choose_account_type);
// Setup the list
- ListView list = (ListView) findViewById(android.R.id.list);
+ ListView list = findViewById(android.R.id.list);
// Use an existing ListAdapter that will map an array of strings to TextViews
list.setAdapter(new AccountArrayAdapter(this,
android.R.layout.simple_list_item_1, mAuthenticatorInfosToDisplay));
diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
index 8442585..6680ce6 100644
--- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java
+++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
@@ -248,7 +248,7 @@
populateUIAccountList(listItems);
// Only enable "OK" button if something has been selected.
- mOkButton = (Button) findViewById(android.R.id.button2);
+ mOkButton = findViewById(android.R.id.button2);
mOkButton.setEnabled(mSelectedItemIndex != SELECTED_ITEM_NONE);
}
@@ -592,7 +592,7 @@
* If not specified then makes the description invisible.
*/
private void overrideDescriptionIfSupplied(String descriptionOverride) {
- TextView descriptionView = (TextView) findViewById(R.id.description);
+ TextView descriptionView = findViewById(R.id.description);
if (!TextUtils.isEmpty(descriptionOverride)) {
descriptionView.setText(descriptionOverride);
} else {
@@ -605,7 +605,7 @@
* based on {@code mSelectedItemIndex} member variable.
*/
private final void populateUIAccountList(String[] listItems) {
- ListView list = (ListView) findViewById(android.R.id.list);
+ ListView list = findViewById(android.R.id.list);
list.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_single_choice, listItems));
list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
index 38eab29..af74b03 100644
--- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java
+++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
@@ -84,7 +84,7 @@
return;
}
- final TextView authTokenTypeView = (TextView) findViewById(R.id.authtoken_type);
+ final TextView authTokenTypeView = findViewById(R.id.authtoken_type);
authTokenTypeView.setVisibility(View.GONE);
final AccountManagerCallback<String> callback = new AccountManagerCallback<String>() {
@@ -116,7 +116,7 @@
findViewById(R.id.allow_button).setOnClickListener(this);
findViewById(R.id.deny_button).setOnClickListener(this);
- LinearLayout packagesListView = (LinearLayout) findViewById(R.id.packages_list);
+ LinearLayout packagesListView = findViewById(R.id.packages_list);
for (String pkg : packages) {
String packageLabel;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 95549d6..950991b 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4235,14 +4235,25 @@
mTaskDescription.setPrimaryColor(colorPrimary);
}
}
- // For dev-preview only.
- if (mTaskDescription.getBackgroundColor() == 0) {
- int colorBackground = a.getColor(
- com.android.internal.R.styleable.ActivityTaskDescription_colorBackground, 0);
- if (colorBackground != 0 && Color.alpha(colorBackground) == 0xFF) {
- mTaskDescription.setBackgroundColor(colorBackground);
- }
+
+ int colorBackground = a.getColor(
+ com.android.internal.R.styleable.ActivityTaskDescription_colorBackground, 0);
+ if (colorBackground != 0 && Color.alpha(colorBackground) == 0xFF) {
+ mTaskDescription.setBackgroundColor(colorBackground);
}
+
+ final int statusBarColor = a.getColor(
+ com.android.internal.R.styleable.ActivityTaskDescription_statusBarColor, 0);
+ if (statusBarColor != 0) {
+ mTaskDescription.setStatusBarColor(statusBarColor);
+ }
+
+ final int navigationBarColor = a.getColor(
+ com.android.internal.R.styleable.ActivityTaskDescription_navigationBarColor, 0);
+ if (navigationBarColor != 0) {
+ mTaskDescription.setNavigationBarColor(navigationBarColor);
+ }
+
a.recycle();
setTaskDescription(mTaskDescription);
}
@@ -4510,12 +4521,20 @@
*/
public void startActivityForResultAsUser(Intent intent, int requestCode,
@Nullable Bundle options, UserHandle user) {
+ startActivityForResultAsUser(intent, mEmbeddedID, requestCode, options, user);
+ }
+
+ /**
+ * @hide Implement to provide correct calling token.
+ */
+ public void startActivityForResultAsUser(Intent intent, String resultWho, int requestCode,
+ @Nullable Bundle options, UserHandle user) {
if (mParent != null) {
throw new RuntimeException("Can't be called from a child");
}
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
- this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode,
+ this, mMainThread.getApplicationThread(), mToken, resultWho, intent, requestCode,
options, user);
if (ar != null) {
mMainThread.sendActivityResult(
@@ -4552,7 +4571,7 @@
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
- this, mMainThread.getApplicationThread(), mToken, this,
+ this, mMainThread.getApplicationThread(), mToken, mEmbeddedID,
intent, -1, options, user);
if (ar != null) {
mMainThread.sendActivityResult(
@@ -5081,6 +5100,15 @@
/**
* @hide
*/
+ public void startActivityAsUserFromFragment(@NonNull Fragment fragment,
+ @RequiresPermission Intent intent, int requestCode, @Nullable Bundle options,
+ UserHandle user) {
+ startActivityForResultAsUser(intent, fragment.mWho, requestCode, options, user);
+ }
+
+ /**
+ * @hide
+ */
@Override
public void startActivityForResult(
String who, Intent intent, int requestCode, @Nullable Bundle options) {
@@ -5913,7 +5941,7 @@
*/
public void setTaskDescription(ActivityManager.TaskDescription taskDescription) {
if (mTaskDescription != taskDescription) {
- mTaskDescription.copyFrom(taskDescription);
+ mTaskDescription.copyFromPreserveHiddenFields(taskDescription);
// Scale the icon down to something reasonable if it is provided
if (taskDescription.getIconFilename() == null && taskDescription.getIcon() != null) {
final int size = ActivityManager.getLauncherLargeIconSizeInner(this);
@@ -7452,6 +7480,14 @@
}
@Override
+ public void onStartActivityAsUserFromFragment(
+ Fragment fragment, Intent intent, int requestCode, Bundle options,
+ UserHandle user) {
+ Activity.this.startActivityAsUserFromFragment(
+ fragment, intent, requestCode, options, user);
+ }
+
+ @Override
public void onStartIntentSenderFromFragment(Fragment fragment, IntentSender intent,
int requestCode, @Nullable Intent fillInIntent, int flagsMask, int flagsValues,
int extraFlags, Bundle options) throws IntentSender.SendIntentException {
@@ -7490,7 +7526,7 @@
@Nullable
@Override
- public View onFindViewById(int id) {
+ public <T extends View> T onFindViewById(int id) {
return Activity.this.findViewById(id);
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 4004bd6..8859831 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1145,6 +1145,8 @@
private String mIconFilename;
private int mColorPrimary;
private int mColorBackground;
+ private int mStatusBarColor;
+ private int mNavigationBarColor;
/**
* Creates the TaskDescription to the specified values.
@@ -1155,7 +1157,7 @@
* opaque.
*/
public TaskDescription(String label, Bitmap icon, int colorPrimary) {
- this(label, icon, null, colorPrimary, 0);
+ this(label, icon, null, colorPrimary, 0, 0, 0);
if ((colorPrimary != 0) && (Color.alpha(colorPrimary) != 255)) {
throw new RuntimeException("A TaskDescription's primary color should be opaque");
}
@@ -1168,7 +1170,7 @@
* @param icon An icon that represents the current state of this activity.
*/
public TaskDescription(String label, Bitmap icon) {
- this(label, icon, null, 0, 0);
+ this(label, icon, null, 0, 0, 0, 0);
}
/**
@@ -1177,24 +1179,26 @@
* @param label A label and description of the current state of this activity.
*/
public TaskDescription(String label) {
- this(label, null, null, 0, 0);
+ this(label, null, null, 0, 0, 0, 0);
}
/**
* Creates an empty TaskDescription.
*/
public TaskDescription() {
- this(null, null, null, 0, 0);
+ this(null, null, null, 0, 0, 0, 0);
}
/** @hide */
public TaskDescription(String label, Bitmap icon, String iconFilename, int colorPrimary,
- int colorBackground) {
+ int colorBackground, int statusBarColor, int navigationBarColor) {
mLabel = label;
mIcon = icon;
mIconFilename = iconFilename;
mColorPrimary = colorPrimary;
mColorBackground = colorBackground;
+ mStatusBarColor = statusBarColor;
+ mNavigationBarColor = navigationBarColor;
}
/**
@@ -1214,6 +1218,29 @@
mIconFilename = other.mIconFilename;
mColorPrimary = other.mColorPrimary;
mColorBackground = other.mColorBackground;
+ mStatusBarColor = other.mStatusBarColor;
+ mNavigationBarColor = other.mNavigationBarColor;
+ }
+
+ /**
+ * Copies this the values from another TaskDescription, but preserves the hidden fields
+ * if they weren't set on {@code other}
+ * @hide
+ */
+ public void copyFromPreserveHiddenFields(TaskDescription other) {
+ mLabel = other.mLabel;
+ mIcon = other.mIcon;
+ mIconFilename = other.mIconFilename;
+ mColorPrimary = other.mColorPrimary;
+ if (other.mColorBackground != 0) {
+ mColorBackground = other.mColorBackground;
+ }
+ if (other.mStatusBarColor != 0) {
+ mStatusBarColor = other.mStatusBarColor;
+ }
+ if (other.mNavigationBarColor != 0) {
+ mNavigationBarColor = other.mNavigationBarColor;
+ }
}
private TaskDescription(Parcel source) {
@@ -1253,6 +1280,20 @@
}
/**
+ * @hide
+ */
+ public void setStatusBarColor(int statusBarColor) {
+ mStatusBarColor = statusBarColor;
+ }
+
+ /**
+ * @hide
+ */
+ public void setNavigationBarColor(int navigationBarColor) {
+ mNavigationBarColor = navigationBarColor;
+ }
+
+ /**
* Sets the icon for this task description.
* @hide
*/
@@ -1325,6 +1366,20 @@
return mColorBackground;
}
+ /**
+ * @hide
+ */
+ public int getStatusBarColor() {
+ return mStatusBarColor;
+ }
+
+ /**
+ * @hide
+ */
+ public int getNavigationBarColor() {
+ return mNavigationBarColor;
+ }
+
/** @hide */
public void saveToXml(XmlSerializer out) throws IOException {
if (mLabel != null) {
@@ -1377,6 +1432,8 @@
}
dest.writeInt(mColorPrimary);
dest.writeInt(mColorBackground);
+ dest.writeInt(mStatusBarColor);
+ dest.writeInt(mNavigationBarColor);
if (mIconFilename == null) {
dest.writeInt(0);
} else {
@@ -1390,6 +1447,8 @@
mIcon = source.readInt() > 0 ? Bitmap.CREATOR.createFromParcel(source) : null;
mColorPrimary = source.readInt();
mColorBackground = source.readInt();
+ mStatusBarColor = source.readInt();
+ mNavigationBarColor = source.readInt();
mIconFilename = source.readInt() > 0 ? source.readString() : null;
}
@@ -1407,7 +1466,9 @@
public String toString() {
return "TaskDescription Label: " + mLabel + " Icon: " + mIcon +
" IconFilename: " + mIconFilename + " colorPrimary: " + mColorPrimary +
- " colorBackground: " + mColorBackground;
+ " colorBackground: " + mColorBackground +
+ " statusBarColor: " + mColorBackground +
+ " navigationBarColor: " + mNavigationBarColor;
}
}
@@ -3347,6 +3408,26 @@
}
/**
+ * Return the importance of a given uid, based on the processes that are
+ * currently running. The return value is one of the importance constants defined
+ * in {@link RunningAppProcessInfo}, giving you the highest importance of all the
+ * processes that this uid has running. If there are no processes
+ * running its code, {@link RunningAppProcessInfo#IMPORTANCE_GONE} is returned.
+ * @hide
+ */
+ @SystemApi @TestApi
+ @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
+ public int getUidImportance(int uid) {
+ try {
+ int procState = getService().getUidProcessState(uid,
+ mContext.getOpPackageName());
+ return RunningAppProcessInfo.procStateToImportance(procState);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Callback to get reports about changes to the importance of a uid. Use with
* {@link #addOnUidImportanceListener}.
* @hide
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3167ba7..5022d7d 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2199,7 +2199,7 @@
public ContextImpl getSystemUiContext() {
synchronized (this) {
if (mSystemUiContext == null) {
- mSystemUiContext = ContextImpl.createSystemUiContext(this);
+ mSystemUiContext = ContextImpl.createSystemUiContext(getSystemContext());
}
return mSystemUiContext;
}
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index 9928512..7d81c4c 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -48,7 +48,7 @@
* and add your view to it:
*
* <pre>
- * FrameLayout fl = (FrameLayout) findViewById(android.R.id.custom);
+ * FrameLayout fl = findViewById(android.R.id.custom);
* fl.addView(myView, new LayoutParams(MATCH_PARENT, WRAP_CONTENT));
* </pre>
*
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 75f9d67..6cc8a14 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2220,11 +2220,12 @@
/**
* System Context to be used for UI. This Context has resources that can be themed.
+ * Make sure that the created system UI context shares the same LoadedApk as the system context.
*/
- static ContextImpl createSystemUiContext(ActivityThread mainThread) {
- LoadedApk packageInfo = new LoadedApk(mainThread);
- ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
- null);
+ static ContextImpl createSystemUiContext(ContextImpl systemContext) {
+ final LoadedApk packageInfo = systemContext.mPackageInfo;
+ ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo, null,
+ null, null, 0, null);
context.setResources(createResources(null, packageInfo, null, Display.DEFAULT_DISPLAY, null,
packageInfo.getCompatibilityInfo()));
return context;
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index a3c123f..c7bcc54 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -34,6 +34,7 @@
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
import android.transition.Transition;
import android.transition.TransitionInflater;
import android.transition.TransitionSet;
@@ -1188,6 +1189,19 @@
}
/**
+ * @hide
+ * Call {@link Activity#startActivityForResultAsUser(Intent, int, UserHandle)} from the
+ * fragment's containing Activity.
+ */
+ public void startActivityForResultAsUser(
+ Intent intent, int requestCode, Bundle options, UserHandle user) {
+ if (mHost == null) {
+ throw new IllegalStateException("Fragment " + this + " not attached to Activity");
+ }
+ mHost.onStartActivityAsUserFromFragment(this, intent, requestCode, options, user);
+ }
+
+ /**
* Call {@link Activity#startIntentSenderForResult(IntentSender, int, Intent, int, int, int,
* Bundle)} from the fragment's containing Activity.
*/
@@ -2513,7 +2527,7 @@
mChildFragmentManager.attachController(mHost, new FragmentContainer() {
@Override
@Nullable
- public View onFindViewById(int id) {
+ public <T extends View> T onFindViewById(int id) {
if (mView == null) {
throw new IllegalStateException("Fragment does not have a view");
}
diff --git a/core/java/android/app/FragmentContainer.java b/core/java/android/app/FragmentContainer.java
index 6ed54dc..77c9c31 100644
--- a/core/java/android/app/FragmentContainer.java
+++ b/core/java/android/app/FragmentContainer.java
@@ -31,7 +31,7 @@
* view is not a child of this container.
*/
@Nullable
- public abstract View onFindViewById(@IdRes int id);
+ public abstract <T extends View> T onFindViewById(@IdRes int id);
/**
* Return {@code true} if the container holds any view.
diff --git a/core/java/android/app/FragmentHostCallback.java b/core/java/android/app/FragmentHostCallback.java
index 41a885e..5ef23e6 100644
--- a/core/java/android/app/FragmentHostCallback.java
+++ b/core/java/android/app/FragmentHostCallback.java
@@ -23,6 +23,7 @@
import android.content.IntentSender;
import android.os.Bundle;
import android.os.Handler;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.view.LayoutInflater;
import android.view.View;
@@ -146,6 +147,20 @@
}
/**
+ * @hide
+ * Starts a new {@link Activity} from the given fragment.
+ * See {@link Activity#startActivityForResult(Intent, int)}.
+ */
+ public void onStartActivityAsUserFromFragment(Fragment fragment, Intent intent, int requestCode,
+ Bundle options, UserHandle userHandle) {
+ if (requestCode != -1) {
+ throw new IllegalStateException(
+ "Starting activity with a requestCode requires a FragmentActivity host");
+ }
+ mContext.startActivityAsUser(intent, userHandle);
+ }
+
+ /**
* Starts a new {@link IntentSender} from the given fragment.
* See {@link Activity#startIntentSender(IntentSender, Intent, int, int, int, Bundle)}.
*/
@@ -192,7 +207,7 @@
@Nullable
@Override
- public View onFindViewById(int id) {
+ public <T extends View> T onFindViewById(int id) {
return null;
}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 75d6295..91578a2 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1243,7 +1243,7 @@
+ f
+ " for a container view with no id"));
}
- container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
+ container = mContainer.onFindViewById(f.mContainerId);
if (container == null && !f.mRestored) {
String resName;
try {
diff --git a/core/java/android/app/FragmentTransition.java b/core/java/android/app/FragmentTransition.java
index 780a922..9a920d7 100644
--- a/core/java/android/app/FragmentTransition.java
+++ b/core/java/android/app/FragmentTransition.java
@@ -193,7 +193,7 @@
View nonExistentView, ArrayMap<String, String> nameOverrides) {
ViewGroup sceneRoot = null;
if (fragmentManager.mContainer.onHasView()) {
- sceneRoot = (ViewGroup) fragmentManager.mContainer.onFindViewById(containerId);
+ sceneRoot = fragmentManager.mContainer.onFindViewById(containerId);
}
if (sceneRoot == null) {
return;
@@ -265,7 +265,7 @@
View nonExistentView, ArrayMap<String, String> nameOverrides) {
ViewGroup sceneRoot = null;
if (fragmentManager.mContainer.onHasView()) {
- sceneRoot = (ViewGroup) fragmentManager.mContainer.onFindViewById(containerId);
+ sceneRoot = fragmentManager.mContainer.onFindViewById(containerId);
}
if (sceneRoot == null) {
return;
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 079bbcd..fc827a9 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -190,6 +190,8 @@
int flags, in Bundle options, int userId);
void cancelIntentSender(in IIntentSender sender);
String getPackageForIntentSender(in IIntentSender sender);
+ void registerIntentSenderCancelListener(in IIntentSender sender, in IResultReceiver receiver);
+ void unregisterIntentSenderCancelListener(in IIntentSender sender, in IResultReceiver receiver);
void enterSafeMode();
boolean startNextMatchingActivity(in IBinder callingActivity,
in Intent intent, in Bundle options);
@@ -463,6 +465,7 @@
* etc.
*/
void keyguardGoingAway(int flags);
+ int getUidProcessState(int uid, in String callingPackage);
void registerUidObserver(in IUidObserver observer, int which, int cutpoint,
String callingPackage);
void unregisterUidObserver(in IUidObserver observer);
@@ -576,17 +579,6 @@
* @param hasTopUi Whether the calling process has "top-level" UI.
*/
void setHasTopUi(boolean hasTopUi);
- /**
- * Returns if the target of the PendingIntent can be fired directly, without triggering
- * a work profile challenge. This can happen if the PendingIntent is to start direct-boot
- * aware activities, and the target user is in RUNNING_LOCKED state, i.e. we should allow
- * direct-boot aware activity to bypass work challenge when the user hasn't unlocked yet.
- * @param intent the {@link PendingIntent} to be tested.
- * @return {@code true} if the intent should not trigger a work challenge, {@code false}
- * otherwise.
- * @throws RemoteException
- */
- boolean canBypassWorkChallenge(in PendingIntent intent);
// Start of O transactions
void requestActivityRelaunch(in IBinder token);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 61dacef..f4e8f3f 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -101,6 +101,10 @@
void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim);
void setInterruptionFilter(String pkg, int interruptionFilter);
+ void updateNotificationChannelFromPrivilegedListener(in INotificationListener token, String pkg, in NotificationChannel channel);
+ ParceledListSlice getNotificationChannelsFromPrivilegedListener(in INotificationListener token, String pkg);
+ ParceledListSlice getNotificationChannelGroupsFromPrivilegedListener(in INotificationListener token, String pkg);
+
void applyEnqueuedAdjustmentFromAssistant(in INotificationListener token, in Adjustment adjustment);
void applyAdjustmentFromAssistant(in INotificationListener token, in Adjustment adjustment);
void applyAdjustmentsFromAssistant(in INotificationListener token, in List<Adjustment> adjustments);
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index d546f27..9377d35 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1779,7 +1779,7 @@
* {@hide}
*/
public ActivityResult execStartActivity(
- Context who, IBinder contextThread, IBinder token, Activity target,
+ Context who, IBinder contextThread, IBinder token, String resultWho,
Intent intent, int requestCode, Bundle options, UserHandle user) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
@@ -1810,7 +1810,7 @@
int result = ActivityManager.getService()
.startActivityAsUser(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
- token, target != null ? target.mEmbeddedID : null,
+ token, resultWho,
requestCode, 0, null, options, user.getIdentifier());
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
diff --git a/core/java/android/app/JobSchedulerImpl.java b/core/java/android/app/JobSchedulerImpl.java
index e30b96f..4ac44f7 100644
--- a/core/java/android/app/JobSchedulerImpl.java
+++ b/core/java/android/app/JobSchedulerImpl.java
@@ -20,6 +20,8 @@
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.app.job.IJobScheduler;
+import android.app.job.JobWorkItem;
+import android.content.Intent;
import android.os.RemoteException;
import java.util.List;
@@ -46,6 +48,15 @@
}
@Override
+ public int enqueue(JobInfo job, JobWorkItem work) {
+ try {
+ return mBinder.enqueue(job, work);
+ } catch (RemoteException e) {
+ return JobScheduler.RESULT_FAILURE;
+ }
+ }
+
+ @Override
public int scheduleAsPackage(JobInfo job, String packageName, int userId, String tag) {
try {
return mBinder.scheduleAsPackage(job, packageName, userId, tag);
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 92216d1..e50bc13 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -26,6 +26,7 @@
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
+import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.text.TextUtils;
@@ -139,7 +140,7 @@
private int mImportance = DEFAULT_IMPORTANCE;
private boolean mBypassDnd;
private int mLockscreenVisibility = DEFAULT_VISIBILITY;
- private Uri mSound;
+ private Uri mSound = Settings.System.DEFAULT_NOTIFICATION_URI;
private boolean mLights;
private int mLightColor = DEFAULT_LIGHT_COLOR;
private long[] mVibration;
@@ -330,7 +331,8 @@
/**
* Sets the sound that should be played for notifications posted to this channel and its
- * audio attributes.
+ * audio attributes. Notification channels with an {@link #getImportance() importance} of at
+ * least {@link NotificationManager#IMPORTANCE_DEFAULT} should have a sound.
*
* Only modifiable before the channel is submitted to
* {@link NotificationManager#notify(String, int, Notification)}.
@@ -445,7 +447,7 @@
}
/**
- * Returns the user specified importance {e.g. @link NotificationManager#IMPORTANCE_LOW} for
+ * Returns the user specified importance e.g. {@link NotificationManager#IMPORTANCE_LOW} for
* notifications posted to this channel.
*/
public int getImportance() {
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 9c18df8..4abca9a 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -165,7 +165,7 @@
setContentView(com.android.internal.R.layout.search_bar);
// get the view elements for local access
- mSearchView = (SearchView) findViewById(com.android.internal.R.id.search_view);
+ mSearchView = findViewById(com.android.internal.R.id.search_view);
mSearchView.setIconified(false);
mSearchView.setOnCloseListener(mOnCloseListener);
mSearchView.setOnQueryTextListener(mOnQueryChangeListener);
@@ -184,7 +184,7 @@
mBadgeLabel = (TextView) mSearchView.findViewById(com.android.internal.R.id.search_badge);
mSearchAutoComplete = (AutoCompleteTextView)
mSearchView.findViewById(com.android.internal.R.id.search_src_text);
- mAppIcon = (ImageView) findViewById(com.android.internal.R.id.search_app_icon);
+ mAppIcon = findViewById(com.android.internal.R.id.search_app_icon);
mSearchPlate = mSearchView.findViewById(com.android.internal.R.id.search_plate);
mWorkingSpinner = getContext().getDrawable(com.android.internal.R.drawable.search_spinner);
// TODO: Restore the spinner for slow suggestion lookups
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 4572578..40fe6af 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -120,6 +120,8 @@
import android.print.PrintManager;
import android.view.autofill.AutofillManager;
import android.view.autofill.IAutoFillManager;
+import android.service.oemlock.IOemLockService;
+import android.service.oemlock.OemLockManager;
import android.service.persistentdata.IPersistentDataBlockService;
import android.service.persistentdata.PersistentDataBlockManager;
import android.service.vr.IVrManager;
@@ -641,7 +643,8 @@
new CachedServiceFetcher<PrintManager>() {
@Override
public PrintManager createService(ContextImpl ctx) throws ServiceNotFoundException {
- IBinder iBinder = ServiceManager.getServiceOrThrow(Context.PRINT_SERVICE);
+ // Get the services without throwing as this is an optional feature
+ IBinder iBinder = ServiceManager.getService(Context.PRINT_SERVICE);
IPrintManager service = IPrintManager.Stub.asInterface(iBinder);
return new PrintManager(ctx.getOuterContext(), service, UserHandle.myUserId(),
UserHandle.getAppId(Process.myUid()));
@@ -652,8 +655,9 @@
@Override
public CompanionDeviceManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
+ // Get the services without throwing as this is an optional feature
IBinder iBinder =
- ServiceManager.getServiceOrThrow(Context.COMPANION_DEVICE_SERVICE);
+ ServiceManager.getService(Context.COMPANION_DEVICE_SERVICE);
ICompanionDeviceManager service =
ICompanionDeviceManager.Stub.asInterface(iBinder);
return new CompanionDeviceManager(service, ctx);
@@ -750,6 +754,20 @@
}
}});
+ registerService(Context.OEM_LOCK_SERVICE, OemLockManager.class,
+ new StaticServiceFetcher<OemLockManager>() {
+ @Override
+ public OemLockManager createService() throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.OEM_LOCK_SERVICE);
+ IOemLockService oemLockService = IOemLockService.Stub.asInterface(b);
+ if (oemLockService != null) {
+ return new OemLockManager(oemLockService);
+ } else {
+ // not supported
+ return null;
+ }
+ }});
+
registerService(Context.MEDIA_PROJECTION_SERVICE, MediaProjectionManager.class,
new CachedServiceFetcher<MediaProjectionManager>() {
@Override
@@ -833,7 +851,8 @@
new CachedServiceFetcher<AutofillManager>() {
@Override
public AutofillManager createService(ContextImpl ctx) throws ServiceNotFoundException {
- IBinder b = ServiceManager.getServiceOrThrow(Context.AUTOFILL_MANAGER_SERVICE);
+ // Get the services without throwing as this is an optional feature
+ IBinder b = ServiceManager.getService(Context.AUTOFILL_MANAGER_SERVICE);
IAutoFillManager service = IAutoFillManager.Stub.asInterface(b);
return new AutofillManager(ctx.getOuterContext(), service);
}});
diff --git a/core/java/android/app/TabActivity.java b/core/java/android/app/TabActivity.java
index 637c8c1..ad8b0db 100644
--- a/core/java/android/app/TabActivity.java
+++ b/core/java/android/app/TabActivity.java
@@ -108,7 +108,7 @@
@Override
public void onContentChanged() {
super.onContentChanged();
- mTabHost = (TabHost) findViewById(com.android.internal.R.id.tabhost);
+ mTabHost = findViewById(com.android.internal.R.id.tabhost);
if (mTabHost == null) {
throw new RuntimeException(
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index 790a952..2b590e0 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -27,6 +27,16 @@
import java.lang.annotation.RetentionPolicy;
import java.util.Collection;
+/**
+ * Definitions for working with security logs.
+ *
+ * <p>Device owner apps can control the logging with
+ * {@link DevicePolicyManager#setSecurityLoggingEnabled}. When security logs are enabled, device
+ * owner apps receive periodic callbacks from {@link DeviceAdminReceiver#onSecurityLogsAvailable},
+ * at which time new batch of logs can be collected via
+ * {@link DevicePolicyManager#retrieveSecurityLogs}. {@link SecurityEvent} describes the type and
+ * format of security logs being collected.
+ */
public class SecurityLog {
private static final String PROPERTY_LOGGING_ENABLED = "persist.logd.security";
diff --git a/core/java/android/app/job/IJobCallback.aidl b/core/java/android/app/job/IJobCallback.aidl
index 2d3948f..e7695e2 100644
--- a/core/java/android/app/job/IJobCallback.aidl
+++ b/core/java/android/app/job/IJobCallback.aidl
@@ -16,6 +16,8 @@
package android.app.job;
+import android.app.job.JobWorkItem;
+
/**
* The server side of the JobScheduler IPC protocols. The app-side implementation
* invokes on this interface to indicate completion of the (asynchronous) instructions
@@ -43,6 +45,14 @@
*/
void acknowledgeStopMessage(int jobId, boolean reschedule);
/*
+ * Called to deqeue next work item for the job.
+ */
+ JobWorkItem dequeueWork(int jobId);
+ /*
+ * Called to report that job has completed processing a work item.
+ */
+ boolean completeWork(int jobId, int workId);
+ /*
* Tell the job manager that the client is done with its execution, so that it can go on to
* the next one and stop attributing wakelock time to us etc.
*
diff --git a/core/java/android/app/job/IJobScheduler.aidl b/core/java/android/app/job/IJobScheduler.aidl
index b6eec27..e94da0c 100644
--- a/core/java/android/app/job/IJobScheduler.aidl
+++ b/core/java/android/app/job/IJobScheduler.aidl
@@ -17,6 +17,7 @@
package android.app.job;
import android.app.job.JobInfo;
+import android.app.job.JobWorkItem;
/**
* IPC interface that supports the app-facing {@link #JobScheduler} api.
@@ -24,6 +25,7 @@
*/
interface IJobScheduler {
int schedule(in JobInfo job);
+ int enqueue(in JobInfo job, in JobWorkItem work);
int scheduleAsPackage(in JobInfo job, String packageName, int userId, String tag);
void cancel(int jobId);
void cancelAll();
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 8220ff9..23baa17 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -23,6 +23,7 @@
import android.content.ClipData;
import android.content.ComponentName;
import android.net.Uri;
+import android.os.BaseBundle;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -50,6 +51,8 @@
public static final int NETWORK_TYPE_UNMETERED = 2;
/** This job requires network connectivity that is not roaming. */
public static final int NETWORK_TYPE_NOT_ROAMING = 3;
+ /** This job requires metered connectivity such as most cellular data networks. */
+ public static final int NETWORK_TYPE_METERED = 4;
/**
* Amount of backoff a job has initially by default, in milliseconds.
@@ -346,10 +349,13 @@
}
/**
- * One of {@link android.app.job.JobInfo#NETWORK_TYPE_ANY},
+ * The kind of connectivity requirements that the job has.
+ *
+ * @return One of {@link android.app.job.JobInfo#NETWORK_TYPE_ANY},
* {@link android.app.job.JobInfo#NETWORK_TYPE_NONE},
- * {@link android.app.job.JobInfo#NETWORK_TYPE_UNMETERED}, or
- * {@link android.app.job.JobInfo#NETWORK_TYPE_NOT_ROAMING}.
+ * {@link android.app.job.JobInfo#NETWORK_TYPE_UNMETERED},
+ * {@link android.app.job.JobInfo#NETWORK_TYPE_METERED}, or
+ * {@link android.app.job.JobInfo#NETWORK_TYPE_NOT_ROAMING},
*/
public int getNetworkType() {
return networkType;
@@ -442,6 +448,130 @@
return hasLateConstraint;
}
+ private static boolean kindofEqualsBundle(BaseBundle a, BaseBundle b) {
+ return (a == b) || (a != null && a.kindofEquals(b));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof JobInfo)) {
+ return false;
+ }
+ JobInfo j = (JobInfo) o;
+ if (jobId != j.jobId) {
+ return false;
+ }
+ // XXX won't be correct if one is parcelled and the other not.
+ if (!kindofEqualsBundle(extras, j.extras)) {
+ return false;
+ }
+ // XXX won't be correct if one is parcelled and the other not.
+ if (!kindofEqualsBundle(transientExtras, j.transientExtras)) {
+ return false;
+ }
+ // XXX for now we consider two different clip data objects to be different,
+ // regardless of whether their contents are the same.
+ if (clipData != j.clipData) {
+ return false;
+ }
+ if (clipGrantFlags != j.clipGrantFlags) {
+ return false;
+ }
+ if (!Objects.equals(service, j.service)) {
+ return false;
+ }
+ if (constraintFlags != j.constraintFlags) {
+ return false;
+ }
+ if (!Objects.deepEquals(triggerContentUris, j.triggerContentUris)) {
+ return false;
+ }
+ if (triggerContentUpdateDelay != j.triggerContentUpdateDelay) {
+ return false;
+ }
+ if (triggerContentMaxDelay != j.triggerContentMaxDelay) {
+ return false;
+ }
+ if (hasEarlyConstraint != j.hasEarlyConstraint) {
+ return false;
+ }
+ if (hasLateConstraint != j.hasLateConstraint) {
+ return false;
+ }
+ if (networkType != j.networkType) {
+ return false;
+ }
+ if (minLatencyMillis != j.minLatencyMillis) {
+ return false;
+ }
+ if (maxExecutionDelayMillis != j.maxExecutionDelayMillis) {
+ return false;
+ }
+ if (isPeriodic != j.isPeriodic) {
+ return false;
+ }
+ if (isPersisted != j.isPersisted) {
+ return false;
+ }
+ if (intervalMillis != j.intervalMillis) {
+ return false;
+ }
+ if (flexMillis != j.flexMillis) {
+ return false;
+ }
+ if (initialBackoffMillis != j.initialBackoffMillis) {
+ return false;
+ }
+ if (backoffPolicy != j.backoffPolicy) {
+ return false;
+ }
+ if (priority != j.priority) {
+ return false;
+ }
+ if (flags != j.flags) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hashCode = jobId;
+ if (extras != null) {
+ hashCode = 31*hashCode + extras.hashCode();
+ }
+ if (transientExtras != null) {
+ hashCode = 31*hashCode + transientExtras.hashCode();
+ }
+ if (clipData != null) {
+ hashCode = 31*hashCode + clipData.hashCode();
+ }
+ hashCode = 31*hashCode + clipGrantFlags;
+ if (service != null) {
+ hashCode = 31*hashCode + service.hashCode();
+ }
+ hashCode = 31*hashCode + constraintFlags;
+ if (triggerContentUris != null) {
+ hashCode = 31*hashCode + triggerContentUris.hashCode();
+ }
+ hashCode = 31*hashCode + Long.hashCode(triggerContentUpdateDelay);
+ hashCode = 31*hashCode + Long.hashCode(triggerContentMaxDelay);
+ hashCode = 31*hashCode + Boolean.hashCode(hasEarlyConstraint);
+ hashCode = 31*hashCode + Boolean.hashCode(hasLateConstraint);
+ hashCode = 31*hashCode + networkType;
+ hashCode = 31*hashCode + Long.hashCode(minLatencyMillis);
+ hashCode = 31*hashCode + Long.hashCode(maxExecutionDelayMillis);
+ hashCode = 31*hashCode + Boolean.hashCode(isPeriodic);
+ hashCode = 31*hashCode + Boolean.hashCode(isPersisted);
+ hashCode = 31*hashCode + Long.hashCode(intervalMillis);
+ hashCode = 31*hashCode + Long.hashCode(flexMillis);
+ hashCode = 31*hashCode + Long.hashCode(initialBackoffMillis);
+ hashCode = 31*hashCode + backoffPolicy;
+ hashCode = 31*hashCode + priority;
+ hashCode = 31*hashCode + flags;
+ return hashCode;
+ }
+
private JobInfo(Parcel in) {
jobId = in.readInt();
extras = in.readPersistableBundle();
diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java
index 8d52d3b..016a0fa 100644
--- a/core/java/android/app/job/JobParameters.java
+++ b/core/java/android/app/job/JobParameters.java
@@ -24,6 +24,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
+import android.os.RemoteException;
/**
* Contains the parameters used to configure/identify your job. You do not create this object
@@ -155,6 +156,53 @@
return mTriggeredContentAuthorities;
}
+ /**
+ * Dequeue the next pending {@link JobWorkItem} from these JobParameters associated with their
+ * currently running job. Calling this method when there is no more work available and all
+ * previously dequeued work has been completed will result in the system taking care of
+ * stopping the job for you --
+ * you should not call {@link JobService#jobFinished(JobParameters, boolean)} yourself
+ * (otherwise you risk losing an upcoming JobWorkItem that is being enqueued at the same time).
+ *
+ * @return Returns a new {@link JobWorkItem} if there is one pending, otherwise null.
+ * If null is returned, the system will also stop the job if all work has also been completed.
+ * (This means that for correct operation, you must always call dequeueWork() after you have
+ * completed other work, to check either for more work or allow the system to stop the job.)
+ */
+ public JobWorkItem dequeueWork() {
+ try {
+ return getCallback().dequeueWork(getJobId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Report the completion of executing a {@link JobWorkItem} previously returned by
+ * {@link #dequeueWork()}. This tells the system you are done with the
+ * work associated with that item, so it will not be returned again. Note that if this
+ * is the last work in the queue, completing it here will <em>not</em> finish the overall
+ * job -- for that to happen, you still need to call {@link #dequeueWork()}
+ * again.
+ *
+ * <p>If you are enqueueing work into a job, you must call this method for each piece
+ * of work you process. Do <em>not</em> call
+ * {@link JobService#jobFinished(JobParameters, boolean)}
+ * or else you can lose work in your queue.</p>
+ *
+ * @param work The work you have completed processing, as previously returned by
+ * {@link #dequeueWork()}
+ */
+ public void completeWork(JobWorkItem work) {
+ try {
+ if (!getCallback().completeWork(getJobId(), work.getWorkId())) {
+ throw new IllegalArgumentException("Given work is not active: " + work);
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/** @hide */
public IJobCallback getCallback() {
return IJobCallback.Stub.asInterface(callback);
diff --git a/core/java/android/app/job/JobScheduler.java b/core/java/android/app/job/JobScheduler.java
index 1b640d0..e0afe03 100644
--- a/core/java/android/app/job/JobScheduler.java
+++ b/core/java/android/app/job/JobScheduler.java
@@ -19,6 +19,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.content.ClipData;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.PersistableBundle;
import java.util.List;
@@ -59,6 +63,10 @@
public static final int RESULT_SUCCESS = 1;
/**
+ * Schedule a job to be executed. Will replace any currently scheduled job with the same
+ * ID with the new information in the {@link JobInfo}. If a job with the given ID is currently
+ * running, it will be stopped.
+ *
* @param job The job you wish scheduled. See
* {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs
* you can schedule.
@@ -67,6 +75,42 @@
public abstract int schedule(JobInfo job);
/**
+ * Similar to {@link #schedule}, but allows you to enqueue work for an existing job. If a job
+ * with the same ID is already scheduled, it will be replaced with the new {@link JobInfo}, but
+ * any previously enqueued work will remain and be dispatched the next time it runs. If a job
+ * with the same ID is already running, the new work will be enqueued for it.
+ *
+ * <p>The work you enqueue is later retrieved through
+ * {@link JobParameters#dequeueWork() JobParameters.dequeueWork()}. Be sure to see there
+ * about how to process work; the act of enqueueing work changes how you should handle the
+ * overall lifecycle of an executing job.</p>
+ *
+ * <p>It is strongly encouraged that you use the same {@link JobInfo} for all work you
+ * enqueue. This will allow the system to optimal schedule work along with any pending
+ * and/or currently running work. If the JobInfo changes from the last time the job was
+ * enqueued, the system will need to update the associated JobInfo, which can cause a disruption
+ * in exection. In particular, this can result in any currently running job that is processing
+ * previous work to be stopped and restarted with the new JobInfo.</p>
+ *
+ * <p>It is recommended that you avoid using
+ * {@link JobInfo.Builder#setExtras(PersistableBundle)} or
+ * {@link JobInfo.Builder#setTransientExtras(Bundle)} with a JobInfo you are using to
+ * enqueue work. The system will try to compare these extras with the previous JobInfo,
+ * but there are situations where it may get this wrong and count the JobInfo as changing.
+ * (That said, you should be relatively safe with a simple set of consistent data in these
+ * fields.) You should never use {@link JobInfo.Builder#setClipData(ClipData, int)} with
+ * work you are enqueue, since currently this will always be treated as a different JobInfo,
+ * even if the ClipData contents is exactly the same.</p>
+ *
+ * @param job The job you wish to enqueue work for. See
+ * {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs
+ * you can schedule.
+ * @param work New work to enqueue. This will be available later when the job starts running.
+ * @return An int representing ({@link #RESULT_SUCCESS} or {@link #RESULT_FAILURE}).
+ */
+ public abstract int enqueue(JobInfo job, JobWorkItem work);
+
+ /**
*
* @param job The job to be scheduled.
* @param packageName The package on behalf of which the job is to be scheduled. This will be
diff --git a/core/java/android/service/autofill/IAutoFillServiceConnection.aidl b/core/java/android/app/job/JobWorkItem.aidl
similarity index 77%
rename from core/java/android/service/autofill/IAutoFillServiceConnection.aidl
rename to core/java/android/app/job/JobWorkItem.aidl
index cf73a10..e8fe47d 100644
--- a/core/java/android/service/autofill/IAutoFillServiceConnection.aidl
+++ b/core/java/android/app/job/JobWorkItem.aidl
@@ -14,13 +14,7 @@
* limitations under the License.
*/
-package android.service.autofill;
+package android.app.job;
-/**
- * Interface from an auto fill service to the system.
- *
- * @hide
- */
-interface IAutoFillServiceConnection {
- void disableSelf();
-}
+/** @hide */
+parcelable JobWorkItem;
diff --git a/core/java/android/app/job/JobWorkItem.java b/core/java/android/app/job/JobWorkItem.java
new file mode 100644
index 0000000..4bb057e
--- /dev/null
+++ b/core/java/android/app/job/JobWorkItem.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.job;
+
+import android.content.Intent;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A unit of work that can be enqueued for a job using
+ * {@link JobScheduler#enqueue JobScheduler.enqueue}.
+ */
+final public class JobWorkItem implements Parcelable {
+ final Intent mIntent;
+ int mWorkId;
+
+ /**
+ * Create a new piece of work.
+ * @param intent The general Intent describing this work.
+ */
+ public JobWorkItem(Intent intent) {
+ mIntent = intent;
+ }
+
+ /**
+ * Return the Intent associated with this work.
+ */
+ public Intent getIntent() {
+ return mIntent;
+ }
+
+ /**
+ * @hide
+ */
+ public void setWorkId(int id) {
+ mWorkId = id;
+ }
+
+ /**
+ * @hide
+ */
+ public int getWorkId() {
+ return mWorkId;
+ }
+
+ public String toString() {
+ return "JobWorkItem{id=" + mWorkId + " intent=" + mIntent + "}";
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ if (mIntent != null) {
+ out.writeInt(1);
+ mIntent.writeToParcel(out, 0);
+ } else {
+ out.writeInt(0);
+ }
+ out.writeInt(mWorkId);
+ }
+
+ public static final Parcelable.Creator<JobWorkItem> CREATOR
+ = new Parcelable.Creator<JobWorkItem>() {
+ public JobWorkItem createFromParcel(Parcel in) {
+ return new JobWorkItem(in);
+ }
+
+ public JobWorkItem[] newArray(int size) {
+ return new JobWorkItem[size];
+ }
+ };
+
+ public JobWorkItem(Parcel in) {
+ if (in.readInt() != 0) {
+ mIntent = Intent.CREATOR.createFromParcel(in);
+ } else {
+ mIntent = null;
+ }
+ mWorkId = in.readInt();
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index cb6fa05..e6cebc0 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -593,24 +593,34 @@
public static final int TRANSPORT_LE = 2;
/**
- * 1M initiating PHY.
+ * Bluetooth LE 1M PHY.
*/
public static final int PHY_LE_1M = 1;
/**
- * 2M initiating PHY.
+ * Bluetooth LE 2M PHY.
*/
public static final int PHY_LE_2M = 2;
/**
- * LE Coded initiating PHY.
+ * Bluetooth LE Coded PHY.
*/
- public static final int PHY_LE_CODED = 4;
+ public static final int PHY_LE_CODED = 3;
/**
- * Any LE PHY.
+ * Bluetooth LE 1M PHY mask.
*/
- public static final int PHY_LE_ANY = PHY_LE_1M | PHY_LE_2M | PHY_LE_CODED;
+ public static final int PHY_LE_1M_MASK = 1;
+
+ /**
+ * Bluetooth LE 2M PHY mask.
+ */
+ public static final int PHY_LE_2M_MASK = 2;
+
+ /**
+ * Bluetooth LE Coded PHY mask.
+ */
+ public static final int PHY_LE_CODED_MASK = 4;
/**
* No preferred coding when transmitting on the LE Coded PHY.
@@ -1651,7 +1661,7 @@
*/
public BluetoothGatt connectGatt(Context context, boolean autoConnect,
BluetoothGattCallback callback, int transport) {
- return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO, PHY_LE_1M));
+ return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO, PHY_LE_1M_MASK));
}
/**
@@ -1668,8 +1678,8 @@
* {@link BluetoothDevice#TRANSPORT_AUTO} or
* {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
* @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of
- * {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M},
- * and {@link BluetoothDevice#PHY_LE_CODED}. This option does not take effect if
+ * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
+ * and {@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if
* {@code autoConnect} is set to true.
* @throws IllegalArgumentException if callback is null
*/
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 5d1e8ec..4aaf6bd 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -785,11 +785,11 @@
* if no PHY change happens. It is also triggered when remote device updates the PHY.
*
* @param txPhy preferred transmitter PHY. Bitwise OR of any of
- * {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M}, and
- * {@link BluetoothDevice#PHY_LE_CODED}.
+ * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
+ * and {@link BluetoothDevice#PHY_LE_CODED_MASK}.
* @param rxPhy preferred receiver PHY. Bitwise OR of any of
- * {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M}, and
- * {@link BluetoothDevice#PHY_LE_CODED}.
+ * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
+ * and {@link BluetoothDevice#PHY_LE_CODED_MASK}.
* @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one
* of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED},
* {@link BluetoothDevice#PHY_OPTION_S2} or {@link BluetoothDevice#PHY_OPTION_S8}
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 2df2ed8..eddc278 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -558,11 +558,11 @@
*
* @param device The remote device to send this response to
* @param txPhy preferred transmitter PHY. Bitwise OR of any of
- * {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M}, and
- * {@link BluetoothDevice#PHY_LE_CODED}.
+ * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
+ * and {@link BluetoothDevice#PHY_LE_CODED_MASK}.
* @param rxPhy preferred receiver PHY. Bitwise OR of any of
- * {@link BluetoothDevice#PHY_LE_1M}, {@link BluetoothDevice#PHY_LE_2M}, and
- * {@link BluetoothDevice#PHY_LE_CODED}.
+ * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK},
+ * and {@link BluetoothDevice#PHY_LE_CODED_MASK}.
* @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one
* of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED},
* {@link BluetoothDevice#PHY_OPTION_S2} or {@link BluetoothDevice#PHY_OPTION_S8}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 28421eb..8519dba 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -1011,6 +1011,18 @@
}
/**
+ * check if in-band ringing is supported for this platform.
+ *
+ * @return true if in-band ringing is supported
+ * false if in-band ringing is not supported
+ * @hide
+ */
+ public static boolean isInbandRingingSupported(Context context) {
+ return context.getResources().getBoolean(
+ com.android.internal.R.bool.config_bluetooth_hfp_inband_ringing_support);
+ }
+
+ /**
* Send Headset the BIND response from AG to report change in the status of the
* HF indicators to the headset
*
diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
index f5c1f08..31d8f48 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetParameters.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
@@ -17,6 +17,7 @@
package android.bluetooth.le;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
import android.os.Parcel;
import android.os.Parcelable;
@@ -30,21 +31,6 @@
public final class AdvertisingSetParameters implements Parcelable {
/**
- * 1M advertiser PHY.
- */
- public static final int PHY_LE_1M = 1;
-
- /**
- * 2M advertiser PHY.
- */
- public static final int PHY_LE_2M = 2;
-
- /**
- * LE Coded advertiser PHY.
- */
- public static final int PHY_LE_CODED = 3;
-
- /**
* Advertise on low frequency, around every 1000ms. This is the default and
* preferred advertising mode as it consumes the least power.
*/
@@ -241,21 +227,21 @@
*/
public static final class Builder {
- private boolean connectable = true;
- private boolean scannable = true;
+ private boolean connectable = false;
+ private boolean scannable = false;
private boolean isLegacy = false;
private boolean isAnonymous = false;
private boolean includeTxPower = false;
- private int primaryPhy = PHY_LE_1M;
- private int secondaryPhy = PHY_LE_1M;
+ private int primaryPhy = BluetoothDevice.PHY_LE_1M;
+ private int secondaryPhy = BluetoothDevice.PHY_LE_1M;
private int interval = INTERVAL_LOW;
private int txPowerLevel = TX_POWER_MEDIUM;
/**
* Set whether the advertisement type should be connectable or
* non-connectable.
- * Legacy advertisements can be both connectable and scannable. Other
- * advertisements can be connectable only if not scannable.
+ * Legacy advertisements can be both connectable and scannable. Non-legacy
+ * advertisements can be only scannable or only connectable.
* @param connectable Controls whether the advertisment type will be
* connectable (true) or non-connectable (false).
*/
@@ -265,9 +251,9 @@
}
/**
- * Set whether the advertisement type should be scannable
- * Legacy advertisements can be both connectable and scannable. Other
- * advertisements can be scannable only if not connectable.
+ * Set whether the advertisement type should be scannable.
+ * Legacy advertisements can be both connectable and scannable. Non-legacy
+ * advertisements can be only scannable or only connectable.
* @param scannable Controls whether the advertisment type will be
* scannable (true) or non-scannable (false).
*/
@@ -321,12 +307,13 @@
* Use {@link BluetoothAdapter#isLeCodedPhySupported} to determine if LE Coded PHY is
* supported on this device.
* @param primaryPhy Primary advertising physical channel, can only be
- * {@link AdvertisingSetParameters#PHY_LE_1M} or
- * {@link AdvertisingSetParameters#PHY_LE_CODED}.
+ * {@link BluetoothDevice#PHY_LE_1M} or
+ * {@link BluetoothDevice#PHY_LE_CODED}.
* @throws IllegalArgumentException If the primaryPhy is invalid.
*/
public Builder setPrimaryPhy(int primaryPhy) {
- if (primaryPhy != PHY_LE_1M && primaryPhy != PHY_LE_CODED) {
+ if (primaryPhy != BluetoothDevice.PHY_LE_1M &&
+ primaryPhy != BluetoothDevice.PHY_LE_CODED) {
throw new IllegalArgumentException("bad primaryPhy " + primaryPhy);
}
this.primaryPhy = primaryPhy;
@@ -343,14 +330,15 @@
* supported on this device.
*
* @param secondaryPhy Secondary advertising physical channel, can only be
- * one of {@link AdvertisingSetParameters#PHY_LE_1M},
- * {@link AdvertisingSetParameters#PHY_LE_2M} or
- * {@link AdvertisingSetParameters#PHY_LE_CODED}.
+ * one of {@link BluetoothDevice#PHY_LE_1M},
+ * {@link BluetoothDevice#PHY_LE_2M} or
+ * {@link BluetoothDevice#PHY_LE_CODED}.
* @throws IllegalArgumentException If the secondaryPhy is invalid.
*/
public Builder setSecondaryPhy(int secondaryPhy) {
- if (secondaryPhy != PHY_LE_1M && secondaryPhy !=PHY_LE_2M &&
- secondaryPhy != PHY_LE_CODED) {
+ if (secondaryPhy != BluetoothDevice.PHY_LE_1M &&
+ secondaryPhy != BluetoothDevice.PHY_LE_2M &&
+ secondaryPhy != BluetoothDevice.PHY_LE_CODED) {
throw new IllegalArgumentException("bad secondaryPhy " + secondaryPhy);
}
this.secondaryPhy = secondaryPhy;
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index a9deb75..ea3031b 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -17,6 +17,7 @@
package android.bluetooth.le;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetoothGatt;
@@ -363,12 +364,12 @@
boolean support2MPhy = mBluetoothAdapter.isLe2MPhySupported();
int pphy = parameters.getPrimaryPhy();
int sphy = parameters.getSecondaryPhy();
- if (pphy == AdvertisingSetParameters.PHY_LE_CODED && !supportCodedPhy) {
+ if (pphy == BluetoothDevice.PHY_LE_CODED && !supportCodedPhy) {
throw new IllegalArgumentException("Unsupported primary PHY selected");
}
- if ((sphy == AdvertisingSetParameters.PHY_LE_CODED && !supportCodedPhy)
- || (sphy == AdvertisingSetParameters.PHY_LE_2M && !support2MPhy)) {
+ if ((sphy == BluetoothDevice.PHY_LE_CODED && !supportCodedPhy)
+ || (sphy == BluetoothDevice.PHY_LE_2M && !support2MPhy)) {
throw new IllegalArgumentException("Unsupported secondary PHY selected");
}
@@ -386,7 +387,7 @@
}
boolean supportPeriodic = mBluetoothAdapter.isLePeriodicAdvertisingSupported();
- if (periodicParameters != null && periodicParameters.getEnable() && !supportPeriodic) {
+ if (periodicParameters != null && !supportPeriodic) {
throw new IllegalArgumentException(
"Controller does not support LE Periodic Advertising");
}
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
index 149540c..8891d2e 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java
@@ -29,28 +29,20 @@
private static final int INTERVAL_MAX = 80;
private static final int INTERVAL_MIN = 65519;
- private final boolean enable;
private final boolean includeTxPower;
private final int interval;
- private PeriodicAdvertisingParameters(boolean enable, boolean includeTxPower, int interval) {
- this.enable = enable;
+ private PeriodicAdvertisingParameters(boolean includeTxPower, int interval) {
this.includeTxPower = includeTxPower;
this.interval = interval;
}
private PeriodicAdvertisingParameters(Parcel in) {
- enable = in.readInt() != 0 ? true : false;
includeTxPower = in.readInt() != 0 ? true : false;
interval = in.readInt();
}
/**
- * Returns whether the periodic advertising shall be enabled.
- */
- public boolean getEnable() { return enable; }
-
- /**
* Returns whether the TX Power will be included.
*/
public boolean getIncludeTxPower() { return includeTxPower; }
@@ -68,7 +60,6 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(enable ? 1 : 0);
dest.writeInt(includeTxPower ? 1 : 0);
dest.writeInt(interval);
}
@@ -89,18 +80,9 @@
public static final class Builder {
private boolean includeTxPower = false;
- private boolean enable = false;
private int interval = INTERVAL_MAX;
/**
- * Set whether the Periodic Advertising should be enabled for this set.
- */
- public Builder setEnable(boolean enable) {
- this.enable = enable;
- return this;
- }
-
- /**
* Whether the transmission power level should be included in the periodic
* packet.
*/
@@ -128,7 +110,7 @@
* Build the {@link AdvertisingSetParameters} object.
*/
public PeriodicAdvertisingParameters build() {
- return new PeriodicAdvertisingParameters(enable, includeTxPower, interval);
+ return new PeriodicAdvertisingParameters(includeTxPower, interval);
}
}
}
diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java
index 745cd16..5b2fa40 100644
--- a/core/java/android/bluetooth/le/ScanResult.java
+++ b/core/java/android/bluetooth/le/ScanResult.java
@@ -47,21 +47,6 @@
public static final int PHY_UNUSED = 0x00;
/**
- * Bluetooth LE 1Mbit advertiser PHY.
- */
- public static final int PHY_LE_1M = 0x01;
-
- /**
- * Bluetooth LE 2Mbit advertiser PHY.
- */
- public static final int PHY_LE_2M = 0x02;
-
- /**
- * Bluetooth LE Coded advertiser PHY.
- */
- public static final int PHY_LE_CODED = 0x03;
-
- /**
* Advertising Set ID is not present in the packet.
*/
public static final int SID_NOT_PRESENT = 0xFF;
@@ -112,7 +97,7 @@
mRssi = rssi;
mTimestampNanos = timestampNanos;
mEventType = (DATA_COMPLETE << 5) | ET_LEGACY_MASK | ET_CONNECTABLE_MASK;
- mPrimaryPhy = PHY_LE_1M;
+ mPrimaryPhy = BluetoothDevice.PHY_LE_1M;
mSecondaryPhy = PHY_UNUSED;
mAdvertisingSid = SID_NOT_PRESENT;
mTxPower = 127;
@@ -256,16 +241,16 @@
/**
* Returns the primary Physical Layer
* on which this advertisment was received.
- * Can be one of {@link ScanResult#PHY_LE_1M} or
- * {@link ScanResult#PHY_LE_CODED}.
+ * Can be one of {@link BluetoothDevice#PHY_LE_1M} or
+ * {@link BluetoothDevice#PHY_LE_CODED}.
*/
public int getPrimaryPhy() { return mPrimaryPhy; }
/**
* Returns the secondary Physical Layer
* on which this advertisment was received.
- * Can be one of {@link ScanResult#PHY_LE_1M},
- * {@link ScanResult#PHY_LE_2M}, {@link ScanResult#PHY_LE_CODED}
+ * Can be one of {@link BluetoothDevice#PHY_LE_1M},
+ * {@link BluetoothDevice#PHY_LE_2M}, {@link BluetoothDevice#PHY_LE_CODED}
* or {@link ScanResult#PHY_UNUSED} - if the advertisement
* was not received on a secondary physical channel.
*/
diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java
index 69c9a8c..36e48e9 100644
--- a/core/java/android/bluetooth/le/ScanSettings.java
+++ b/core/java/android/bluetooth/le/ScanSettings.java
@@ -17,6 +17,7 @@
package android.bluetooth.le;
import android.annotation.SystemApi;
+import android.bluetooth.BluetoothDevice;
import android.os.Parcel;
import android.os.Parcelable;
@@ -123,16 +124,6 @@
public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1;
/**
- * Use the Bluetooth LE 1Mbit PHY for scanning.
- */
- public static final int PHY_LE_1M = 1;
-
- /**
- * Use Bluetooth LE Coded PHY for scanning.
- */
- public static final int PHY_LE_CODED = 3;
-
- /**
* Use all supported PHYs for scanning.
* This will check the controller capabilities, and start
* the scan on 1Mbit and LE Coded PHYs if supported, or on
@@ -412,8 +403,8 @@
* Selecting an unsupported phy will result in failure to start scan.
*
* @param phy Can be one of
- * {@link ScanSettings#PHY_LE_1M},
- * {@link ScanSettings#PHY_LE_CODED} or
+ * {@link BluetoothDevice#PHY_LE_1M},
+ * {@link BluetoothDevice#PHY_LE_CODED} or
* {@link ScanSettings#PHY_LE_ALL_SUPPORTED}
*/
public Builder setPhy(int phy) {
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index 2f87633..d428a3a 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -24,7 +24,6 @@
import android.database.CursorToBulkCursorAdaptor;
import android.database.DatabaseUtils;
import android.database.IContentObserver;
-import android.database.PageViewCursor;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -104,7 +103,6 @@
if (cursor != null) {
CursorToBulkCursorAdaptor adaptor = null;
- cursor = PageViewCursor.wrap(cursor, queryArgs);
try {
adaptor = new CursorToBulkCursorAdaptor(cursor, observer,
getProviderName());
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 88bade1..18120c7 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2745,7 +2745,8 @@
* {@link #BIND_WAIVE_PRIORITY}.
* @return If you have successfully bound to the service, {@code true} is returned;
* {@code false} is returned if the connection is not made so you will not
- * receive the service object.
+ * receive the service object. However, you should still call
+ * {@link #unbindService} to release the connection.
*
* @throws SecurityException If the caller does not have permission to access the service
* or the service can not be found.
@@ -2896,6 +2897,7 @@
BATTERY_SERVICE,
JOB_SCHEDULER_SERVICE,
//@hide: PERSISTENT_DATA_BLOCK_SERVICE,
+ //@hide: OEM_LOCK_SERVICE,
MEDIA_PROJECTION_SERVICE,
MIDI_SERVICE,
RADIO_SERVICE,
@@ -3818,6 +3820,17 @@
/**
* Use with {@link #getSystemService} to retrieve a {@link
+ * android.service.oemlock.OemLockManager} instance for managing the OEM lock.
+ *
+ * @see #getSystemService
+ * @see android.service.oemlock.OemLockManager
+ * @hide
+ */
+ @SystemApi
+ public static final String OEM_LOCK_SERVICE = "oem_lock";
+
+ /**
+ * Use with {@link #getSystemService} to retrieve a {@link
* android.media.projection.MediaProjectionManager} instance for managing
* media projection sessions.
* @see #getSystemService
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 5415eb5..0da4f8d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -657,6 +657,16 @@
public static final String ACTION_VIEW = "android.intent.action.VIEW";
/**
+ * Extra that can be included on activity intents coming from the storage UI
+ * when it launches sub-activities to manage various types of storage. For example,
+ * it may use {@link #ACTION_VIEW} with a "image/*" MIME type to have an app show
+ * the images on the device, and in that case also include this extra to tell the
+ * app it is coming from the storage UI so should help the user manage storage of
+ * this type.
+ */
+ public static final String EXTRA_FROM_STORAGE = "android.intent.extra.FROM_STORAGE";
+
+ /**
* A synonym for {@link #ACTION_VIEW}, the "standard" action that is
* performed on a piece of data.
*/
@@ -1437,6 +1447,20 @@
public static final String ACTION_POWER_USAGE_SUMMARY = "android.intent.action.POWER_USAGE_SUMMARY";
/**
+ * Activity Action: Setup wizard action provided for OTA provisioning to determine if it needs
+ * to run.
+ * <p>Input: Nothing.
+ * <p>Output: Nothing.
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#M}, setup wizard can be identified
+ * using {@link #ACTION_MAIN} and {@link #CATEGORY_SETUP_WIZARD}
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ public static final String ACTION_DEVICE_INITIALIZATION_WIZARD =
+ "android.intent.action.DEVICE_INITIALIZATION_WIZARD";
+
+ /**
* Activity Action: Setup wizard to launch after a platform update. This
* activity should have a string meta-data field associated with it,
* {@link #METADATA_SETUP_VERSION}, which defines the current version of
@@ -1447,6 +1471,7 @@
* <p>Output: Nothing.
* @hide
*/
+ @SystemApi
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP";
@@ -2047,13 +2072,13 @@
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
/**
- * Broadcast Action: A new application package has been installed on the
+ * Broadcast Action: An application package has been installed or updated on the
* device. The data contains the name of the package. Note that the
* newly installed package does <em>not</em> receive this broadcast.
* <p>May include the following extras:
* <ul>
- * <li> {@link #EXTRA_UID} containing the integer uid assigned to the new package.
- * <li> {@link #EXTRA_REPLACING} is set to true if this is following
+ * <li> {@link #EXTRA_UID} containing the integer uid assigned to this package.
+ * <li> {@link #EXTRA_REPLACING} is set to {@code true} if this is following
* an {@link #ACTION_PACKAGE_REMOVED} broadcast for the same package.
* </ul>
*
@@ -2063,6 +2088,22 @@
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
/**
+ * Broadcast Action: A new application package has been installed on the
+ * device. The data contains the name of the package. Note that the
+ * newly installed package does <em>not</em> receive this broadcast.
+ * <p class="note">Unlike {@link #ACTION_PACKAGE_ADDED}, this broadcast is delivered
+ * to manifest receivers as well as those registered at runtime.
+ * <p>May include the following extras:
+ * <ul>
+ * <li> {@link #EXTRA_UID} containing the integer uid assigned to the new package.
+ * </ul>
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_PACKAGE_FIRST_ADDED = "android.intent.action.PACKAGE_FIRST_ADDED";
+ /**
* Broadcast Action: A new version of an application package has been
* installed, replacing an existing version that was previously installed.
* The data contains the name of the package.
@@ -3216,13 +3257,6 @@
"android.intent.action.MEDIA_RESOURCE_GRANTED";
/**
- * Broadcast Action: An overlay package has been installed. The data
- * contains the name of the added overlay package.
- * @hide
- */
- public static final String ACTION_OVERLAY_ADDED = "android.intent.action.OVERLAY_ADDED";
-
- /**
* Broadcast Action: An overlay package has changed. The data contains the
* name of the overlay package which has changed. This is broadcast on all
* changes to the OverlayInfo returned by {@link
@@ -3234,22 +3268,6 @@
public static final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
/**
- * Broadcast Action: An overlay package has been removed. The data contains
- * the name of the overlay package which has been removed.
- * @hide
- */
- public static final String ACTION_OVERLAY_REMOVED = "android.intent.action.OVERLAY_REMOVED";
-
- /**
- * Broadcast Action: The order of a package's list of overlay packages has
- * changed. The data contains the package name of the overlay package that
- * had its position in the list adjusted.
- * @hide
- */
- public static final String
- ACTION_OVERLAY_PRIORITY_CHANGED = "android.intent.action.OVERLAY_PRIORITY_CHANGED";
-
- /**
* Activity Action: Allow the user to select and return one or more existing
* documents. When invoked, the system will display the various
* {@link DocumentsProvider} instances installed on the device, letting the
@@ -3405,9 +3423,7 @@
public static final String EXTRA_SUBSCRIPTION_INDEX = "android.intent.extra.SUBSCRIPTION_INDEX";
/**
- * Deprecated - use {@link #ACTION_FACTORY_RESET} instead.
- *
- * {@hide}
+ * Deprecated - use ACTION_FACTORY_RESET instead.
*/
@Deprecated
public static final String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 4d76755..c3bdde5 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -275,10 +275,6 @@
@Deprecated
public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;
- /** @deprecated punted, don't use. */
- @Deprecated
- public static final int FLAG_MATCH_CHOOSER = 1 << 4;
-
/**
* Does not retrieve CHOOSER only shortcuts.
* TODO: Add another flag for MATCH_ALL_PINNED
@@ -375,12 +371,6 @@
return this;
}
- /** @deprecated punted, don't use. */
- @Deprecated
- public ShortcutQuery setIntent(@Nullable Intent intent) {
- return this;
- }
-
/**
* Set query options. At least one of the {@code MATCH} flags should be set. Otherwise,
* no shortcuts will be returned.
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 8ff2f35..7f11985 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -272,6 +272,9 @@
public String overlayTarget;
/** @hide */
+ public int overlayPriority;
+
+ /** @hide */
public boolean isStaticOverlay;
public PackageInfo() {
@@ -327,6 +330,7 @@
dest.writeString(requiredAccountType);
dest.writeString(overlayTarget);
dest.writeInt(isStaticOverlay ? 1 : 0);
+ dest.writeInt(overlayPriority);
}
public static final Parcelable.Creator<PackageInfo> CREATOR
@@ -377,6 +381,7 @@
requiredAccountType = source.readString();
overlayTarget = source.readString();
isStaticOverlay = source.readInt() != 0;
+ overlayPriority = source.readInt();
// The component lists were flattened with the redundant ApplicationInfo
// instances omitted. Distribute the canonical one here as appropriate.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index fa3e4e9..e5c8f0d 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1763,6 +1763,17 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports any
+ * one of the {@link #FEATURE_NFC}, {@link #FEATURE_NFC_HOST_CARD_EMULATION},
+ * or {@link #FEATURE_NFC_HOST_CARD_EMULATION_NFCF} features.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_NFC_ANY = "android.hardware.nfc.any";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports the OpenGL ES
* <a href="http://www.khronos.org/registry/gles/extensions/ANDROID/ANDROID_extension_pack_es31a.txt">
* Android Extension Pack</a>.
@@ -2404,6 +2415,15 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device supports autofill of user credentials, addresses, credit cards, etc
+ * via integration with {@link android.service.autofill.AutofillService autofill
+ * providers}.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_AUTOFILL = "android.software.autofill";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
* The device implements headtracking suitable for a VR device.
*/
@SdkConstant(SdkConstantType.FEATURE)
@@ -6247,7 +6267,7 @@
* @return true if the calling package is trusted by the user to request install packages on
* the device, false otherwise.
* @see {@link android.content.Intent#ACTION_INSTALL_PACKAGE}
- * @see {@link android.provider.Settings#ACTION_MANAGE_EXTERNAL_SOURCES}
+ * @see {@link android.provider.Settings#ACTION_MANAGE_UNKNOWN_APP_SOURCES}
*/
public abstract boolean canRequestPackageInstalls();
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index d44d0dc..430d8b1 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -629,6 +629,7 @@
pi.restrictedAccountType = p.mRestrictedAccountType;
pi.requiredAccountType = p.mRequiredAccountType;
pi.overlayTarget = p.mOverlayTarget;
+ pi.overlayPriority = p.mOverlayPriority;
pi.isStaticOverlay = p.mIsStaticOverlay;
pi.firstInstallTime = firstInstallTime;
pi.lastUpdateTime = lastUpdateTime;
@@ -2104,6 +2105,9 @@
com.android.internal.R.styleable.AndroidManifestResourceOverlay);
pkg.mOverlayTarget = sa.getString(
com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
+ pkg.mOverlayPriority = sa.getInt(
+ com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
+ 0);
pkg.mIsStaticOverlay = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic,
false);
@@ -2114,6 +2118,12 @@
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return null;
}
+ if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
+ outError[0] = "<overlay> priority must be between 0 and 9999";
+ mParseError =
+ PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ return null;
+ }
if (pkg.mIsStaticOverlay) {
// TODO(b/35742444): Need to support selection method based on a package name.
}
@@ -3353,7 +3363,12 @@
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_persistent,
false)) {
- ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
+ // Check if persistence is based on a feature being present
+ final String requiredFeature = sa.getNonResourceString(
+ com.android.internal.R.styleable.AndroidManifestApplication_persistentFeature);
+ if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
+ ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
+ }
}
}
@@ -4258,7 +4273,7 @@
a.intents.add(intent);
}
// adjust activity flags when we implicitly expose it via a browsable filter
- intent.setVisibleToInstantApp(visibleToEphemeral || isWebBrowsableIntent(intent));
+ intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent));
if (intent.isVisibleToInstantApp()) {
a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
}
@@ -4291,7 +4306,7 @@
owner.preferredActivityFilters.add(intent);
}
// adjust activity flags when we implicitly expose it via a browsable filter
- intent.setVisibleToInstantApp(visibleToEphemeral || isWebBrowsableIntent(intent));
+ intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent));
if (intent.isVisibleToInstantApp()) {
a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
}
@@ -4619,7 +4634,7 @@
+ parser.getPositionDescription());
} else {
intent.setVisibleToInstantApp(
- visibleToEphemeral || isWebBrowsableIntent(intent));
+ visibleToEphemeral || isImplicitlyExposedIntent(intent));
a.intents.add(intent);
}
// adjust activity flags when we implicitly expose it via a browsable filter
@@ -4821,7 +4836,7 @@
}
outInfo.intents.add(intent);
// adjust provider flags when we implicitly expose it via a browsable filter
- intent.setVisibleToInstantApp(visibleToEphemeral || isWebBrowsableIntent(intent));
+ intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent));
if (intent.isVisibleToInstantApp()) {
outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL;
}
@@ -5126,7 +5141,7 @@
return null;
}
// adjust activity flags when we implicitly expose it via a browsable filter
- intent.setVisibleToInstantApp(visibleToEphemeral || isWebBrowsableIntent(intent));
+ intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent));
if (intent.isVisibleToInstantApp()) {
s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL;
}
@@ -5167,8 +5182,11 @@
return s;
}
- private boolean isWebBrowsableIntent(IntentInfo intent) {
- return intent.hasCategory(Intent.CATEGORY_BROWSABLE);
+ private boolean isImplicitlyExposedIntent(IntentInfo intent) {
+ return intent.hasCategory(Intent.CATEGORY_BROWSABLE)
+ || intent.hasAction(Intent.ACTION_SEND)
+ || intent.hasAction(Intent.ACTION_SENDTO)
+ || intent.hasAction(Intent.ACTION_SEND_MULTIPLE);
}
private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
@@ -5681,6 +5699,7 @@
public String mRequiredAccountType;
public String mOverlayTarget;
+ public int mOverlayPriority;
public boolean mIsStaticOverlay;
public boolean mTrustedOverlay;
@@ -6163,6 +6182,7 @@
mRestrictedAccountType = dest.readString();
mRequiredAccountType = dest.readString();
mOverlayTarget = dest.readString();
+ mOverlayPriority = dest.readInt();
mIsStaticOverlay = (dest.readInt() == 1);
mTrustedOverlay = (dest.readInt() == 1);
mSigningKeys = (ArraySet<PublicKey>) dest.readArraySet(boot);
@@ -6280,6 +6300,7 @@
dest.writeString(mRestrictedAccountType);
dest.writeString(mRequiredAccountType);
dest.writeString(mOverlayTarget);
+ dest.writeInt(mOverlayPriority);
dest.writeInt(mIsStaticOverlay ? 1 : 0);
dest.writeInt(mTrustedOverlay ? 1 : 0);
dest.writeArraySet(mSigningKeys);
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 3f4a090..2b76ae2 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -1032,20 +1032,6 @@
return this;
}
- /** @deprecated punted, don't use. */
- @Deprecated
- @NonNull
- public Builder setChooserExtras(@NonNull PersistableBundle extras) {
- return this;
- }
-
- /** @deprecated punted, don't use. */
- @Deprecated
- public Builder addChooserIntentFilter(@NonNull IntentFilter filter,
- @NonNull ComponentName name) {
- return this;
- }
-
/**
* Creates a {@link ShortcutInfo} instance.
*/
@@ -1246,27 +1232,6 @@
return mIntentPersistableExtrases;
}
- /** @deprecated punted, don't use. */
- @Deprecated
- @NonNull
- public PersistableBundle getChooserExtras() {
- return new PersistableBundle();
- }
-
- /** @deprecated punted, don't use. */
- @Deprecated
- @NonNull
- public IntentFilter[] getChooserIntentFilters() {
- return new IntentFilter[0];
- }
-
- /** @deprecated punted, don't use. */
- @Deprecated
- @NonNull
- public ComponentName[] getChooserComponentNames() {
- return new ComponentName[0];
- }
-
/**
* "Rank" of a shortcut, which is a non-negative, sequential value that's unique for each
* {@link #getActivity} for each of the two types of shortcuts (static and dynamic).
@@ -1388,12 +1353,6 @@
return hasFlags(FLAG_PINNED);
}
- /** @deprecated punted, don't use. */
- @Deprecated
- public boolean isChooser() {
- return false;
- }
-
/**
* Return whether a shortcut is static; that is, whether a shortcut is
* published from AndroidManifest.xml. If {@code true}, the shortcut is
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index a46db06..faf2381 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -91,7 +91,7 @@
* file. An item with no state spec is considered to match any set of states and is generally
* useful as a final item to be used as a default.
* <p>
- * If an item with no state spec if placed before other items, those items
+ * If an item with no state spec is placed before other items, those items
* will be ignored.
*
* <a name="ItemAttributes"></a>
@@ -521,6 +521,15 @@
}
/**
+ * Return whether the state spec list has at least one item explicitly specifying
+ * {@link android.R.attr#state_focused}.
+ * @hide
+ */
+ public boolean hasFocusStateSpecified() {
+ return StateSet.containsAttribute(mStateSpecs, R.attr.state_focused);
+ }
+
+ /**
* Indicates whether this color state list is opaque, which means that every
* color returned from {@link #getColorForState(int[], int)} has an alpha
* value of 255.
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index c8353c9..88c1627 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -127,7 +127,7 @@
*/
public static final int COLOR_MODE_WIDE_COLOR_GAMUT_YES = 0x2;
- /** Constant for {@link #colorMode}: bits that encode whether the dynamic range of the screen. */
+ /** Constant for {@link #colorMode}: bits that encode the dynamic range of the screen. */
public static final int COLOR_MODE_HDR_MASK = 0xc;
/** Constant for {@link #colorMode}: bits shift to get the screen dynamic range. */
public static final int COLOR_MODE_HDR_SHIFT = 2;
@@ -155,7 +155,7 @@
COLOR_MODE_HDR_UNDEFINED;
/**
- * Bit mask of for color capabilities of the screen. Currently there are two fields:
+ * Bit mask of color capabilities of the screen. Currently there are two fields:
* <p>The {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} bits define the color gamut of
* the screen. They may be one of
* {@link #COLOR_MODE_WIDE_COLOR_GAMUT_NO} or {@link #COLOR_MODE_WIDE_COLOR_GAMUT_YES}.</p>
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 3693bce9..408bee8 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1450,7 +1450,8 @@
* <p>Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done
* with the array.
*
- * @param attrs The desired attributes.
+ * @param attrs The desired attributes. These attribute IDs must be sorted in ascending
+ * order.
*
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*
@@ -1474,7 +1475,8 @@
* with the array.
*
* @param resId The desired style resource.
- * @param attrs The desired attributes in the style.
+ * @param attrs The desired attributes in the style. These attribute IDs must be sorted in
+ * ascending order.
*
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*
@@ -1521,7 +1523,8 @@
* the styles.
*
* @param set The base set of attribute values. May be null.
- * @param attrs The desired attributes to be retrieved.
+ * @param attrs The desired attributes to be retrieved. These attribute IDs must be sorted
+ * in ascending order.
* @param defStyleAttr An attribute in the current theme that contains a
* reference to a style resource that supplies
* defaults values for the TypedArray. Can be
@@ -1552,7 +1555,8 @@
* @param values The base set of attribute values, must be equal in
* length to {@code attrs}. All values must be of type
* {@link TypedValue#TYPE_ATTRIBUTE}.
- * @param attrs The desired attributes to be retrieved.
+ * @param attrs The desired attributes to be retrieved. These attribute IDs must be sorted
+ * in ascending order.
* @return Returns a TypedArray holding an array of the attribute
* values. Be sure to call {@link TypedArray#recycle()}
* when done with it.
@@ -1791,14 +1795,15 @@
* performing styling of them using a theme and/or style resources.
*
* @param set The current attribute values to retrieve.
- * @param attrs The specific attributes to be retrieved.
+ * @param attrs The specific attributes to be retrieved. These attribute IDs must be sorted in
+ * ascending order.
* @return Returns a TypedArray holding an array of the attribute values.
* Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
* when done with it.
*
* @see Theme#obtainStyledAttributes(AttributeSet, int[], int, int)
*/
- public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
+ public TypedArray obtainAttributes(AttributeSet set, @StyleableRes int[] attrs) {
int len = attrs.length;
TypedArray array = TypedArray.obtain(this, len);
diff --git a/core/java/android/database/PageViewCursor.java b/core/java/android/database/PageViewCursor.java
deleted file mode 100644
index 4569a27..0000000
--- a/core/java/android/database/PageViewCursor.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.database;
-
-import static com.android.internal.util.ArrayUtils.contains;
-import static com.android.internal.util.Preconditions.checkArgument;
-
-import android.annotation.Nullable;
-import android.annotation.TestApi;
-import android.content.ContentResolver;
-import android.os.Build;
-import android.os.Bundle;
-import android.util.Log;
-import android.util.MathUtils;
-
-import java.util.Arrays;
-
-/**
- * Cursor wrapper that provides visibility into a subset of a wrapped cursor.
- *
- * The window is specified by offset and limit.
- *
- * @hide
- */
-@TestApi
-public final class PageViewCursor extends CursorWrapper implements CrossProcessCursor {
-
- /** An extra added to results that are auto-paged using the wrapper. */
- public static final String EXTRA_AUTO_PAGED = "android.content.extra.AUTO_PAGED";
-
- private static final String[] EMPTY_ARGS = new String[0];
- private static final String TAG = "PageViewCursor";
- private static final boolean DEBUG = Build.IS_DEBUGGABLE;
- private static final boolean VERBOSE = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.VERBOSE);
-
- private final int mOffset; // aka first index
- private final int mCount;
- private final Bundle mExtras;
-
- private @Nullable CursorWindow mWindow;
- private int mPos = -1;
- private int mWindowFillCount = 0;
-
- /**
- * @see PageViewCursor#wrap(Cursor, Bundle)
- */
- public PageViewCursor(Cursor cursor, Bundle queryArgs) {
- super(cursor);
-
- int offset = queryArgs.getInt(ContentResolver.QUERY_ARG_OFFSET, 0);
- int limit = queryArgs.getInt(ContentResolver.QUERY_ARG_LIMIT, Integer.MAX_VALUE);
-
- checkArgument(offset > -1);
- checkArgument(limit > -1);
-
- int count = mCursor.getCount();
-
- mOffset = offset;
-
- mExtras = new Bundle();
- Bundle extras = cursor.getExtras();
- if (extras != null) {
- mExtras.putAll(extras);
- }
-
- // When we're wrapping another cursor, it should not already be "paged".
- checkArgument(!hasPagedResponseDetails(mExtras));
-
- mExtras.putBoolean(EXTRA_AUTO_PAGED, true);
- mExtras.putInt(ContentResolver.EXTRA_TOTAL_SIZE, count);
-
- // Ensure we retain any extra args supplied in cursor extras, and add
- // offset and/or limit.
- String[] existingArgs = mExtras.getStringArray(ContentResolver.EXTRA_HONORED_ARGS);
- existingArgs = existingArgs != null ? existingArgs : EMPTY_ARGS;
-
- int size = existingArgs.length;
-
- // copy the array with space for the extra query args we'll be adding.
- String[] newArgs = Arrays.copyOf(existingArgs, size + 2);
-
- if (queryArgs.containsKey(ContentResolver.QUERY_ARG_OFFSET)) {
- newArgs[size++] = ContentResolver.QUERY_ARG_OFFSET;
- }
- if (queryArgs.containsKey(ContentResolver.QUERY_ARG_LIMIT)) {
- newArgs[size++] = ContentResolver.QUERY_ARG_LIMIT;
- }
-
- assert(size > existingArgs.length); // must add at least one arg.
-
- // At this point there may be a null element at the end of
- // the array because our pre-sizing didn't match the actualy
- // number of args we added. So we trim.
- if (size == newArgs.length - 1) {
- newArgs = Arrays.copyOf(newArgs, size);
- }
- mExtras.putStringArray(ContentResolver.EXTRA_HONORED_ARGS, newArgs);
-
- mCount = MathUtils.constrain(count - offset, 0, limit);
-
- if (DEBUG) Log.d(TAG, "Wrapped cursor"
- + " offset: " + mOffset
- + ", limit: " + limit
- + ", delegate_size: " + count
- + ", paged_count: " + mCount);
- }
-
- @Override
- public Bundle getExtras() {
- return mExtras;
- }
-
- @Override
- public int getPosition() {
- return mPos;
- }
-
- @Override
- public boolean isBeforeFirst() {
- if (mCount == 0) {
- return true;
- }
- return mPos == -1;
- }
-
- @Override
- public boolean isAfterLast() {
- if (mCount == 0) {
- return true;
- }
- return mPos == mCount;
- }
-
- @Override
- public boolean isFirst() {
- return mPos == 0;
- }
-
- @Override
- public boolean isLast() {
- return mPos == mCount - 1;
- }
-
- @Override
- public boolean moveToFirst() {
- return moveToPosition(0);
- }
-
- @Override
- public boolean moveToLast() {
- return moveToPosition(mCount - 1);
- }
-
- @Override
- public boolean moveToNext() {
- return move(1);
- }
-
- @Override
- public boolean moveToPrevious() {
- return move(-1);
- }
-
- @Override
- public boolean move(int offset) {
- return moveToPosition(mPos + offset);
- }
-
- @Override
- public boolean moveToPosition(int position) {
- if (position >= mCount) {
- if (VERBOSE) Log.v(TAG, "Invalid Positon: " + position + " >= count: " + mCount
- + ". Moving to last record.");
- mPos = mCount;
- super.moveToPosition(mOffset + mPos); // move into "after last" state.
- return false;
- }
-
- // Make sure position isn't before the beginning of the cursor
- if (position < 0) {
- if (VERBOSE) Log.v(TAG, "Ignoring invalid move to position: " + position);
- mPos = -1;
- super.moveToPosition(mPos);
- return false;
- }
-
- if (position == mPos) {
- if (VERBOSE) Log.v(TAG, "Ignoring no-op move to position: " + position);
- return true;
- }
-
- int delegatePosition = position + mOffset;
- if (VERBOSE) Log.v(TAG, "Moving delegate cursor to position: " + delegatePosition);
- if (super.moveToPosition(delegatePosition)) {
- mPos = position;
- return true;
- } else {
- mPos = -1;
- super.moveToPosition(-1);
- return false;
- }
- }
-
- @Override
- public boolean onMove(int oldPosition, int newPosition) {
- throw new UnsupportedOperationException("Not supported.");
- }
-
- @Override
- public int getCount() {
- return mCount;
- }
-
- @Override
- public boolean getWantsAllOnMoveCalls() {
- return false; // we want bulk cursor adapter to lift data into a CursorWindow.
- }
-
- @Override
- public CursorWindow getWindow() {
- assert(mPos == -1 || mPos == 0);
- if (mWindow == null) {
- mWindow = new CursorWindow("PageViewCursorWindow");
- fillWindow(0, mWindow);
- }
-
- return mWindow;
- }
-
- @Override
- public void fillWindow(int position, CursorWindow window) {
- assert(window == mWindow);
-
- if (mWindowFillCount++ > 0) {
- Log.w(TAG, "Re-filling window on paged cursor! Reduce ContentResolver.QUERY_ARG_LIMIT");
- }
-
- DatabaseUtils.cursorFillWindow(this, position, window);
- }
-
- /**
- * Wraps the cursor such that it will honor paging args (if present), AND if the cursor does
- * not report paging size.
- * <p>
- * No-op if cursor already contains paging or is less than specified page size.
- */
- public static Cursor wrap(Cursor cursor, @Nullable Bundle queryArgs) {
-
- boolean hasPagingArgs = queryArgs != null
- && (queryArgs.containsKey(ContentResolver.QUERY_ARG_OFFSET)
- || queryArgs.containsKey(ContentResolver.QUERY_ARG_LIMIT));
-
- if (!hasPagingArgs) {
- if (VERBOSE) Log.v(TAG, "No-wrap: No paging args in request.");
- return cursor;
- }
-
- if (hasPagedResponseDetails(cursor.getExtras())) {
- if (VERBOSE) Log.v(TAG, "No-wrap. Cursor has paging details.");
- return cursor;
- }
-
- // Cursors that want all calls aren't compatible with our way
- // of doing business. TODO: Cover this case in CTS.
- if (cursor.getWantsAllOnMoveCalls()) {
- Log.w(TAG, "Unable to wrap cursor that wants to hear about move calls.");
- return cursor;
- }
-
- return new PageViewCursor(cursor, queryArgs);
- }
-
- /**
- * @return true if the extras contains information indicating the associated cursor is
- * paged.
- */
- private static boolean hasPagedResponseDetails(@Nullable Bundle extras) {
- if (extras == null) {
- return false;
- }
-
- if (extras.containsKey(ContentResolver.EXTRA_TOTAL_SIZE)) {
- return true;
- }
-
- String[] honoredArgs = extras.getStringArray(ContentResolver.EXTRA_HONORED_ARGS);
- if (honoredArgs != null
- && (contains(honoredArgs, ContentResolver.QUERY_ARG_OFFSET)
- || contains(honoredArgs, ContentResolver.QUERY_ARG_LIMIT))) {
- return true;
- }
-
- return false;
- }
-}
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 0218cb5..a895f82 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -836,16 +836,16 @@
}
/**
- * Test if sensor support direct channel backed by a specific type of shared memory.
+ * Test if a sensor supports a specified direct channel type.
*
* @param sharedMemType type of shared memory used by direct channel.
- * @return <code>true</code> if the shared memory type is supported.
- * @see SensorDirectChannel#TYPE_ASHMEM
+ * @return <code>true</code> if the specified shared memory type is supported.
+ * @see SensorDirectChannel#TYPE_MEMORY_FILE
* @see SensorDirectChannel#TYPE_HARDWARE_BUFFER
*/
public boolean isDirectChannelTypeSupported(@SensorDirectChannel.MemoryType int sharedMemType) {
switch (sharedMemType) {
- case SensorDirectChannel.TYPE_ASHMEM:
+ case SensorDirectChannel.TYPE_MEMORY_FILE:
return (mFlags & (1 << DIRECT_CHANNEL_SHIFT)) > 0;
case SensorDirectChannel.TYPE_HARDWARE_BUFFER:
return (mFlags & (1 << DIRECT_CHANNEL_SHIFT + 1)) > 0;
diff --git a/core/java/android/hardware/SensorDirectChannel.java b/core/java/android/hardware/SensorDirectChannel.java
index a65d57d..bd7f9cf 100644
--- a/core/java/android/hardware/SensorDirectChannel.java
+++ b/core/java/android/hardware/SensorDirectChannel.java
@@ -23,26 +23,31 @@
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.nio.channels.Channel;
import java.util.concurrent.atomic.AtomicBoolean;
/**
- * Class representing a sensor direct channel. Use {@link
- * SensorManager#createDirectChannel(android.os.MemoryFile)} to obtain object.
+ * Class representing a sensor direct channel. Use
+ * {@link SensorManager#createDirectChannel(android.os.MemoryFile)} or
+ * {@link SensorManager#createDirectChannel(android.hardware.HardwareBuffer)}
+ * to obtain an object. The channel object can be then configured
+ * (see {@link #configure(Sensor, int)})
+ * to start delivery of sensor events into shared memory buffer.
*/
-public final class SensorDirectChannel implements AutoCloseable {
+public final class SensorDirectChannel implements Channel {
// shared memory types
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true, value = {TYPE_ASHMEM, TYPE_HARDWARE_BUFFER})
+ @IntDef(flag = true, value = {TYPE_MEMORY_FILE, TYPE_HARDWARE_BUFFER})
public @interface MemoryType {};
/**
* Shared memory type ashmem, wrapped in MemoryFile object.
*
* @see SensorManager#createDirectChannel(MemoryFile)
*/
- public static final int TYPE_ASHMEM = 1;
+ public static final int TYPE_MEMORY_FILE = 1;
/**
* Shared memory type wrapped by HardwareBuffer object.
@@ -61,7 +66,7 @@
/**
* Sensor stopped (no event output).
*
- * @see SensorManager#configureDirectChannel(SensorDirectChannel, Sensor, int)
+ * @see #configure(Sensor, int)
*/
public static final int RATE_STOP = 0;
/**
@@ -70,7 +75,7 @@
* The actual rate is expected to be between 55% to 220% of nominal rate, thus between 27.5Hz to
* 110Hz.
*
- * @see SensorManager#configureDirectChannel(SensorDirectChannel, Sensor, int)
+ * @see #configure(Sensor, int)
*/
public static final int RATE_NORMAL = 1; //50Hz
/**
@@ -79,7 +84,7 @@
* The actual rate is expected to be between 55% to 220% of nominal rate, thus between 110Hz to
* 440Hz.
*
- * @see SensorManager#configureDirectChannel(SensorDirectChannel, Sensor, int)
+ * @see #configure(Sensor, int)
*/
public static final int RATE_FAST = 2; // ~200Hz
/**
@@ -88,7 +93,7 @@
* The actual rate is expected to be between 55% to 220% of nominal rate, thus between 440Hz to
* 1760Hz.
*
- * @see SensorManager#configureDirectChannel(SensorDirectChannel, Sensor, int)
+ * @see #configure(Sensor, int)
*/
public static final int RATE_VERY_FAST = 3; // ~800Hz
@@ -98,10 +103,17 @@
*
* @return <code>true</code> if channel is valid.
*/
- public boolean isValid() {
+ @Override
+ public boolean isOpen() {
return !mClosed.get();
}
+ /** @removed */
+ @Deprecated
+ public boolean isValid() {
+ return isOpen();
+ }
+
/**
* Close sensor direct channel.
*
@@ -113,13 +125,61 @@
*/
@Override
public void close() {
- mCloseGuard.close();
if (mClosed.compareAndSet(false, true)) {
+ mCloseGuard.close();
// actual close action
mManager.destroyDirectChannel(this);
}
}
+ /**
+ * Configure sensor rate or stop sensor report.
+ *
+ * To start event report of a sensor, or change rate of existing report, call this function with
+ * rateLevel other than {@link android.hardware.SensorDirectChannel#RATE_STOP}. Sensor events
+ * will be added into a queue formed by the shared memory used in creation of direction channel.
+ * Each element of the queue has size of 104 bytes and represents a sensor event. Data
+ * structure of an element (all fields in little-endian):
+ *
+ * <pre>
+ * offset type name
+ * ------------------------------------------------------------------------
+ * 0x0000 int32_t size (always 104)
+ * 0x0004 int32_t sensor report token
+ * 0x0008 int32_t type (see SensorType)
+ * 0x000C uint32_t atomic counter
+ * 0x0010 int64_t timestamp (see Event)
+ * 0x0018 float[16]/int64_t[8] data (data type depends on sensor type)
+ * 0x0058 int32_t[4] reserved (set to zero)
+ * </pre>
+ *
+ * There are no head or tail pointers. The sequence and frontier of new sensor events is
+ * determined by the atomic counter, which counts from 1 after creation of direct channel and
+ * increments 1 for each new event. Atomic counter will wrap back to 1 after it reaches
+ * UINT32_MAX, skipping value 0 to avoid confusion with uninitialized memory. The writer in
+ * sensor system will wrap around from the start of shared memory region when it reaches the
+ * end. If size of memory region is not a multiple of size of element (104 bytes), the residual
+ * is not used at the end. Function returns a positive sensor report token on success. This
+ * token can be used to differentiate sensor events from multiple sensor of the same type. For
+ * example, if there are two accelerometers in the system A and B, it is guaranteed different
+ * report tokens will be returned when starting sensor A and B.
+ *
+ * To stop a sensor, call this function with rateLevel equal {@link
+ * android.hardware.SensorDirectChannel#RATE_STOP}. If the sensor parameter is left to be null,
+ * this will stop all active sensor report associated with the direct channel specified.
+ * Function return 1 on success or 0 on failure.
+ *
+ * @param sensor A {@link android.hardware.Sensor} object to denote sensor to be operated.
+ * @param rateLevel rate level defined in {@link android.hardware.SensorDirectChannel}.
+ * @return * starting report or changing rate: positive sensor report token on success,
+ * 0 on failure;
+ * * stopping report: 1 on success, 0 on failure.
+ * @throws NullPointerException when channel is null.
+ */
+ public int configure(Sensor sensor, @RateLevel int rateLevel) {
+ return mManager.configureDirectChannelImpl(this, sensor, rateLevel);
+ }
+
/** @hide */
SensorDirectChannel(SensorManager manager, int id, int type, long size) {
mManager = manager;
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 1dc6478..ed56391 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -882,7 +882,12 @@
/**
- * Create a sensor direct channel backed by shared memory wrapped by MemoryFile object.
+ * Create a sensor direct channel backed by shared memory wrapped in MemoryFile object.
+ *
+ * The resulting channel can be used for delivering sensor events to native code, other
+ * processes, GPU/DSP or other co-processors without CPU intervention. This is the recommanded
+ * for high performance sensor applications that use high sensor rates (e.g. greater than 200Hz)
+ * and cares about sensor event latency.
*
* Use the returned {@link android.hardware.SensorDirectChannel} object to configure direct
* report of sensor events. After use, call {@link android.hardware.SensorDirectChannel#close()}
@@ -890,7 +895,7 @@
*
* @param mem A {@link android.os.MemoryFile} shared memory object.
* @return A {@link android.hardware.SensorDirectChannel} object if successful, null otherwise.
- * @throws IllegalArgumentException when mem is null.
+ * @throws NullPointerException when mem is null.
* @see SensorDirectChannel#close()
* @see #configureDirectChannel(SensorDirectChannel, Sensor, int)
*/
@@ -899,7 +904,12 @@
}
/**
- * Create a sensor direct channel backed by shared memory wrapped by HardwareBuffer object.
+ * Create a sensor direct channel backed by shared memory wrapped in HardwareBuffer object.
+ *
+ * The resulting channel can be used for delivering sensor events to native code, other
+ * processes, GPU/DSP or other co-processors without CPU intervention. This is the recommanded
+ * for high performance sensor applications that use high sensor rates (e.g. greater than 200Hz)
+ * and cares about sensor event latency.
*
* Use the returned {@link android.hardware.SensorDirectChannel} object to configure direct
* report of sensor events. After use, call {@link android.hardware.SensorDirectChannel#close()}
@@ -908,7 +918,7 @@
* @param mem A {@link android.hardware.HardwareBuffer} shared memory object.
* @return A {@link android.hardware.SensorDirectChannel} object if successful,
* null otherwise.
- * @throws IllegalArgumentException when mem is null.
+ * @throws NullPointerException when mem is null.
* @see SensorDirectChannel#close()
* @see #configureDirectChannel(SensorDirectChannel, Sensor, int)
*/
@@ -928,50 +938,9 @@
/** @hide */
protected abstract void destroyDirectChannelImpl(SensorDirectChannel channel);
- /**
- * Configure sensor rate or stop sensor report on a direct report channel specified.
- *
- * To start event report of a sensor, or change rate of existing report, call this function with
- * rateLevel other than {@link android.hardware.SensorDirectChannel#RATE_STOP}. Sensor events
- * will be added into a queue formed by the shared memory used in creation of direction channel.
- * Each element of the queue has size of 104 bytes and represents a sensor event. Data
- * structure of an element (all fields in little-endian):
- *
- * offset type name
- *- ---------------------------------------------
- * 0x0000 int32_t size (always 104)
- * 0x0004 int32_t sensor report token
- * 0x0008 int32_t type (see SensorType)
- * 0x000C uint32_t atomic counter
- * 0x0010 int64_t timestamp (see Event)
- * 0x0018 float[16]/int64_t[8] data (data type depends on sensor type)
- * 0x0058 int32_t[4] reserved (set to zero)
- *
- * There is no head or tail pointers. The sequence and frontier of new sensor events is
- * determined by the atomic counter, which counts from 1 after creation of direct channel and
- * increments 1 for each new event. The writer in sensor system will wrap around from to
- * start of shared memory region when it reaches the end. If size of memory region is not
- * a multiple of size of element (104 bytes), the residual is not used at the end.
- * Function returns a positive sensor report token on success. This token can be used for
- * differentiate sensor events from multiple sensor of the same type. For example, if there are
- * two accelerometer in the system A and B, it is guaranteed different report tokens will be
- * returned when starting sensor A and B.
- *
- * To stop a sensor, call this function with rateLevel equal {@link
- * android.hardware.SensorDirectChannel#RATE_STOP}. If the sensor parameter is left to be null,
- * this will stop all active sensor report associated with the direct channel specified.
- * Function return 1 on success or 0 on failure.
- *
- * @param channel A {@link android.hardware.SensorDirectChannel} object representing direct
- * channel to be configured.
- * @param sensor A {@link android.hardware.Sensor} object to denote sensor to be operated.
- * @param rateLevel rate level defined in {@link android.hardware.SensorDirectChannel}.
- * @return starting report or changing rate: positive sensor report token on success, 0 on failure;
- * stopping report: 1 on success, 0 on failure.
- * @throws IllegalArgumentException when SensorDirectChannel is null.
- */
- public int configureDirectChannel(SensorDirectChannel channel, Sensor sensor,
- @SensorDirectChannel.RateLevel int rateLevel) {
+ /** @removed */
+ @Deprecated
+ public int configureDirectChannel(SensorDirectChannel channel, Sensor sensor, int rateLevel) {
return configureDirectChannelImpl(channel, sensor, rateLevel);
}
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 0677179..10c4cb3 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -35,6 +35,7 @@
import com.android.internal.annotations.GuardedBy;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
@@ -500,10 +501,8 @@
/** @hide */
protected int configureDirectChannelImpl(
SensorDirectChannel channel, Sensor sensor, int rate) {
- if (channel == null) throw new IllegalArgumentException("channel cannot be null");
-
- if (!channel.isValid()) {
- throw new IllegalStateException("channel is invalid");
+ if (!channel.isOpen()) {
+ throw new IllegalStateException("channel is closed");
}
if (rate < SensorDirectChannel.RATE_STOP
@@ -532,7 +531,8 @@
/** @hide */
protected SensorDirectChannel createDirectChannelImpl(
MemoryFile memoryFile, HardwareBuffer hardwareBuffer) {
- SensorDirectChannel ch = null;
+ int id;
+ int type;
long size;
if (memoryFile != null) {
int fd;
@@ -549,11 +549,13 @@
}
size = memoryFile.length();
- int id = nativeCreateDirectChannel(
- mNativeInstance, size, SensorDirectChannel.TYPE_ASHMEM, fd, null);
- if (id > 0) {
- ch = new SensorDirectChannel(this, id, SensorDirectChannel.TYPE_ASHMEM, size);
+ id = nativeCreateDirectChannel(
+ mNativeInstance, size, SensorDirectChannel.TYPE_MEMORY_FILE, fd, null);
+ if (id <= 0) {
+ throw new UncheckedIOException(
+ new IOException("create MemoryFile direct channel failed " + id));
}
+ type = SensorDirectChannel.TYPE_MEMORY_FILE;
} else if (hardwareBuffer != null) {
if (hardwareBuffer.getFormat() != HardwareBuffer.BLOB) {
throw new IllegalArgumentException("Format of HardwareBuffer must be BLOB");
@@ -571,18 +573,18 @@
"HardwareBuffer must set usage flag USAGE0_SENSOR_DIRECT_DATA");
}
size = hardwareBuffer.getWidth();
- int id = nativeCreateDirectChannel(
+ id = nativeCreateDirectChannel(
mNativeInstance, size, SensorDirectChannel.TYPE_HARDWARE_BUFFER,
-1, hardwareBuffer);
- if (id > 0) {
- ch = new SensorDirectChannel(
- this, id, SensorDirectChannel.TYPE_HARDWARE_BUFFER, size);
+ if (id <= 0) {
+ throw new UncheckedIOException(
+ new IOException("create HardwareBuffer direct channel failed " + id));
}
+ type = SensorDirectChannel.TYPE_HARDWARE_BUFFER;
} else {
- throw new IllegalArgumentException("Invalid parameter");
+ throw new NullPointerException("shared memory object cannot be null");
}
-
- return ch;
+ return new SensorDirectChannel(this, id, type, size);
}
/** @hide */
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index a529c2f..3267172 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -247,6 +247,7 @@
* </p>
*
* @see #createVirtualDisplay
+ * @hide
*/
public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java
index 425a89d..1e98301 100644
--- a/core/java/android/hardware/usb/UsbDevice.java
+++ b/core/java/android/hardware/usb/UsbDevice.java
@@ -37,7 +37,7 @@
* <div class="special reference">
* <h3>Developer Guides</h3>
* <p>For more information about communicating with USB hardware, read the
- * <a href="{@docRoot}guide/topics/usb/index.html">USB</a> developer guide.</p>
+ * <a href="{@docRoot}guide/topics/connectivity/usb/index.html">USB</a> developer guide.</p>
* </div>
*/
public class UsbDevice implements Parcelable {
diff --git a/core/java/android/inputmethodservice/ExtractEditLayout.java b/core/java/android/inputmethodservice/ExtractEditLayout.java
index 37ca4b4..af69f0f 100644
--- a/core/java/android/inputmethodservice/ExtractEditLayout.java
+++ b/core/java/android/inputmethodservice/ExtractEditLayout.java
@@ -41,6 +41,6 @@
@Override
public void onFinishInflate() {
super.onFinishInflate();
- mExtractActionButton = (Button) findViewById(com.android.internal.R.id.inputExtractAction);
+ mExtractActionButton = findViewById(com.android.internal.R.id.inputExtractAction);
}
}
diff --git a/core/java/android/metrics/MetricsReader.java b/core/java/android/metrics/MetricsReader.java
index d8768e7..5be977a 100644
--- a/core/java/android/metrics/MetricsReader.java
+++ b/core/java/android/metrics/MetricsReader.java
@@ -27,6 +27,7 @@
import java.util.Collection;
import java.util.LinkedList;
import java.util.Queue;
+import java.util.concurrent.TimeUnit;
/**
* Read platform logs.
@@ -80,7 +81,7 @@
mPendingQueue.clear();
mSeenQueue.clear();
for (Event event : nativeEvents) {
- final long eventTimestampMs = event.getTimeNanos() / 1000000;
+ final long eventTimestampMs = event.getTimeMillis();
Object data = event.getData();
Object[] objects;
if (data instanceof Object[]) {
@@ -152,24 +153,25 @@
*/
@VisibleForTesting
public static class Event {
- long mTimeNanos;
+ long mTimeMillis;
int mPid;
Object mData;
- public Event(long timeNanos, int pid, Object data) {
- mTimeNanos = timeNanos;
+ public Event(long timeMillis, int pid, Object data) {
+ mTimeMillis = timeMillis;
mPid = pid;
mData = data;
}
Event(EventLog.Event nativeEvent) {
- mTimeNanos = nativeEvent.getTimeNanos();
+ mTimeMillis = TimeUnit.MILLISECONDS.convert(
+ nativeEvent.getTimeNanos(), TimeUnit.NANOSECONDS);
mPid = nativeEvent.getProcessId();
mData = nativeEvent.getData();
}
- public long getTimeNanos() {
- return mTimeNanos;
+ public long getTimeMillis() {
+ return mTimeMillis;
}
public int getProcessId() {
@@ -196,7 +198,8 @@
throws IOException {
// Testing in Android: the Static Final Class Strikes Back!
ArrayList<EventLog.Event> nativeEvents = new ArrayList<>();
- EventLog.readEventsOnWrapping(tags, horizonMs, nativeEvents);
+ long horizonNs = TimeUnit.NANOSECONDS.convert(horizonMs, TimeUnit.MILLISECONDS);
+ EventLog.readEventsOnWrapping(tags, horizonNs, nativeEvents);
for (EventLog.Event nativeEvent : nativeEvents) {
Event event = new Event(nativeEvent);
events.add(event);
diff --git a/core/java/android/net/ConnectivityMetricsEvent.java b/core/java/android/net/ConnectivityMetricsEvent.java
index 63ccaae..46bb346 100644
--- a/core/java/android/net/ConnectivityMetricsEvent.java
+++ b/core/java/android/net/ConnectivityMetricsEvent.java
@@ -18,6 +18,7 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.util.BitUtils;
/**
* Represents a core networking event defined in package android.net.metrics.
@@ -78,13 +79,15 @@
public String toString() {
StringBuilder buffer = new StringBuilder("ConnectivityMetricsEvent(");
buffer.append(String.format("%tT.%tL", timestamp, timestamp));
- // TODO: add transports
if (netId != 0) {
buffer.append(", ").append(netId);
}
if (ifname != null) {
buffer.append(", ").append(ifname);
}
+ for (int t : BitUtils.unpackBits(transports)) {
+ buffer.append(", ").append(NetworkCapabilities.transportNameOf(t));
+ }
buffer.append("): ").append(data.toString());
return buffer.toString();
}
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index 7fea4a2..ce7894f 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -32,7 +32,7 @@
*
* <p>Valid lengths for this key are {128, 192, 256}.
*/
- public static final String ALGO_CRYPT_AES_CBC = "cbc(aes)";
+ public static final String CRYPT_AES_CBC = "cbc(aes)";
/**
* MD5 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in new
@@ -40,7 +40,7 @@
*
* <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 128.
*/
- public static final String ALGO_AUTH_HMAC_MD5 = "hmac(md5)";
+ public static final String AUTH_HMAC_MD5 = "hmac(md5)";
/**
* SHA1 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in
@@ -48,35 +48,35 @@
*
* <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 160.
*/
- public static final String ALGO_AUTH_HMAC_SHA1 = "hmac(sha1)";
+ public static final String AUTH_HMAC_SHA1 = "hmac(sha1)";
/**
* SHA256 HMAC Authentication/Integrity Algorithm.
*
* <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 256.
*/
- public static final String ALGO_AUTH_HMAC_SHA256 = "hmac(sha256)";
+ public static final String AUTH_HMAC_SHA256 = "hmac(sha256)";
/**
* SHA384 HMAC Authentication/Integrity Algorithm.
*
* <p>Valid truncation lengths are multiples of 8 bits from 192 to (default) 384.
*/
- public static final String ALGO_AUTH_HMAC_SHA384 = "hmac(sha384)";
+ public static final String AUTH_HMAC_SHA384 = "hmac(sha384)";
/**
* SHA512 HMAC Authentication/Integrity Algorithm
*
* <p>Valid truncation lengths are multiples of 8 bits from 256 to (default) 512.
*/
- public static final String ALGO_AUTH_HMAC_SHA512 = "hmac(sha512)";
+ public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
/** @hide */
@StringDef({
- ALGO_CRYPT_AES_CBC,
- ALGO_AUTH_HMAC_MD5,
- ALGO_AUTH_HMAC_SHA1,
- ALGO_AUTH_HMAC_SHA256,
- ALGO_AUTH_HMAC_SHA512
+ CRYPT_AES_CBC,
+ AUTH_HMAC_MD5,
+ AUTH_HMAC_SHA1,
+ AUTH_HMAC_SHA256,
+ AUTH_HMAC_SHA512
})
@Retention(RetentionPolicy.SOURCE)
public @interface AlgorithmName {}
@@ -164,17 +164,17 @@
private static boolean isTruncationLengthValid(String algo, int truncLenBits) {
switch (algo) {
- case ALGO_CRYPT_AES_CBC:
+ case CRYPT_AES_CBC:
return (truncLenBits == 128 || truncLenBits == 192 || truncLenBits == 256);
- case ALGO_AUTH_HMAC_MD5:
+ case AUTH_HMAC_MD5:
return (truncLenBits >= 96 && truncLenBits <= 128);
- case ALGO_AUTH_HMAC_SHA1:
+ case AUTH_HMAC_SHA1:
return (truncLenBits >= 96 && truncLenBits <= 160);
- case ALGO_AUTH_HMAC_SHA256:
+ case AUTH_HMAC_SHA256:
return (truncLenBits >= 96 && truncLenBits <= 256);
- case ALGO_AUTH_HMAC_SHA384:
+ case AUTH_HMAC_SHA384:
return (truncLenBits >= 192 && truncLenBits <= 384);
- case ALGO_AUTH_HMAC_SHA512:
+ case AUTH_HMAC_SHA512:
return (truncLenBits >= 256 && truncLenBits <= 512);
default:
return false;
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 6852beb..f8702e2 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -193,15 +193,44 @@
*
* @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT}
* @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress.
- * @param requestedSpi the requested SPI, or '0' to allocate a random SPI.
* @return the reserved SecurityParameterIndex
* @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
* for this user
* @throws SpiUnavailableException indicating that a particular SPI cannot be reserved
*/
public SecurityParameterIndex reserveSecurityParameterIndex(
+ int direction, InetAddress remoteAddress)
+ throws ResourceUnavailableException {
+ try {
+ return new SecurityParameterIndex(
+ mService,
+ direction,
+ remoteAddress,
+ IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
+ } catch (SpiUnavailableException unlikely) {
+ throw new ResourceUnavailableException("No SPIs available");
+ }
+ }
+
+ /**
+ * Reserve an SPI for traffic bound towards the specified remote address.
+ *
+ * <p>If successful, this SPI is guaranteed available until released by a call to {@link
+ * SecurityParameterIndex#close()}.
+ *
+ * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT}
+ * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress.
+ * @param requestedSpi the requested SPI, or '0' to allocate a random SPI.
+ * @return the reserved SecurityParameterIndex
+ * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated
+ * for this user
+ */
+ public SecurityParameterIndex reserveSecurityParameterIndex(
int direction, InetAddress remoteAddress, int requestedSpi)
throws SpiUnavailableException, ResourceUnavailableException {
+ if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) {
+ throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI");
+ }
return new SecurityParameterIndex(mService, direction, remoteAddress, requestedSpi);
}
@@ -249,6 +278,23 @@
}
/**
+ * Apply an active Transport Mode IPsec Transform to a stream socket to perform IPsec
+ * encapsulation of the traffic flowing between the socket and the remote InetAddress of that
+ * transform. For security reasons, attempts to send traffic to any IP address other than the
+ * address associated with that transform will throw an IOException. In addition, if the
+ * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
+ * send() or receive() until the transform is removed from the socket by calling {@link
+ * #removeTransportModeTransform(Socket, IpSecTransform)};
+ *
+ * @param socket a socket file descriptor
+ * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
+ */
+ public void applyTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
+ throws IOException {
+ applyTransportModeTransform(new ParcelFileDescriptor(socket), transform);
+ }
+
+ /**
* Apply an active Tunnel Mode IPsec Transform to a network, which will tunnel all traffic to
* and from that network's interface with IPsec (applies an outer IP header and IPsec Header to
* all traffic, and expects an additional IP header and IPsec Header on all inbound traffic).
@@ -289,6 +335,20 @@
removeTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform);
}
+ /**
+ * Remove a transform from a given stream socket. Once removed, traffic on the socket will not
+ * be encypted. This allows sockets that have been used for IPsec to be reclaimed for
+ * communication in the clear in the event socket reuse is desired. This operation will succeed
+ * regardless of the underlying state of a transform. If a transform is removed, communication
+ * on all sockets to which that transform was applied will fail until this method is called.
+ *
+ * @param socket a socket file descriptor that previously had a transform applied to it.
+ * @param transform the IPsec Transform that was previously applied to the given socket
+ */
+ public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform) {
+ removeTransportModeTransform(new ParcelFileDescriptor(socket), transform);
+ }
+
/* Call down to activate a transform */
private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {
try {
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 8665b9c..a594bef 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -19,7 +19,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
-import java.lang.IllegalArgumentException;
+import com.android.internal.util.BitUtils;
/**
* This class represents the capabilities of a network. This is used both to specify
@@ -289,7 +289,7 @@
* @hide
*/
public int[] getCapabilities() {
- return enumerateBits(mNetworkCapabilities);
+ return BitUtils.unpackBits(mNetworkCapabilities);
}
/**
@@ -305,19 +305,6 @@
return ((mNetworkCapabilities & (1 << capability)) != 0);
}
- private int[] enumerateBits(long val) {
- int size = Long.bitCount(val);
- int[] result = new int[size];
- int index = 0;
- int resource = 0;
- while (val > 0) {
- if ((val & 1) == 1) result[index++] = resource;
- val = val >> 1;
- resource++;
- }
- return result;
- }
-
private void combineNetCapabilities(NetworkCapabilities nc) {
this.mNetworkCapabilities |= nc.mNetworkCapabilities;
}
@@ -428,6 +415,15 @@
/** @hide */
public static final int MAX_TRANSPORT = TRANSPORT_WIFI_AWARE;
+ private static final String[] TRANSPORT_NAMES = {
+ "CELLULAR",
+ "WIFI",
+ "BLUETOOTH",
+ "ETHERNET",
+ "VPN",
+ "WIFI_AWARE"
+ };
+
/**
* Adds the given transport type to this {@code NetworkCapability} instance.
* Multiple transports may be applied sequentially. Note that when searching
@@ -474,18 +470,7 @@
* @hide
*/
public int[] getTransportTypes() {
- return enumerateBits(mTransportTypes);
- }
-
- /**
- * Gets all the transports set on this {@code NetworkCapability} instance.
- *
- * @return a bit field composed of up bits at indexes defined by
- * {@code NetworkCapabilities.TRANSPORT_*} values for this instance.
- * @hide
- */
- public long getTransports() {
- return mTransportTypes;
+ return BitUtils.unpackBits(mTransportTypes);
}
/**
@@ -899,18 +884,23 @@
* @hide
*/
public static String transportNamesOf(int[] types) {
- String transports = "";
- for (int i = 0; i < types.length;) {
- switch (types[i]) {
- case TRANSPORT_CELLULAR: transports += "CELLULAR"; break;
- case TRANSPORT_WIFI: transports += "WIFI"; break;
- case TRANSPORT_BLUETOOTH: transports += "BLUETOOTH"; break;
- case TRANSPORT_ETHERNET: transports += "ETHERNET"; break;
- case TRANSPORT_VPN: transports += "VPN"; break;
- case TRANSPORT_WIFI_AWARE: transports += "WIFI_AWARE"; break;
- }
- if (++i < types.length) transports += "|";
+ if (types == null || types.length == 0) {
+ return "";
}
- return transports;
+ StringBuilder transports = new StringBuilder();
+ for (int t : types) {
+ transports.append("|").append(transportNameOf(t));
+ }
+ return transports.substring(1);
+ }
+
+ /**
+ * @hide
+ */
+ public static String transportNameOf(int transport) {
+ if (transport < 0 || TRANSPORT_NAMES.length <= transport) {
+ return "UNKNOWN";
+ }
+ return TRANSPORT_NAMES[transport];
}
}
diff --git a/core/java/android/net/NetworkRecommendationProvider.java b/core/java/android/net/NetworkRecommendationProvider.java
index 271b0a7..af0459d 100644
--- a/core/java/android/net/NetworkRecommendationProvider.java
+++ b/core/java/android/net/NetworkRecommendationProvider.java
@@ -20,6 +20,19 @@
/**
* The base class for implementing a network recommendation provider.
+ * <p>
+ * A network recommendation provider is any application which:
+ * <ul>
+ * <li>Is granted the {@link permission#SCORE_NETWORKS} permission.
+ * <li>Includes a Service for the {@link NetworkScoreManager#ACTION_RECOMMEND_NETWORKS} intent
+ * which is protected by the {@link permission#BIND_NETWORK_RECOMMENDATION_SERVICE} permission.
+ * </ul>
+ * <p>
+ * Implementations are required to implement the abstract methods in this class and return the
+ * result of {@link #getBinder()} from the <code>onBind()</code> method in their Service.
+ * <p>
+ * The default network recommendation provider is controlled via the
+ * <code>config_defaultNetworkRecommendationProviderPackage</code> config key.
* @hide
*/
@SystemApi
diff --git a/core/java/android/net/metrics/ConnectStats.java b/core/java/android/net/metrics/ConnectStats.java
index 214edee..30b2656 100644
--- a/core/java/android/net/metrics/ConnectStats.java
+++ b/core/java/android/net/metrics/ConnectStats.java
@@ -16,53 +16,47 @@
package android.net.metrics;
+import android.net.NetworkCapabilities;
import android.system.OsConstants;
import android.util.IntArray;
import android.util.SparseIntArray;
+import com.android.internal.util.BitUtils;
import com.android.internal.util.TokenBucket;
-import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.ConnectStatistics;
-import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.Pair;
/**
- * A class that aggregates connect() statistics and helps build
- * IpConnectivityLogClass.ConnectStatistics instances.
- *
+ * A class that aggregates connect() statistics.
* {@hide}
*/
public class ConnectStats {
private final static int EALREADY = OsConstants.EALREADY;
private final static int EINPROGRESS = OsConstants.EINPROGRESS;
+ /** Network id of the network associated with the event, or 0 if unspecified. */
+ public final int netId;
+ /** Transports of the network associated with the event, as defined in NetworkCapabilities. */
+ public final long transports;
/** How many events resulted in a given errno. */
- private final SparseIntArray mErrnos = new SparseIntArray();
- /** Latencies of blocking connects. TODO: add non-blocking connects latencies. */
- private final IntArray mLatencies = new IntArray();
+ public final SparseIntArray errnos = new SparseIntArray();
+ /** Latencies of successful blocking connects. TODO: add non-blocking connects latencies. */
+ public final IntArray latencies = new IntArray();
/** TokenBucket for rate limiting latency recording. */
- private final TokenBucket mLatencyTb;
+ public final TokenBucket mLatencyTb;
/** Maximum number of latency values recorded. */
- private final int mMaxLatencyRecords;
+ public final int mMaxLatencyRecords;
/** Total count of successful connects. */
- private int mConnectCount = 0;
+ public int connectCount = 0;
/** Total count of successful connects done in blocking mode. */
- private int mConnectBlockingCount = 0;
+ public int connectBlockingCount = 0;
/** Total count of successful connects with IPv6 socket address. */
- private int mIpv6ConnectCount = 0;
+ public int ipv6ConnectCount = 0;
- public ConnectStats(TokenBucket tb, int maxLatencyRecords) {
+ public ConnectStats(int netId, long transports, TokenBucket tb, int maxLatencyRecords) {
+ this.netId = netId;
+ this.transports = transports;
mLatencyTb = tb;
mMaxLatencyRecords = maxLatencyRecords;
}
- public ConnectStatistics toProto() {
- ConnectStatistics stats = new ConnectStatistics();
- stats.connectCount = mConnectCount;
- stats.connectBlockingCount = mConnectBlockingCount;
- stats.ipv6AddrCount = mIpv6ConnectCount;
- stats.latenciesMs = mLatencies.toArray();
- stats.errnosCounters = toPairArrays(mErrnos);
- return stats;
- }
-
public void addEvent(int errno, int latencyMs, String ipAddr) {
if (isSuccess(errno)) {
countConnect(errno, ipAddr);
@@ -73,12 +67,12 @@
}
private void countConnect(int errno, String ipAddr) {
- mConnectCount++;
+ connectCount++;
if (!isNonBlocking(errno)) {
- mConnectBlockingCount++;
+ connectBlockingCount++;
}
if (isIPv6(ipAddr)) {
- mIpv6ConnectCount++;
+ ipv6ConnectCount++;
}
}
@@ -91,16 +85,16 @@
// Rate limited
return;
}
- if (mLatencies.size() >= mMaxLatencyRecords) {
+ if (latencies.size() >= mMaxLatencyRecords) {
// Hard limit the total number of latency measurements.
return;
}
- mLatencies.add(ms);
+ latencies.add(ms);
}
private void countError(int errno) {
- final int newcount = mErrnos.get(errno, 0) + 1;
- mErrnos.put(errno, newcount);
+ final int newcount = errnos.get(errno, 0) + 1;
+ errnos.put(errno, newcount);
}
private static boolean isSuccess(int errno) {
@@ -117,27 +111,18 @@
return ipAddr.contains(":");
}
- private static Pair[] toPairArrays(SparseIntArray counts) {
- final int s = counts.size();
- Pair[] pairs = new Pair[s];
- for (int i = 0; i < s; i++) {
- Pair p = new Pair();
- p.key = counts.keyAt(i);
- p.value = counts.valueAt(i);
- pairs[i] = p;
- }
- return pairs;
- }
-
@Override
public String toString() {
- StringBuilder builder = new StringBuilder("ConnectStats(")
- .append(String.format("%d success, ", mConnectCount))
- .append(String.format("%d blocking, ", mConnectBlockingCount))
- .append(String.format("%d IPv6 dst", mIpv6ConnectCount));
- for (int i = 0; i < mErrnos.size(); i++) {
- String errno = OsConstants.errnoName(mErrnos.keyAt(i));
- int count = mErrnos.valueAt(i);
+ StringBuilder builder = new StringBuilder("ConnectStats(").append(netId).append(", ");
+ for (int t : BitUtils.unpackBits(transports)) {
+ builder.append(NetworkCapabilities.transportNameOf(t)).append(", ");
+ }
+ builder.append(String.format("%d success, ", connectCount));
+ builder.append(String.format("%d blocking, ", connectBlockingCount));
+ builder.append(String.format("%d IPv6 dst", ipv6ConnectCount));
+ for (int i = 0; i < errnos.size(); i++) {
+ String errno = OsConstants.errnoName(errnos.keyAt(i));
+ int count = errnos.valueAt(i);
builder.append(String.format(", %s: %d", errno, count));
}
return builder.append(")").toString();
diff --git a/core/java/android/net/metrics/DnsEvent.java b/core/java/android/net/metrics/DnsEvent.java
index 89ae1c2..a4970e4 100644
--- a/core/java/android/net/metrics/DnsEvent.java
+++ b/core/java/android/net/metrics/DnsEvent.java
@@ -16,67 +16,70 @@
package android.net.metrics;
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.net.NetworkCapabilities;
+import java.util.Arrays;
+import com.android.internal.util.BitUtils;
/**
* A DNS event recorded by NetdEventListenerService.
* {@hide}
*/
-final public class DnsEvent implements Parcelable {
- public final int netId;
+final public class DnsEvent {
- // The event type is currently only 1 or 2, so we store it as a byte.
- public final byte[] eventTypes;
+ private static final int SIZE_LIMIT = 20000;
+
+ // Network id of the network associated with the event, or 0 if unspecified.
+ public final int netId;
+ // Transports of the network associated with the event, as defined in NetworkCapabilities.
+ // It is the caller responsability to ensure the value of transports does not change between
+ // calls to addResult.
+ public final long transports;
+ // The number of DNS queries recorded. Queries are stored in the structure-of-array style where
+ // the eventTypes, returnCodes, and latenciesMs arrays have the same length and the i-th event
+ // is spread across the three array at position i.
+ public int eventCount;
+ // The types of DNS queries as defined in INetdEventListener.
+ public byte[] eventTypes;
// Current getaddrinfo codes go from 1 to EAI_MAX = 15. gethostbyname returns errno, but there
// are fewer than 255 errno values. So we store the result code in a byte as well.
- public final byte[] returnCodes;
- // The latency is an integer because a) short arrays aren't parcelable and b) a short can only
- // store a maximum latency of 32757 or 65535 ms, which is too short for pathologically slow
- // queries.
- public final int[] latenciesMs;
+ public byte[] returnCodes;
+ // Latencies in milliseconds of queries, stored as ints.
+ public int[] latenciesMs;
- public DnsEvent(int netId, byte[] eventTypes, byte[] returnCodes, int[] latenciesMs) {
+ public DnsEvent(int netId, long transports, int initialCapacity) {
this.netId = netId;
- this.eventTypes = eventTypes;
- this.returnCodes = returnCodes;
- this.latenciesMs = latenciesMs;
+ this.transports = transports;
+ eventTypes = new byte[initialCapacity];
+ returnCodes = new byte[initialCapacity];
+ latenciesMs = new int[initialCapacity];
}
- private DnsEvent(Parcel in) {
- this.netId = in.readInt();
- this.eventTypes = in.createByteArray();
- this.returnCodes = in.createByteArray();
- this.latenciesMs = in.createIntArray();
+ public void addResult(byte eventType, byte returnCode, int latencyMs) {
+ if (eventCount >= SIZE_LIMIT) {
+ // TODO: implement better rate limiting that does not biases metrics.
+ return;
+ }
+ if (eventCount == eventTypes.length) {
+ resize((int) (1.4 * eventCount));
+ }
+ eventTypes[eventCount] = eventType;
+ returnCodes[eventCount] = returnCode;
+ latenciesMs[eventCount] = latencyMs;
+ eventCount++;
}
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(netId);
- out.writeByteArray(eventTypes);
- out.writeByteArray(returnCodes);
- out.writeIntArray(latenciesMs);
- }
-
- @Override
- public int describeContents() {
- return 0;
+ public void resize(int newLength) {
+ eventTypes = Arrays.copyOf(eventTypes, newLength);
+ returnCodes = Arrays.copyOf(returnCodes, newLength);
+ latenciesMs = Arrays.copyOf(latenciesMs, newLength);
}
@Override
public String toString() {
- return String.format("DnsEvent(%d, %d events)", netId, eventTypes.length);
+ StringBuilder builder = new StringBuilder("DnsEvent(").append(netId).append(", ");
+ for (int t : BitUtils.unpackBits(transports)) {
+ builder.append(NetworkCapabilities.transportNameOf(t)).append(", ");
+ }
+ return builder.append(eventCount).append(" events)").toString();
}
-
- public static final Parcelable.Creator<DnsEvent> CREATOR = new Parcelable.Creator<DnsEvent>() {
- @Override
- public DnsEvent createFromParcel(Parcel in) {
- return new DnsEvent(in);
- }
-
- @Override
- public DnsEvent[] newArray(int size) {
- return new DnsEvent[size];
- }
- };
}
diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java
index ac727ca..4e57efa 100644
--- a/core/java/android/net/metrics/IpConnectivityLog.java
+++ b/core/java/android/net/metrics/IpConnectivityLog.java
@@ -23,6 +23,7 @@
import android.os.ServiceManager;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.BitUtils;
/**
* Class for logging IpConnectvity events with IpConnectivityMetrics
@@ -117,10 +118,10 @@
* @param data is a Parcelable instance representing the event.
* @return true if the event was successfully logged.
*/
- public boolean log(int netid, long transports, Parcelable data) {
+ public boolean log(int netid, int[] transports, Parcelable data) {
ConnectivityMetricsEvent ev = makeEv(data);
ev.netId = netid;
- ev.transports = transports;
+ ev.transports = BitUtils.packBits(transports);
return log(ev);
}
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 6f388e2..65025fb 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -325,6 +325,23 @@
}
/**
+ * @hide This kind-of does an equality comparison. Kind-of.
+ */
+ public boolean kindofEquals(BaseBundle other) {
+ if (other == null) {
+ return false;
+ }
+ if (isParcelled() != other.isParcelled()) {
+ // Big kind-of here!
+ return false;
+ } else if (isParcelled()) {
+ return mParcelledData.compareData(other.mParcelledData) == 0;
+ } else {
+ return mMap.equals(other.mMap);
+ }
+ }
+
+ /**
* Removes all elements from the mapping of this Bundle.
*/
public void clear() {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 4c6d22a..832031e 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -182,7 +182,7 @@
* New in version 19:
* - Wakelock data (wl) gets current and max times.
* New in version 20:
- * - Background timers and counters for: Sensor, BluetoothScan, WifiScan, Jobs.
+ * - Background timers and counters for: Sensor, BluetoothScan, WifiScan, Jobs, Syncs.
*/
static final String CHECKIN_VERSION = "20";
@@ -594,11 +594,6 @@
public abstract long getSystemCpuTimeUs(int which);
/**
- * Get the total cpu power consumed (in milli-ampere-microseconds).
- */
- public abstract long getCpuPowerMaUs(int which);
-
- /**
* Returns the approximate cpu time (in milliseconds) spent at a certain CPU speed for a
* given CPU cluster.
* @param cluster the index of the CPU cluster.
@@ -3392,9 +3387,13 @@
// Convert from microseconds to milliseconds with rounding
final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
final int count = timer.getCountLocked(which);
+ final Timer bgTimer = timer.getSubTimer();
+ final long bgTime = bgTimer != null ?
+ (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+ final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
if (totalTime != 0) {
dumpLine(pw, uid, category, SYNC_DATA, "\"" + syncs.keyAt(isy) + "\"",
- totalTime, count);
+ totalTime, count, bgTime, bgCount);
}
}
@@ -3467,10 +3466,9 @@
final long userCpuTimeUs = u.getUserCpuTimeUs(which);
final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
- final long powerCpuMaUs = u.getCpuPowerMaUs(which);
- if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) {
+ if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) {
dumpLine(pw, uid, category, CPU_DATA, userCpuTimeUs / 1000, systemCpuTimeUs / 1000,
- powerCpuMaUs / 1000);
+ 0 /* old cpu power, keep for compatibility */);
}
final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
@@ -4608,6 +4606,10 @@
// Convert from microseconds to milliseconds with rounding
final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
final int count = timer.getCountLocked(which);
+ final Timer bgTimer = timer.getSubTimer();
+ final long bgTime = bgTimer != null ?
+ (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+ final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
sb.setLength(0);
sb.append(prefix);
sb.append(" Sync ");
@@ -4618,6 +4620,13 @@
sb.append("realtime (");
sb.append(count);
sb.append(" times)");
+ if (bgTime > 0) {
+ sb.append(", ");
+ formatTimeMs(sb, bgTime);
+ sb.append("background (");
+ sb.append(bgCount);
+ sb.append(" times)");
+ }
} else {
sb.append("(not used)");
}
@@ -4758,17 +4767,13 @@
final long userCpuTimeUs = u.getUserCpuTimeUs(which);
final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
- final long powerCpuMaUs = u.getCpuPowerMaUs(which);
- if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) {
+ if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) {
sb.setLength(0);
sb.append(prefix);
sb.append(" Total cpu time: u=");
formatTimeMs(sb, userCpuTimeUs / 1000);
sb.append("s=");
formatTimeMs(sb, systemCpuTimeUs / 1000);
- sb.append("p=");
- printmAh(sb, powerCpuMaUs / (1000.0 * 1000.0 * 60.0 * 60.0));
- sb.append("mAh");
pw.println(sb.toString());
}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 76128e6..c3836a3 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -315,6 +315,7 @@
private static native byte[] nativeMarshall(long nativePtr);
private static native long nativeUnmarshall(
long nativePtr, byte[] data, int offset, int length);
+ private static native int nativeCompareData(long thisNativePtr, long otherNativePtr);
private static native long nativeAppendFrom(
long thisNativePtr, long otherNativePtr, int offset, int length);
@FastNative
@@ -487,6 +488,11 @@
updateNativeSize(nativeAppendFrom(mNativePtr, parcel.mNativePtr, offset, length));
}
+ /** @hide */
+ public final int compareData(Parcel other) {
+ return nativeCompareData(mNativePtr, other.mNativePtr);
+ }
+
/**
* Report whether the parcel contains any marshalled file descriptors.
*/
diff --git a/core/java/android/os/ProxyFileDescriptorCallback.java b/core/java/android/os/ProxyFileDescriptorCallback.java
index 2e9f8d9..e69fb55 100644
--- a/core/java/android/os/ProxyFileDescriptorCallback.java
+++ b/core/java/android/os/ProxyFileDescriptorCallback.java
@@ -21,12 +21,14 @@
/**
* Callback that handles file system requests from ProxyFileDescriptor.
+ *
+ * @see android.os.storage.StorageManager#openProxyFileDescriptor(int, ProxyFileDescriptorCallback)
*/
public abstract class ProxyFileDescriptorCallback {
/**
* Returns size of bytes provided by the file descriptor.
- * @return Size of bytes
- * @throws ErrnoException
+ * @return Size of bytes.
+ * @throws ErrnoException ErrnoException containing E constants in OsConstants.
*/
public long onGetSize() throws ErrnoException {
throw new ErrnoException("onGetSize", OsConstants.EBADF);
@@ -35,11 +37,13 @@
/**
* Provides bytes read from file descriptor.
* It needs to return exact requested size of bytes unless it reaches file end.
- * @param offset Where to read bytes from.
+ * @param offset Offset in bytes from the file head specifying where to read bytes. If a seek
+ * operation is conducted on the file descriptor, then a read operation is requested, the
+ * offset refrects the proper position of requested bytes.
* @param size Size for read bytes.
* @param data Byte array to store read bytes.
* @return Size of bytes returned by the function.
- * @throws ErrnoException
+ * @throws ErrnoException ErrnoException containing E constants in OsConstants.
*/
public int onRead(long offset, int size, byte[] data) throws ErrnoException {
throw new ErrnoException("onRead", OsConstants.EBADF);
@@ -47,19 +51,23 @@
/**
* Handles bytes written to file descriptor.
- * @param offset Where to write bytes to.
+ * @param offset Offset in bytes from the file head specifying where to write bytes. If a seek
+ * operation is conducted on the file descriptor, then a write operation is requested, the
+ * offset refrects the proper position of requested bytes.
* @param size Size for write bytes.
* @param data Byte array to be written to somewhere.
* @return Size of bytes processed by the function.
- * @throws ErrnoException
+ * @throws ErrnoException ErrnoException containing E constants in OsConstants.
*/
public int onWrite(long offset, int size, byte[] data) throws ErrnoException {
throw new ErrnoException("onWrite", OsConstants.EBADF);
}
/**
- * Processes fsync request.
- * @throws ErrnoException
+ * Ensures all the written data are stored in permanent storage device.
+ * For example, if it has data stored in on memory cache, it needs to flush data to storage
+ * device.
+ * @throws ErrnoException ErrnoException containing E constants in OsConstants.
*/
public void onFsync() throws ErrnoException {
throw new ErrnoException("onFsync", OsConstants.EINVAL);
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 4aec8ae..6a4fef2 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -344,6 +344,7 @@
* @hide
*/
@SystemApi
+ @TestApi
public @UserIdInt int getIdentifier() {
return mHandle;
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index a6bf2d2..6f4c9cf 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -682,8 +682,10 @@
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
* @see #getUserRestrictions()
+ * @deprecated use {@link OemLockManager#setOemUnlockAllowedByCarrier(boolean, byte[])} instead.
* @hide
*/
+ @Deprecated
@SystemApi
public static final String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index b1f6421..c6bbf48 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -19,6 +19,7 @@
import android.app.ActivityThread;
import android.content.Context;
import android.media.AudioAttributes;
+import android.util.Log;
/**
* Class that operates the vibrator on the device.
@@ -30,6 +31,7 @@
* {@link Context#getSystemService} with {@link Context#VIBRATOR_SERVICE} as the argument.
*/
public abstract class Vibrator {
+ private static final String TAG = "Vibrator";
private final String mPackageName;
@@ -90,9 +92,14 @@
*/
@Deprecated
public void vibrate(long milliseconds, AudioAttributes attributes) {
- VibrationEffect effect =
- VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE);
- vibrate(effect, attributes);
+ try {
+ // This ignores all exceptions to stay compatible with pre-O implementations.
+ VibrationEffect effect =
+ VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE);
+ vibrate(effect, attributes);
+ } catch (IllegalArgumentException iae) {
+ Log.e(TAG, "Failed to create VibrationEffect", iae);
+ }
}
/**
@@ -150,12 +157,17 @@
*/
@Deprecated
public void vibrate(long[] pattern, int repeat, AudioAttributes attributes) {
- // This call needs to continue throwing ArrayIndexOutOfBoundsException for compatibility
- // purposes, whereas VibrationEffect throws an IllegalArgumentException.
+ // This call needs to continue throwing ArrayIndexOutOfBoundsException but ignore all other
+ // exceptions for compatibility purposes
if (repeat < -1 || repeat >= pattern.length) {
throw new ArrayIndexOutOfBoundsException();
}
- vibrate(VibrationEffect.createWaveform(pattern, repeat), attributes);
+
+ try {
+ vibrate(VibrationEffect.createWaveform(pattern, repeat), attributes);
+ } catch (IllegalArgumentException iae) {
+ Log.e(TAG, "Failed to create VibrationEffect", iae);
+ }
}
public void vibrate(VibrationEffect vibe) {
diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java
new file mode 100644
index 0000000..1ef3916
--- /dev/null
+++ b/core/java/android/os/VintfObject.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import java.util.ArrayList;
+
+import android.util.Log;
+
+/** @hide */
+public class VintfObject {
+
+ private static final String LOG_TAG = "VintfObject";
+
+ /**
+ * Slurps all device information (both manifests)
+ * and report it.
+ * If any error in getting one of the manifests, it is not included in
+ * the list.
+ */
+ public static String[] report() {
+ ArrayList<String> ret = new ArrayList<>();
+ put(ret, getDeviceManifest(), "device manifest");
+ put(ret, getFrameworkManifest(), "framework manifest");
+ return ret.toArray(new String[0]);
+ }
+
+ /**
+ * Verify that the given metadata for an OTA package is compatible with
+ * this device.
+ *
+ * @param packageInfo a list of serialized form of HalMaanifest's /
+ * CompatibilityMatri'ces (XML).
+ * @return = 0 if success (compatible)
+ * > 0 if incompatible
+ * < 0 if any error (mount partition fails, illformed XML, etc.)
+ */
+ public static native int verify(String[] packageInfo);
+
+ // return null if any error, otherwise XML string.
+ private static native String getDeviceManifest();
+ private static native String getFrameworkManifest();
+
+ private static void put(ArrayList<String> list, String content, String message) {
+ if (content == null || content.length() == 0) {
+ Log.e(LOG_TAG, "Cannot get;" + message + "; check native logs for details.");
+ return;
+ }
+ list.add(content);
+ }
+}
diff --git a/core/java/android/os/health/UidHealthStats.java b/core/java/android/os/health/UidHealthStats.java
index a702cdb..afc9d78 100644
--- a/core/java/android/os/health/UidHealthStats.java
+++ b/core/java/android/os/health/UidHealthStats.java
@@ -445,7 +445,10 @@
/**
* An estimate of the number of milliamp-microsends used by this uid.
+ *
+ * @deprecated this measurement is vendor-dependent and not reliable.
*/
+ @Deprecated
@HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
public static final int MEASUREMENT_CPU_POWER_MAMS = HealthKeys.BASE_UID + 64;
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
index 4deb4ab..e9ef770 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -15,10 +15,18 @@
*/
package android.provider;
+import static android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.Signature;
@@ -26,8 +34,10 @@
import android.graphics.Typeface;
import android.graphics.fonts.FontRequest;
import android.graphics.fonts.FontResult;
+import android.graphics.fonts.FontVariationAxis;
import android.net.Uri;
import android.os.Bundle;
+import android.os.CancellationSignal;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
@@ -37,14 +47,22 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* Utility class to deal with Font ContentProviders.
@@ -62,6 +80,15 @@
public static final class Columns implements BaseColumns {
/**
* Constant used to request data from a font provider. The cursor returned from the query
+ * may populate this column with a long for the font file ID. The client will request a file
+ * descriptor to "file/FILE_ID" with this ID immediately under the top-level content URI. If
+ * not present, the client will request a file descriptor to the top-level URI with the
+ * given base font ID. Note that several results may return the same file ID, e.g. for TTC
+ * files with different indices.
+ */
+ public static final String FILE_ID = "file_id";
+ /**
+ * Constant used to request data from a font provider. The cursor returned from the query
* should have this column populated with an int for the ttc index for the resulting font.
*/
public static final String TTC_INDEX = "font_ttc_index";
@@ -131,7 +158,6 @@
* @hide
*/
public static final String PARCEL_FONT_RESULTS = "font_results";
-
// Error codes internal to the system, which can not come from a provider. To keep the number
// space open for new provider codes, these should all be negative numbers.
/** @hide */
@@ -156,11 +182,128 @@
mPackageManager = mContext.getPackageManager();
}
- /** @hide */
- @VisibleForTesting
- public FontsContract(Context context, PackageManager packageManager) {
- mContext = context;
- mPackageManager = packageManager;
+ /**
+ * Object represent a font entry in the family returned from {@link #fetchFonts}.
+ */
+ public static class FontInfo {
+ private final Uri mUri;
+ private final int mTtcIndex;
+ private final FontVariationAxis[] mAxes;
+ private final int mWeight;
+ private final boolean mItalic;
+ private final int mResultCode;
+
+ /**
+ * Creates a Font with all the information needed about a provided font.
+ * @param uri A URI associated to the font file.
+ * @param ttcIndex If providing a TTC_INDEX file, the index to point to. Otherwise, 0.
+ * @param axes If providing a variation font, the settings for it. May be null.
+ * @param weight An integer that indicates the font weight.
+ * @param italic A boolean that indicates the font is italic style or not.
+ * @param resultCode A boolean that indicates the font contents is ready.
+ */
+ /** @hide */
+ public FontInfo(@NonNull Uri uri, @IntRange(from = 0) int ttcIndex,
+ @Nullable FontVariationAxis[] axes, @IntRange(from = 1, to = 1000) int weight,
+ boolean italic, int resultCode) {
+ mUri = Preconditions.checkNotNull(uri);
+ mTtcIndex = ttcIndex;
+ mAxes = axes;
+ mWeight = weight;
+ mItalic = italic;
+ mResultCode = resultCode;
+ }
+
+ /**
+ * Returns a URI associated to this record.
+ */
+ public @NonNull Uri getUri() {
+ return mUri;
+ }
+
+ /**
+ * Returns the index to be used to access this font when accessing a TTC file.
+ */
+ public @IntRange(from = 0) int getTtcIndex() {
+ return mTtcIndex;
+ }
+
+ /**
+ * Returns the list of axes associated to this font.
+ */
+ public @Nullable FontVariationAxis[] getAxes() {
+ return mAxes;
+ }
+
+ /**
+ * Returns the weight value for this font.
+ */
+ public @IntRange(from = 1, to = 1000) int getWeight() {
+ return mWeight;
+ }
+
+ /**
+ * Returns whether this font is italic.
+ */
+ public boolean isItalic() {
+ return mItalic;
+ }
+
+ /**
+ * Returns result code.
+ *
+ * {@link FontsContract.Columns#RESULT_CODE}
+ */
+ public int getResultCode() {
+ return mResultCode;
+ }
+ }
+
+ /**
+ * Object returned from {@link #fetchFonts}.
+ */
+ public static class FontFamilyResult {
+ /**
+ * Constant represents that the font was successfully retrieved. Note that when this value
+ * is set and {@link #getFonts} returns an empty array, it means there were no fonts
+ * matching the given query.
+ */
+ public static final int STATUS_OK = 0;
+
+ /**
+ * Constant represents that the given certificate was not matched with the provider's
+ * signature. {@link #getFonts} returns null if this status was set.
+ */
+ public static final int STATUS_WRONG_CERTIFICATES = 1;
+
+ /**
+ * Constant represents that the provider returns unexpected data. {@link #getFonts} returns
+ * null if this status was set. For example, this value is set when the font provider
+ * gives invalid format of variation settings.
+ */
+ public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2;
+
+ /** @hide */
+ @IntDef({STATUS_OK, STATUS_WRONG_CERTIFICATES, STATUS_UNEXPECTED_DATA_PROVIDED})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface FontResultStatus {}
+
+ private final @FontResultStatus int mStatusCode;
+ private final FontInfo[] mFonts;
+
+ /** @hide */
+ public FontFamilyResult(@FontResultStatus int statusCode, @Nullable FontInfo[] fonts) {
+ mStatusCode = statusCode;
+ mFonts = fonts;
+ }
+
+ public @FontResultStatus int getStatusCode() {
+ return mStatusCode;
+ }
+
+ public @NonNull FontInfo[] getFonts() {
+ return mFonts;
+ }
}
// We use a background thread to post the content resolving work for all requests on. This
@@ -187,33 +330,350 @@
mHandler = new Handler(mThread.getLooper());
}
mHandler.post(() -> {
- ProviderInfo providerInfo = getProvider(request, receiver);
- if (providerInfo == null) {
+ ProviderInfo providerInfo;
+ try {
+ providerInfo = getProvider(mPackageManager, request);
+ if (providerInfo == null) {
+ receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
+ return;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
return;
}
- getFontFromProvider(request, receiver, providerInfo.authority);
+ FontInfo[] fonts;
+ try {
+ fonts = getFontFromProvider(mContext, request, providerInfo.authority,
+ null /* cancellation signal */);
+ } catch (InvalidFormatException e) {
+ receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
+ return;
+ }
+
+ ArrayList<FontResult> result = new ArrayList<>();
+ int resultCode = -1;
+ for (FontInfo font : fonts) {
+ try {
+ resultCode = font.getResultCode();
+ if (resultCode != Columns.RESULT_CODE_OK) {
+ if (resultCode < 0) {
+ // Negative values are reserved for the internal errors.
+ resultCode = Columns.RESULT_CODE_FONT_NOT_FOUND;
+ }
+ for (int i = 0; i < result.size(); ++i) {
+ try {
+ result.get(i).getFileDescriptor().close();
+ } catch (IOException e) {
+ // Ignore, as we are closing fds for cleanup.
+ }
+ }
+ receiver.send(resultCode, null);
+ return;
+ }
+ ParcelFileDescriptor pfd = mContext.getContentResolver().openFileDescriptor(
+ font.getUri(), "r");
+ result.add(new FontResult(pfd, font.getTtcIndex(),
+ FontVariationAxis.toFontVariationSettings(font.getAxes()),
+ font.getWeight(), font.isItalic()));
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, "FileNotFoundException raised when interacting with content "
+ + "provider " + providerInfo.authority, e);
+ }
+ }
+ if (!result.isEmpty()) {
+ Bundle bundle = new Bundle();
+ bundle.putParcelableArrayList(PARCEL_FONT_RESULTS, result);
+ receiver.send(Columns.RESULT_CODE_OK, bundle);
+ return;
+ }
+ receiver.send(Columns.RESULT_CODE_FONT_NOT_FOUND, null);
});
mHandler.removeCallbacks(mReplaceDispatcherThreadRunnable);
mHandler.postDelayed(mReplaceDispatcherThreadRunnable, THREAD_RENEWAL_THRESHOLD_MS);
}
}
+ /**
+ * Interface used to receive asynchronously fetched typefaces.
+ */
+ public static class FontRequestCallback {
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
+ * provider was not found on the device.
+ */
+ public static final int FAIL_REASON_PROVIDER_NOT_FOUND = RESULT_CODE_PROVIDER_NOT_FOUND;
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
+ * provider must be authenticated and the given certificates do not match its signature.
+ */
+ public static final int FAIL_REASON_WRONG_CERTIFICATES = RESULT_CODE_WRONG_CERTIFICATES;
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
+ * returned by the provider was not loaded properly.
+ */
+ public static final int FAIL_REASON_FONT_LOAD_ERROR = -3;
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
+ * provider did not return any results for the given query.
+ */
+ public static final int FAIL_REASON_FONT_NOT_FOUND = Columns.RESULT_CODE_FONT_NOT_FOUND;
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
+ * provider found the queried font, but it is currently unavailable.
+ */
+ public static final int FAIL_REASON_FONT_UNAVAILABLE = Columns.RESULT_CODE_FONT_UNAVAILABLE;
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
+ * query was not supported by the provider.
+ */
+ public static final int FAIL_REASON_MALFORMED_QUERY = Columns.RESULT_CODE_MALFORMED_QUERY;
+
+ /** @hide */
+ @IntDef({ FAIL_REASON_PROVIDER_NOT_FOUND, FAIL_REASON_FONT_LOAD_ERROR,
+ FAIL_REASON_FONT_NOT_FOUND, FAIL_REASON_FONT_UNAVAILABLE,
+ FAIL_REASON_MALFORMED_QUERY })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface FontRequestFailReason {}
+
+ public FontRequestCallback() {}
+
+ /**
+ * Called then a Typeface request done via {@link Typeface#create(FontRequest,
+ * FontRequestCallback)} is complete. Note that this method will not be called if
+ * {@link #onTypefaceRequestFailed(int)} is called instead.
+ * @param typeface The Typeface object retrieved.
+ */
+ public void onTypefaceRetrieved(Typeface typeface) {}
+
+ /**
+ * Called when a Typeface request done via {@link Typeface#create(FontRequest,
+ * FontRequestCallback)} fails.
+ * @param reason One of {@link #FAIL_REASON_PROVIDER_NOT_FOUND},
+ * {@link #FAIL_REASON_FONT_NOT_FOUND},
+ * {@link #FAIL_REASON_FONT_LOAD_ERROR},
+ * {@link #FAIL_REASON_FONT_UNAVAILABLE} or
+ * {@link #FAIL_REASON_MALFORMED_QUERY}.
+ */
+ public void onTypefaceRequestFailed(@FontRequestFailReason int reason) {}
+ }
+
+ /**
+ * Create a typeface object given a font request. The font will be asynchronously fetched,
+ * therefore the result is delivered to the given callback. See {@link FontRequest}.
+ * Only one of the methods in callback will be invoked, depending on whether the request
+ * succeeds or fails. These calls will happen on the caller thread.
+ * @param context A context to be used for fetching from font provider.
+ * @param request A {@link FontRequest} object that identifies the provider and query for the
+ * request. May not be null.
+ * @param callback A callback that will be triggered when results are obtained. May not be null.
+ * @param handler A handler to be processed the font fetching.
+ */
+ public static void requestFont(@NonNull Context context, @NonNull FontRequest request,
+ @NonNull FontRequestCallback callback, @NonNull Handler handler) {
+
+ final Handler callerThreadHandler = new Handler();
+ handler.post(() -> {
+ // TODO: Cache the result.
+ FontFamilyResult result;
+ try {
+ result = fetchFonts(context, null /* cancellation signal */, request);
+ } catch (NameNotFoundException e) {
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_PROVIDER_NOT_FOUND));
+ return;
+ }
+
+ if (result.getStatusCode() != FontFamilyResult.STATUS_OK) {
+ switch (result.getStatusCode()) {
+ case FontFamilyResult.STATUS_WRONG_CERTIFICATES:
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_WRONG_CERTIFICATES));
+ return;
+ case FontFamilyResult.STATUS_UNEXPECTED_DATA_PROVIDED:
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR));
+ return;
+ default:
+ // fetchFont returns unexpected status type. Fallback to load error.
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR));
+ return;
+ }
+ }
+
+ final FontInfo[] fonts = result.getFonts();
+ if (fonts == null || fonts.length == 0) {
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND));
+ return;
+ }
+ for (final FontInfo font : fonts) {
+ if (font.getResultCode() != Columns.RESULT_CODE_OK) {
+ // We proceed if all font entry is ready to use. Otherwise report the first
+ // error.
+ final int resultCode = font.getResultCode();
+ if (resultCode < 0) {
+ // Negative values are reserved for internal errors. Fallback to load error.
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR));
+ } else {
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ resultCode));
+ }
+ return;
+ }
+ }
+
+ final Typeface typeface = buildTypeface(context, null /* cancellation signal */, fonts);
+ if (typeface == null) {
+ // Something went wrong during reading font files. This happens if the given font
+ // file is an unsupported font type.
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR));
+ return;
+ }
+
+ callerThreadHandler.post(() -> callback.onTypefaceRetrieved(typeface));
+ });
+ }
+
+ /**
+ * Fetch fonts given a font request.
+ *
+ * @param context A {@link Context} to be used for fetching fonts.
+ * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If
+ * the operation is canceled, then {@link
+ * android.os.OperationCanceledException} will be thrown when the
+ * query is executed.
+ * @param request A {@link FontRequest} object that identifies the provider and query for the
+ * request.
+ *
+ * @return {@link FontFamilyResult}
+ *
+ * @throws NameNotFoundException If requested package or authority was not found in system.
+ */
+ public static @NonNull FontFamilyResult fetchFonts(
+ @NonNull Context context, @Nullable CancellationSignal cancellationSignal,
+ @NonNull FontRequest request) throws NameNotFoundException {
+ ProviderInfo providerInfo = getProvider(context.getPackageManager(), request);
+ if (providerInfo == null) {
+ return new FontFamilyResult(FontFamilyResult.STATUS_WRONG_CERTIFICATES, null);
+
+ }
+ try {
+ FontInfo[] fonts = getFontFromProvider(
+ context, request, providerInfo.authority, cancellationSignal);
+ return new FontFamilyResult(FontFamilyResult.STATUS_OK, fonts);
+ } catch (InvalidFormatException e) {
+ return new FontFamilyResult(FontFamilyResult.STATUS_UNEXPECTED_DATA_PROVIDED, null);
+ }
+ }
+
+ /**
+ * Build a Typeface from an array of {@link FontInfo}. Results that are marked as not ready
+ * will be skipped.
+ *
+ * @param context A {@link Context} that will be used to fetch the font contents.
+ * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If
+ * the operation is canceled, then {@link
+ * android.os.OperationCanceledException} will be thrown.
+ * @param fonts An array of {@link FontInfo} to be used to create a Typeface.
+ * @param weight A weight value to be used for selecting a font from a font family.
+ * @param italic {@code true} if this font is of italic style. This will be used for font
+ * selection from a font family.
+ * @param fallbackFontName A fallback font name used if this method fails to create the
+ * Typeface. By passing {@code null}, this method returns {@code null}
+ * if typeface creation fails.
+ * @return A Typeface object. May return {@code null} if that is the value passed to {@code
+ * fallBackFontName}.
+ */
+ public static Typeface buildTypeface(@NonNull Context context,
+ @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts,
+ int weight, boolean italic, @Nullable String fallbackFontName) {
+ final Map<Uri, ByteBuffer> uriBuffer =
+ prepareFontData(context, fonts, cancellationSignal);
+ return new Typeface.Builder(fonts, uriBuffer)
+ .setFallback(fallbackFontName)
+ .setWeight(weight)
+ .setItalic(italic)
+ .build();
+ }
+
+ /**
+ * Build a Typeface from an array of {@link FontInfo}
+ *
+ * Results that are marked as not ready will be skipped.
+ *
+ * @param context A {@link Context} that will be used to fetch the font contents.
+ * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If
+ * the operation is canceled, then {@link
+ * android.os.OperationCanceledException} will be thrown.
+ * @param fonts An array of {@link FontInfo} to be used to create a Typeface.
+ * @return A Typeface object. Returns null if typeface creation fails.
+ */
+ public static Typeface buildTypeface(@NonNull Context context,
+ @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts) {
+ final Map<Uri, ByteBuffer> uriBuffer =
+ prepareFontData(context, fonts, cancellationSignal);
+ return new Typeface.Builder(fonts, uriBuffer).build();
+ }
+
+ /**
+ * A helper function to create a mapping from {@link Uri} to {@link ByteBuffer}.
+ *
+ * Skip if the file contents is not ready to be read.
+ *
+ * @param context A {@link Context} to be used for resolving content URI in
+ * {@link FontInfo}.
+ * @param fonts An array of {@link FontInfo}.
+ * @return A map from {@link Uri} to {@link ByteBuffer}.
+ */
+ private static Map<Uri, ByteBuffer> prepareFontData(Context context, FontInfo[] fonts,
+ CancellationSignal cancellationSignal) {
+ final HashMap<Uri, ByteBuffer> out = new HashMap<>();
+ final ContentResolver resolver = context.getContentResolver();
+
+ for (FontInfo font : fonts) {
+ if (font.getResultCode() != Columns.RESULT_CODE_OK) {
+ continue;
+ }
+
+ final Uri uri = font.getUri();
+ if (out.containsKey(uri)) {
+ continue;
+ }
+
+ ByteBuffer buffer = null;
+ try (final ParcelFileDescriptor pfd =
+ resolver.openFileDescriptor(uri, "r", cancellationSignal);
+ final FileInputStream fis = new FileInputStream(pfd.getFileDescriptor())) {
+ final FileChannel fileChannel = fis.getChannel();
+ final long size = fileChannel.size();
+ buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, size);
+ } catch (IOException e) {
+ // ignore
+ }
+
+ // TODO: try other approach?, e.g. read all contents instead of mmap.
+
+ out.put(uri, buffer);
+ }
+ return Collections.unmodifiableMap(out);
+ }
+
/** @hide */
@VisibleForTesting
- public ProviderInfo getProvider(FontRequest request, ResultReceiver receiver) {
+ public static @Nullable ProviderInfo getProvider(
+ PackageManager packageManager, FontRequest request) throws NameNotFoundException {
String providerAuthority = request.getProviderAuthority();
- ProviderInfo info = mPackageManager.resolveContentProvider(providerAuthority, 0);
+ ProviderInfo info = packageManager.resolveContentProvider(providerAuthority, 0);
if (info == null) {
- Log.e(TAG, "Can't find content provider " + providerAuthority);
- receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
- return null;
+ throw new NameNotFoundException("No package found for authority: " + providerAuthority);
}
if (!info.packageName.equals(request.getProviderPackage())) {
- Log.e(TAG, "Found content provider " + providerAuthority + ", but package was not "
- + request.getProviderPackage());
- receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
- return null;
+ throw new NameNotFoundException("Found content provider " + providerAuthority
+ + ", but package was not " + request.getProviderPackage());
}
// Trust system apps without signature checks
if (info.applicationInfo.isSystemApp()) {
@@ -221,16 +681,11 @@
}
List<byte[]> signatures;
- try {
- PackageInfo packageInfo = mPackageManager.getPackageInfo(info.packageName,
- PackageManager.GET_SIGNATURES);
- signatures = convertToByteArrayList(packageInfo.signatures);
- Collections.sort(signatures, sByteArrayComparator);
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG, "Can't find content provider " + providerAuthority, e);
- receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
- return null;
- }
+ PackageInfo packageInfo = packageManager.getPackageInfo(info.packageName,
+ PackageManager.GET_SIGNATURES);
+ signatures = convertToByteArrayList(packageInfo.signatures);
+ Collections.sort(signatures, sByteArrayComparator);
+
List<List<byte[]>> requestCertificatesList = request.getCertificates();
for (int i = 0; i < requestCertificatesList.size(); ++i) {
// Make a copy so we can sort it without modifying the incoming data.
@@ -240,8 +695,6 @@
return info;
}
}
- Log.e(TAG, "Certificates don't match for given provider " + providerAuthority);
- receiver.send(RESULT_CODE_WRONG_CERTIFICATES, null);
return null;
}
@@ -257,7 +710,8 @@
return 0;
};
- private boolean equalsByteArrayList(List<byte[]> signatures, List<byte[]> requestSignatures) {
+ private static boolean equalsByteArrayList(
+ List<byte[]> signatures, List<byte[]> requestSignatures) {
if (signatures.size() != requestSignatures.size()) {
return false;
}
@@ -269,7 +723,7 @@
return true;
}
- private List<byte[]> convertToByteArrayList(Signature[] signatures) {
+ private static List<byte[]> convertToByteArrayList(Signature[] signatures) {
List<byte[]> shas = new ArrayList<>();
for (int i = 0; i < signatures.length; ++i) {
shas.add(signatures[i].toByteArray());
@@ -279,84 +733,70 @@
/** @hide */
@VisibleForTesting
- public void getFontFromProvider(FontRequest request, ResultReceiver receiver,
- String authority) {
- ArrayList<FontResult> result = null;
- Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+ public static @NonNull FontInfo[] getFontFromProvider(
+ Context context, FontRequest request, String authority,
+ CancellationSignal cancellationSignal) throws InvalidFormatException {
+ ArrayList<FontInfo> result = new ArrayList<>();
+ final Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
.authority(authority)
.build();
- try (Cursor cursor = mContext.getContentResolver().query(uri, new String[] { Columns._ID,
- Columns.TTC_INDEX, Columns.VARIATION_SETTINGS, Columns.STYLE,
- Columns.WEIGHT, Columns.ITALIC, Columns.RESULT_CODE },
- "query = ?", new String[] { request.getQuery() }, null);) {
+ final Uri fileBaseUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(authority)
+ .appendPath("file")
+ .build();
+ try (Cursor cursor = context.getContentResolver().query(uri, new String[] { Columns._ID,
+ Columns.FILE_ID, Columns.TTC_INDEX, Columns.VARIATION_SETTINGS,
+ Columns.STYLE, Columns.WEIGHT, Columns.ITALIC, Columns.RESULT_CODE },
+ "query = ?", new String[] { request.getQuery() }, null, cancellationSignal);) {
// TODO: Should we restrict the amount of fonts that can be returned?
// TODO: Write documentation explaining that all results should be from the same family.
if (cursor != null && cursor.getCount() > 0) {
final int resultCodeColumnIndex = cursor.getColumnIndex(Columns.RESULT_CODE);
- int resultCode = -1;
result = new ArrayList<>();
final int idColumnIndex = cursor.getColumnIndexOrThrow(Columns._ID);
+ final int fileIdColumnIndex = cursor.getColumnIndex(Columns.FILE_ID);
final int ttcIndexColumnIndex = cursor.getColumnIndex(Columns.TTC_INDEX);
final int vsColumnIndex = cursor.getColumnIndex(Columns.VARIATION_SETTINGS);
final int weightColumnIndex = cursor.getColumnIndex(Columns.WEIGHT);
final int italicColumnIndex = cursor.getColumnIndex(Columns.ITALIC);
final int styleColumnIndex = cursor.getColumnIndex(Columns.STYLE);
while (cursor.moveToNext()) {
- resultCode = resultCodeColumnIndex != -1
+ int resultCode = resultCodeColumnIndex != -1
? cursor.getInt(resultCodeColumnIndex) : Columns.RESULT_CODE_OK;
- if (resultCode != Columns.RESULT_CODE_OK) {
- if (resultCode < 0) {
- // Negative values are reserved for the internal errors.
- resultCode = Columns.RESULT_CODE_FONT_NOT_FOUND;
- }
- for (int i = 0; i < result.size(); ++i) {
- try {
- result.get(i).getFileDescriptor().close();
- } catch (IOException e) {
- // Ignore, as we are closing fds for cleanup.
- }
- }
- receiver.send(resultCode, null);
- return;
+ final int ttcIndex = ttcIndexColumnIndex != -1
+ ? cursor.getInt(ttcIndexColumnIndex) : 0;
+ final String variationSettings = vsColumnIndex != -1
+ ? cursor.getString(vsColumnIndex) : null;
+
+ Uri fileUri;
+ if (fileIdColumnIndex == -1) {
+ long id = cursor.getLong(idColumnIndex);
+ fileUri = ContentUris.withAppendedId(uri, id);
+ } else {
+ long id = cursor.getLong(fileIdColumnIndex);
+ fileUri = ContentUris.withAppendedId(fileBaseUri, id);
}
- long id = cursor.getLong(idColumnIndex);
- Uri fileUri = ContentUris.withAppendedId(uri, id);
- try {
- ParcelFileDescriptor pfd =
- mContext.getContentResolver().openFileDescriptor(fileUri, "r");
- final int ttcIndex = ttcIndexColumnIndex != -1
- ? cursor.getInt(ttcIndexColumnIndex) : 0;
- final String variationSettings = vsColumnIndex != -1
- ? cursor.getString(vsColumnIndex) : null;
- // TODO: Stop using STYLE column and enforce WEIGHT/ITALIC column.
- int weight;
- boolean italic;
- if (weightColumnIndex != -1 && italicColumnIndex != -1) {
- weight = cursor.getInt(weightColumnIndex);
- italic = cursor.getInt(italicColumnIndex) == 1;
- } else if (styleColumnIndex != -1) {
- final int style = cursor.getInt(styleColumnIndex);
- weight = (style & Typeface.BOLD) != 0 ? 700 : 400;
- italic = (style & Typeface.ITALIC) != 0;
- } else {
- weight = 400;
- italic = false;
- }
- result.add(
- new FontResult(pfd, ttcIndex, variationSettings, weight, italic));
- } catch (FileNotFoundException e) {
- Log.e(TAG, "FileNotFoundException raised when interacting with content "
- + "provider " + authority, e);
+ // TODO: Stop using STYLE column and enforce WEIGHT/ITALIC column.
+ int weight;
+ boolean italic;
+ if (weightColumnIndex != -1 && italicColumnIndex != -1) {
+ weight = cursor.getInt(weightColumnIndex);
+ italic = cursor.getInt(italicColumnIndex) == 1;
+ } else if (styleColumnIndex != -1) {
+ final int style = cursor.getInt(styleColumnIndex);
+ weight = (style & Typeface.BOLD) != 0 ?
+ Typeface.Builder.BOLD_WEIGHT : Typeface.Builder.NORMAL_WEIGHT;
+ italic = (style & Typeface.ITALIC) != 0;
+ } else {
+ weight = Typeface.Builder.NORMAL_WEIGHT;
+ italic = false;
}
+ FontVariationAxis[] axes =
+ FontVariationAxis.fromFontVariationSettings(variationSettings);
+ result.add(new FontInfo(fileUri, ttcIndex, axes, weight, italic, resultCode));
}
}
}
- if (result != null && !result.isEmpty()) {
- Bundle bundle = new Bundle();
- bundle.putParcelableArrayList(PARCEL_FONT_RESULTS, result);
- receiver.send(Columns.RESULT_CODE_OK, bundle);
- return;
- }
- receiver.send(Columns.RESULT_CODE_FONT_NOT_FOUND, null);
+ return result.toArray(new FontInfo[0]);
}
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index cac643fc..539559d 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -302,8 +302,8 @@
* Output: Nothing.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_MANAGE_EXTERNAL_SOURCES =
- "android.settings.action.MANAGE_EXTERNAL_SOURCES";
+ public static final String ACTION_MANAGE_UNKNOWN_APP_SOURCES =
+ "android.settings.action.MANAGE_UNKNOWN_APP_SOURCES";
/**
* Activity Action: Show trusted credentials settings, opening to the user tab,
@@ -3150,6 +3150,13 @@
public static final String VOLUME_BLUETOOTH_SCO = "volume_bluetooth_sco";
/**
+ * @hide
+ * Acessibility volume. This is used internally, changing this
+ * value will not change the volume.
+ */
+ public static final String VOLUME_ACCESSIBILITY = "volume_a11y";
+
+ /**
* Master volume (float in the range 0.0f to 1.0f).
*
* @hide
@@ -3212,6 +3219,22 @@
};
/**
+ * @hide
+ * The mapping of stream type (integer) to its setting.
+ * Unlike the VOLUME_SETTINGS array, this one contains as many entries as
+ * AudioSystem.NUM_STREAM_TYPES, and has empty strings for stream types whose volumes
+ * are never persisted.
+ */
+ public static final String[] VOLUME_SETTINGS_INT = {
+ VOLUME_VOICE, VOLUME_SYSTEM, VOLUME_RING, VOLUME_MUSIC,
+ VOLUME_ALARM, VOLUME_NOTIFICATION, VOLUME_BLUETOOTH_SCO,
+ "" /*STREAM_SYSTEM_ENFORCED, no setting for this stream*/,
+ "" /*STREAM_DTMF, no setting for this stream*/,
+ "" /*STREAM_TTS, no setting for this stream*/,
+ VOLUME_ACCESSIBILITY
+ };
+
+ /**
* Appended to various volume related settings to record the previous
* values before they the settings were affected by a silent/vibrate
* ringer mode change.
@@ -4125,6 +4148,7 @@
INSTANT_APP_SETTINGS.add(HAPTIC_FEEDBACK_ENABLED);
INSTANT_APP_SETTINGS.add(TIME_12_24);
INSTANT_APP_SETTINGS.add(SOUND_EFFECTS_ENABLED);
+ INSTANT_APP_SETTINGS.add(ACCELEROMETER_ROTATION);
}
/**
@@ -6922,7 +6946,8 @@
*
* @hide
*/
- public static final String WEB_ACTION_ENABLED = "web_action_enabled";
+ @SystemApi
+ public static final String INSTANT_APPS_ENABLED = "instant_apps_enabled";
/**
* Has this pairable device been paired or upgraded from a previously paired system.
@@ -7093,6 +7118,7 @@
INSTANT_APP_SETTINGS.add(ANDROID_ID);
INSTANT_APP_SETTINGS.add(PACKAGE_VERIFIER_USER_CONSENT);
+ INSTANT_APP_SETTINGS.add(ALLOW_MOCK_LOCATION);
}
/**
@@ -8818,6 +8844,15 @@
public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
/**
+ * A comma separated list of URLs used for captive portal detection in addition to the
+ * fallback HTTP url associated with the CAPTIVE_PORTAL_FALLBACK_URL settings.
+ *
+ * @hide
+ */
+ public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS =
+ "captive_portal_other_fallback_urls";
+
+ /**
* Whether to use HTTPS for network validation. This is enabled by default and the setting
* needs to be set to 0 to disable it. This setting is a misnomer because captive portals
* don't actually use HTTPS, but it's consistent with the other settings.
@@ -10330,6 +10365,7 @@
INSTANT_APP_SETTINGS.add(TRANSITION_ANIMATION_SCALE);
INSTANT_APP_SETTINGS.add(ANIMATOR_DURATION_SCALE);
INSTANT_APP_SETTINGS.add(DEBUG_VIEW_ATTRIBUTES);
+ INSTANT_APP_SETTINGS.add(WTF_IS_FATAL);
}
/**
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index c82b9eb..a4d3fb2 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -94,9 +94,9 @@
private final IAutoFillService mInterface = new IAutoFillService.Stub() {
@Override
- public void onInit(IAutoFillServiceConnection connection) {
- if (connection != null) {
- mHandlerCaller.obtainMessageO(MSG_CONNECT, connection).sendToTarget();
+ public void onConnectedStateChanged(boolean connected) {
+ if (connected) {
+ mHandlerCaller.obtainMessage(MSG_CONNECT).sendToTarget();
} else {
mHandlerCaller.obtainMessage(MSG_DISCONNECT).sendToTarget();
}
@@ -127,7 +127,6 @@
private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
switch (msg.what) {
case MSG_CONNECT: {
- mConnection = (IAutoFillServiceConnection) msg.obj;
onConnected();
break;
} case MSG_ON_FILL_REQUEST: {
@@ -152,7 +151,6 @@
break;
} case MSG_DISCONNECT: {
onDisconnected();
- mConnection = null;
break;
} default: {
Log.w(TAG, "MyCallbacks received invalid message type: " + msg);
@@ -162,8 +160,6 @@
private HandlerCaller mHandlerCaller;
- private IAutoFillServiceConnection mConnection;
-
/**
* {@inheritDoc}
*
@@ -246,21 +242,9 @@
public void onDisconnected() {
}
- /**
- * Disables the service. After calling this method, the service will
- * be disabled and settings will show that it is turned off.
- *
- * <p>You should call this method only after a call to {@link #onConnected()}
- * and before the corresponding call to {@link #onDisconnected()}. In other words
- * you can disable your service only while the system is connected to it.</p>
- */
+ @Deprecated
public final void disableSelf() {
- if (mConnection != null) {
- try {
- mConnection.disableSelf();
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- }
+ // TODO(b/33197203): Remove when GCore has migrated off this API
+ getSystemService(AutofillManager.class).disableOwnedAutofillServices();
}
}
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index 3117f98..eab0d4c 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -309,7 +309,6 @@
return this;
}
-
/**
* Builds a new {@link FillResponse} instance. You must provide at least
* one dataset or some savable ids or an authentication with a presentation
diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl
index 9f296c6..a8d86ca 100644
--- a/core/java/android/service/autofill/IAutoFillService.aidl
+++ b/core/java/android/service/autofill/IAutoFillService.aidl
@@ -18,7 +18,6 @@
import android.app.assist.AssistStructure;
import android.os.Bundle;
-import android.service.autofill.IAutoFillServiceConnection;
import android.service.autofill.IFillCallback;
import android.service.autofill.ISaveCallback;
import com.android.internal.os.IResultReceiver;
@@ -29,7 +28,7 @@
* @hide
*/
oneway interface IAutoFillService {
- void onInit(in IAutoFillServiceConnection connection);
+ void onConnectedStateChanged(boolean connected);
void onFillRequest(in AssistStructure structure, in Bundle extras,
in IFillCallback callback, int flags);
void onSaveRequest(in AssistStructure structure, in Bundle extras,
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 94505d3..6a15ade 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -462,7 +462,7 @@
* @return The view if found or null otherwise.
*/
@Nullable
- public View findViewById(@IdRes int id) {
+ public <T extends View> T findViewById(@IdRes int id) {
return getWindow().findViewById(id);
}
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index b26e328..dc1a70d 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -16,6 +16,8 @@
package android.service.notification;
+import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
import android.service.notification.IStatusBarNotificationHolder;
import android.service.notification.StatusBarNotification;
import android.service.notification.NotificationRankingUpdate;
@@ -33,6 +35,10 @@
void onListenerHintsChanged(int hints);
void onInterruptionFilterChanged(int interruptionFilter);
+ // companion device managers only
+ void onNotificationChannelModification(String pkgName, in NotificationChannel channel, int modificationType);
+ void onNotificationChannelGroupModification(String pkgName, in NotificationChannelGroup group, int modificationType);
+
// rankers only
void onNotificationEnqueued(in IStatusBarNotificationHolder notificationHolder);
void onNotificationSnoozedUntilContext(in IStatusBarNotificationHolder notificationHolder, String snoozeCriterionId);
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 6ec9d69..d94017c 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -138,7 +138,6 @@
}
}
-
private class NotificationAssistantServiceWrapper extends NotificationListenerWrapper {
@Override
public void onNotificationEnqueued(IStatusBarNotificationHolder sbnHolder) {
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index f55c7cf..4833be3 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -16,8 +16,13 @@
package android.service.notification;
+import android.Manifest;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.TestApi;
import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
+import android.companion.CompanionDeviceManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -51,6 +56,8 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.SomeArgs;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -59,7 +66,7 @@
* A service that receives calls from the system when new notifications are
* posted or removed, or their ranking changed.
* <p>To extend this class, you must declare the service in your manifest file with
- * the {@link android.Manifest.permission#BIND_NOTIFICATION_LISTENER_SERVICE} permission
+ * the {@link Manifest.permission#BIND_NOTIFICATION_LISTENER_SERVICE} permission
* and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
* <pre>
* <service android:name=".NotificationListener"
@@ -215,6 +222,37 @@
@SystemApi
public static final int TRIM_LIGHT = 1;
+
+ /** @hide */
+ @IntDef({NOTIFICATION_CHANNEL_OR_GROUP_ADDED, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED,
+ NOTIFICATION_CHANNEL_OR_GROUP_DELETED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ChannelOrGroupModificationTypes {}
+
+ /**
+ * Channel or group modification reason provided to
+ * {@link #onNotificationChannelModified(String, NotificationChannel, int)} or
+ * {@link #onNotificationChannelGroupModified(String, NotificationChannelGroup, int)}- the
+ * provided object was created.
+ */
+ public static final int NOTIFICATION_CHANNEL_OR_GROUP_ADDED = 1;
+
+ /**
+ * Channel or group modification reason provided to
+ * {@link #onNotificationChannelModified(String, NotificationChannel, int)} or
+ * {@link #onNotificationChannelGroupModified(String, NotificationChannelGroup, int)}- the
+ * provided object was updated.
+ */
+ public static final int NOTIFICATION_CHANNEL_OR_GROUP_UPDATED = 2;
+
+ /**
+ * Channel or group modification reason provided to
+ * {@link #onNotificationChannelModified(String, NotificationChannel, int)} or
+ * {@link #onNotificationChannelGroupModified(String, NotificationChannelGroup, int)}- the
+ * provided object was deleted.
+ */
+ public static final int NOTIFICATION_CHANNEL_OR_GROUP_DELETED = 3;
+
private final Object mLock = new Object();
private Handler mHandler;
@@ -388,6 +426,40 @@
}
/**
+ * Implement this method to learn about notification channel modifications.
+ *
+ * <p>The caller must have {@link CompanionDeviceManager#getAssociations() an associated
+ * device} in order to receive this callback.
+ *
+ * @param pkg The package the channel belongs to.
+ * @param channel The channel that has changed.
+ * @param modificationType One of {@link #NOTIFICATION_CHANNEL_OR_GROUP_ADDED},
+ * {@link #NOTIFICATION_CHANNEL_OR_GROUP_UPDATED},
+ * {@link #NOTIFICATION_CHANNEL_OR_GROUP_DELETED}.
+ */
+ public void onNotificationChannelModified(String pkg, NotificationChannel channel,
+ @ChannelOrGroupModificationTypes int modificationType) {
+ // optional
+ }
+
+ /**
+ * Implement this method to learn about notification channel group modifications.
+ *
+ * <p>The caller must have {@link CompanionDeviceManager#getAssociations() an associated
+ * device} in order to receive this callback.
+ *
+ * @param pkg The package the group belongs to.
+ * @param group The group that has changed.
+ * @param modificationType One of {@link #NOTIFICATION_CHANNEL_OR_GROUP_ADDED},
+ * {@link #NOTIFICATION_CHANNEL_OR_GROUP_UPDATED},
+ * {@link #NOTIFICATION_CHANNEL_OR_GROUP_DELETED}.
+ */
+ public void onNotificationChannelGroupModified(String pkg, NotificationChannelGroup group,
+ @ChannelOrGroupModificationTypes int modificationType) {
+ // optional
+ }
+
+ /**
* Implement this method to be notified when the
* {@link #getCurrentInterruptionFilter() interruption filter} changed.
*
@@ -587,6 +659,69 @@
}
}
+
+ /**
+ * Updates a notification channel for a given package. This should only be used to reflect
+ * changes a user has made to the channel via the listener's user interface.
+ *
+ * <p>The caller must have {@link CompanionDeviceManager#getAssociations() an associated
+ * device} in order to use this method.
+ *
+ * @param pkg The package the channel belongs to.
+ * @param channel the channel to update.
+ */
+ public final void updateNotificationChannel(@NonNull String pkg,
+ @NonNull NotificationChannel channel) {
+ if (!isBound()) return;
+ try {
+ getNotificationInterface().updateNotificationChannelFromPrivilegedListener(
+ mWrapper, pkg, channel);
+ } catch (RemoteException e) {
+ Log.v(TAG, "Unable to contact notification manager", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns all notification channels belonging to the given package.
+ *
+ * <p>The caller must have {@link CompanionDeviceManager#getAssociations() an associated
+ * device} in order to use this method.
+ *
+ * @param pkg The package to retrieve channels for.
+ */
+ public final List<NotificationChannel> getNotificationChannels(@NonNull String pkg) {
+ if (!isBound()) return null;
+ try {
+
+ return getNotificationInterface().getNotificationChannelsFromPrivilegedListener(
+ mWrapper, pkg).getList();
+ } catch (RemoteException e) {
+ Log.v(TAG, "Unable to contact notification manager", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns all notification channel groups belonging to the given package.
+ *
+ * <p>The caller must have {@link CompanionDeviceManager#getAssociations() an associated
+ * device} in order to use this method.
+ *
+ * @param pkg The package to retrieve channel groups for.
+ */
+ public final List<NotificationChannelGroup> getNotificationChannelGroups(@NonNull String pkg) {
+ if (!isBound()) return null;
+ try {
+
+ return getNotificationInterface().getNotificationChannelGroupsFromPrivilegedListener(
+ mWrapper, pkg).getList();
+ } catch (RemoteException e) {
+ Log.v(TAG, "Unable to contact notification manager", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/**
* Sets the notification trim that will be received via {@link #onNotificationPosted}.
*
@@ -1116,6 +1251,28 @@
// no-op in the listener
}
+ @Override
+ public void onNotificationChannelModification(String pkgName, NotificationChannel channel,
+ @ChannelOrGroupModificationTypes int modificationType) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = pkgName;
+ args.arg2 = channel;
+ args.arg3 = modificationType;
+ mHandler.obtainMessage(
+ MyHandler.MSG_ON_NOTIFICATION_CHANNEL_MODIFIED, args).sendToTarget();
+ }
+
+ @Override
+ public void onNotificationChannelGroupModification(String pkgName,
+ NotificationChannelGroup group,
+ @ChannelOrGroupModificationTypes int modificationType) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = pkgName;
+ args.arg2 = group;
+ args.arg3 = modificationType;
+ mHandler.obtainMessage(
+ MyHandler.MSG_ON_NOTIFICATION_CHANNEL_GROUP_MODIFIED, args).sendToTarget();
+ }
}
/**
@@ -1632,6 +1789,8 @@
public static final int MSG_ON_NOTIFICATION_RANKING_UPDATE = 4;
public static final int MSG_ON_LISTENER_HINTS_CHANGED = 5;
public static final int MSG_ON_INTERRUPTION_FILTER_CHANGED = 6;
+ public static final int MSG_ON_NOTIFICATION_CHANNEL_MODIFIED = 7;
+ public static final int MSG_ON_NOTIFICATION_CHANNEL_GROUP_MODIFIED = 8;
public MyHandler(Looper looper) {
super(looper, null, false);
@@ -1678,6 +1837,22 @@
final int interruptionFilter = msg.arg1;
onInterruptionFilterChanged(interruptionFilter);
} break;
+
+ case MSG_ON_NOTIFICATION_CHANNEL_MODIFIED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ String pkgName = (String) args.arg1;
+ NotificationChannel channel = (NotificationChannel) args.arg2;
+ int modificationType = (int) args.arg3;
+ onNotificationChannelModified(pkgName, channel, modificationType);
+ } break;
+
+ case MSG_ON_NOTIFICATION_CHANNEL_GROUP_MODIFIED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ String pkgName = (String) args.arg1;
+ NotificationChannelGroup group = (NotificationChannelGroup) args.arg2;
+ int modificationType = (int) args.arg3;
+ onNotificationChannelGroupModified(pkgName, group, modificationType);
+ } break;
}
}
}
diff --git a/core/java/android/service/autofill/IAutoFillServiceConnection.aidl b/core/java/android/service/oemlock/IOemLockService.aidl
similarity index 65%
copy from core/java/android/service/autofill/IAutoFillServiceConnection.aidl
copy to core/java/android/service/oemlock/IOemLockService.aidl
index cf73a10..2c606f9 100644
--- a/core/java/android/service/autofill/IAutoFillServiceConnection.aidl
+++ b/core/java/android/service/oemlock/IOemLockService.aidl
@@ -14,13 +14,17 @@
* limitations under the License.
*/
-package android.service.autofill;
+package android.service.oemlock;
/**
- * Interface from an auto fill service to the system.
+ * Interface for communication with the OemLockService.
*
* @hide
*/
-interface IAutoFillServiceConnection {
- void disableSelf();
+interface IOemLockService {
+ void setOemUnlockAllowedByCarrier(boolean allowed, in byte[] signature);
+ boolean isOemUnlockAllowedByCarrier();
+
+ void setOemUnlockAllowedByUser(boolean allowed);
+ boolean isOemUnlockAllowedByUser();
}
diff --git a/core/java/android/service/oemlock/OemLockManager.java b/core/java/android/service/oemlock/OemLockManager.java
new file mode 100644
index 0000000..c4fbe5e
--- /dev/null
+++ b/core/java/android/service/oemlock/OemLockManager.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.oemlock;
+
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.RemoteException;
+
+/**
+ * Interface for managing the OEM lock on the device.
+ *
+ * This will only be available if the device implements OEM lock protection.
+ *
+ * Multiple actors have an opinion on whether the device can be OEM unlocked and they must all be in
+ * agreement for unlock to be possible.
+ *
+ * @hide
+ */
+@SystemApi
+public class OemLockManager {
+ private IOemLockService mService;
+
+ /** @hide */
+ public OemLockManager(IOemLockService service) {
+ mService = service;
+ }
+
+ /**
+ * Sets whether the carrier has allowed this device to be OEM unlocked.
+ *
+ * Depending on the implementation, the validity of the request might need to be proved. This
+ * can be acheived by passing a signature that the system will use to verify the request is
+ * legitimate.
+ *
+ * All actors involved must agree for OEM unlock to be possible.
+ *
+ * @param allowed Whether the device should be allowed to be unlocked.
+ * @param signature Optional proof of request validity, {@code null} for none.
+ * @throws IllegalArgumentException if a signature is required but was not provided.
+ * @throws SecurityException if the wrong signature was provided.
+ *
+ * @see #isOemUnlockAllowedByCarrier()
+ */
+ public void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
+ try {
+ mService.setOemUnlockAllowedByCarrier(allowed, signature);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns whether the carrier has allowed this device to be OEM unlocked.
+ * @return Whether OEM unlock is allowed by the carrier, or true if no OEM lock is present.
+ *
+ * @see #setOemUnlockAllowedByCarrier(boolean, byte[])
+ */
+ public boolean isOemUnlockAllowedByCarrier() {
+ try {
+ return mService.isOemUnlockAllowedByCarrier();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Sets whether the user has allowed this device to be unlocked.
+ *
+ * All actors involved must agree for OEM unlock to be possible.
+ *
+ * @param unlocked Whether the device should be made OEM unlocked.
+ *
+ * @see #isOemUnlockAllowedByUser()
+ */
+ public void setOemUnlockAllowedByUser(boolean allowed) {
+ try {
+ mService.setOemUnlockAllowedByUser(allowed);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns whether, or not, the user has allowed this device to be OEM unlocked.
+ * @return Whether OEM unlock is allowed by the user, or true if no OEM lock is present.
+ *
+ * @see #setOemUnlockAllowedByUser(boolean)
+ */
+ public boolean isOemUnlockAllowedByUser() {
+ try {
+ return mService.isOemUnlockAllowedByUser();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+}
diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
index cb021bc..326796a 100644
--- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java
+++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
@@ -146,6 +146,8 @@
/**
* Writes a byte enabling or disabling the ability to "OEM unlock" the device.
+ *
+ * @deprecated use {@link OemLockManager#setOemUnlockAllowedByUser(boolean)} instead.
*/
public void setOemUnlockEnabled(boolean enabled) {
try {
@@ -157,6 +159,8 @@
/**
* Returns whether or not "OEM unlock" is enabled or disabled on this device.
+ *
+ * @deprecated use {@link OemLockManager#isOemUnlockAllowedByUser()} instead.
*/
public boolean getOemUnlockEnabled() {
try {
diff --git a/core/java/android/speech/tts/SynthesisCallback.java b/core/java/android/speech/tts/SynthesisCallback.java
index e535cfa..f5e5f4d 100644
--- a/core/java/android/speech/tts/SynthesisCallback.java
+++ b/core/java/android/speech/tts/SynthesisCallback.java
@@ -151,6 +151,9 @@
* listener ({@link UtteranceProgressListener#onRangeStart}) at the moment that frame has been
* reached by the playback head.
*
+ * <p>This information can be used by the client, for example, to highlight ranges of the text
+ * while it is spoken.
+ *
* <p>The markerInFrames is a frame index into the audio for this synthesis request, i.e. into
* the concatenation of the audio bytes sent to audioAvailable for this synthesis request. The
* definition of a frame depends on the format given by {@link #start}. See {@link AudioFormat}
diff --git a/core/java/android/speech/tts/UtteranceProgressListener.java b/core/java/android/speech/tts/UtteranceProgressListener.java
index 59ee8f3..ef81f12 100644
--- a/core/java/android/speech/tts/UtteranceProgressListener.java
+++ b/core/java/android/speech/tts/UtteranceProgressListener.java
@@ -128,6 +128,9 @@
* <p>This method is called when the audio is expected to start playing on the speaker. Note
* that this is different from {@link #onAudioAvailable} which is called as soon as the audio is
* generated.
+
+ * <p>This information can be used, for example, to highlight ranges of the text while it is
+ * spoken.
*
* <p>Only called if the engine supplies timing information by calling {@link
* SynthesisCallback#rangeStart(int, int, int)}.
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java
index 8537d8f..ed58390 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -23,8 +23,6 @@
import android.annotation.Nullable;
import android.graphics.fonts.FontVariationAxis;
import android.net.Uri;
-import android.os.Parcel;
-import android.os.Parcelable;
import java.lang.annotation.Retention;
@@ -33,7 +31,7 @@
* Font configuration descriptions for System fonts.
* @hide
*/
-public final class FontConfig implements Parcelable {
+public final class FontConfig {
private final @NonNull Family[] mFamilies;
private final @NonNull Alias[] mAliases;
@@ -57,37 +55,9 @@
}
/**
- * @hide
- */
- public FontConfig(Parcel in) {
- mFamilies = in.readTypedArray(Family.CREATOR);
- mAliases = in.readTypedArray(Alias.CREATOR);
- }
-
- @Override
- public void writeToParcel(Parcel out, int flag) {
- out.writeTypedArray(mFamilies, flag);
- out.writeTypedArray(mAliases, flag);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<FontConfig> CREATOR = new Parcelable.Creator() {
- public FontConfig createFromParcel(Parcel in) {
- return new FontConfig(in);
- }
- public FontConfig[] newArray(int size) {
- return new FontConfig[size];
- }
- };
-
- /**
* Class that holds information about a Font.
*/
- public static final class Font implements Parcelable {
+ public static final class Font {
private final @NonNull String mFontName;
private final int mTtcIndex;
private final @NonNull FontVariationAxis[] mAxes;
@@ -152,57 +122,15 @@
return mUri;
}
- /**
- * @hide
- */
public void setUri(@NonNull Uri uri) {
mUri = uri;
}
-
- /**
- * @hide
- */
- public Font(Parcel in) {
- mFontName = in.readString();
- mTtcIndex = in.readInt();
- mAxes = in.createTypedArray(FontVariationAxis.CREATOR);
- mWeight = in.readInt();
- mIsItalic = in.readInt() == 1;
- mUri = in.readTypedObject(Uri.CREATOR);
- }
-
- @Override
- public void writeToParcel(Parcel out, int flag) {
- out.writeString(mFontName);
- out.writeInt(mTtcIndex);
- out.writeTypedArray(mAxes, flag);
- out.writeInt(mWeight);
- out.writeInt(mIsItalic ? 1 : 0);
- out.writeTypedObject(mUri, flag);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Creator<Font> CREATOR = new Creator<Font>() {
- @Override
- public Font createFromParcel(Parcel in) {
- return new Font(in);
- }
-
- @Override
- public Font[] newArray(int size) {
- return new Font[size];
- }
- };
}
/**
* Class that holds information about a Font alias.
*/
- public static final class Alias implements Parcelable {
+ public static final class Alias {
private final @NonNull String mName;
private final @NonNull String mToName;
private final int mWeight;
@@ -233,45 +161,12 @@
public int getWeight() {
return mWeight;
}
-
- /**
- * @hide
- */
- public Alias(Parcel in) {
- mName = in.readString();
- mToName = in.readString();
- mWeight = in.readInt();
- }
-
- @Override
- public void writeToParcel(Parcel out, int flag) {
- out.writeString(mName);
- out.writeString(mToName);
- out.writeInt(mWeight);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Creator<Alias> CREATOR = new Creator<Alias>() {
- @Override
- public Alias createFromParcel(Parcel in) {
- return new Alias(in);
- }
-
- @Override
- public Alias[] newArray(int size) {
- return new Alias[size];
- }
- };
}
/**
* Class that holds information about a Font family.
*/
- public static final class Family implements Parcelable {
+ public static final class Family {
private final @NonNull String mName;
private final @NonNull Font[] mFonts;
private final @NonNull String mLanguage;
@@ -343,40 +238,5 @@
public @Variant int getVariant() {
return mVariant;
}
-
- /**
- * @hide
- */
- public Family(Parcel in) {
- mName = in.readString();
- mFonts = in.readTypedArray(Font.CREATOR);
- mLanguage = in.readString();
- mVariant = in.readInt();
- }
-
- @Override
- public void writeToParcel(Parcel out, int flag) {
- out.writeString(mName);
- out.writeTypedArray(mFonts, flag);
- out.writeString(mLanguage);
- out.writeInt(mVariant);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Creator<Family> CREATOR = new Creator<Family>() {
- @Override
- public Family createFromParcel(Parcel in) {
- return new Family(in);
- }
-
- @Override
- public Family[] newArray(int size) {
- return new Family[size];
- }
- };
}
}
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index b47fce8..a233ba1 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1030,24 +1030,17 @@
* the paragraph's primary direction.
*/
public float getPrimaryHorizontal(int offset) {
- return getPrimaryHorizontal(offset, false /* not clamped */,
- true /* getNewLineStartPosOnLineBreak */);
+ return getPrimaryHorizontal(offset, false /* not clamped */);
}
/**
* Get the primary horizontal position for the specified text offset, but
* optionally clamp it so that it doesn't exceed the width of the layout.
- *
- * @param offset the offset to get horizontal position
- * @param clamped whether to clamp the position by using the width of this layout.
- * @param getNewLineStartPosOnLineBreak whether to get the start position of new line when the
- * offset is at automatic line break.
* @hide
*/
- public float getPrimaryHorizontal(int offset, boolean clamped,
- boolean getNewLineStartPosOnLineBreak) {
+ public float getPrimaryHorizontal(int offset, boolean clamped) {
boolean trailing = primaryIsTrailingPrevious(offset);
- return getHorizontal(offset, trailing, clamped, getNewLineStartPosOnLineBreak);
+ return getHorizontal(offset, trailing, clamped);
}
/**
@@ -1056,37 +1049,26 @@
* the direction other than the paragraph's primary direction.
*/
public float getSecondaryHorizontal(int offset) {
- return getSecondaryHorizontal(offset, false /* not clamped */,
- true /* getNewLineStartPosOnLineBreak */);
+ return getSecondaryHorizontal(offset, false /* not clamped */);
}
/**
* Get the secondary horizontal position for the specified text offset, but
* optionally clamp it so that it doesn't exceed the width of the layout.
- *
- * @param offset the offset to get horizontal position
- * @param clamped whether to clamp the position by using the width of this layout.
- * @param getNewLineStartPosOnLineBreak whether to get the start position of new line when the
- * offset is at automatic line break.
* @hide
*/
- public float getSecondaryHorizontal(int offset, boolean clamped,
- boolean getNewLineStartPosOnLineBreak) {
+ public float getSecondaryHorizontal(int offset, boolean clamped) {
boolean trailing = primaryIsTrailingPrevious(offset);
- return getHorizontal(offset, !trailing, clamped, getNewLineStartPosOnLineBreak);
+ return getHorizontal(offset, !trailing, clamped);
}
- private float getHorizontal(int offset, boolean primary,
- boolean getNewLineStartPosOnLineBreak) {
- return primary ? getPrimaryHorizontal(offset, false /* not clamped */,
- getNewLineStartPosOnLineBreak)
- : getSecondaryHorizontal(offset, false /* not clamped */,
- getNewLineStartPosOnLineBreak);
+ private float getHorizontal(int offset, boolean primary) {
+ return primary ? getPrimaryHorizontal(offset) : getSecondaryHorizontal(offset);
}
- private float getHorizontal(int offset, boolean trailing, boolean clamped,
- boolean getNewLineStartPosOnLineBreak) {
- final int line = getLineForOffset(offset, getNewLineStartPosOnLineBreak);
+ private float getHorizontal(int offset, boolean trailing, boolean clamped) {
+ int line = getLineForOffset(offset);
+
return getHorizontal(offset, trailing, line, clamped);
}
@@ -1300,10 +1282,6 @@
* beyond the end of the text, you get the last line.
*/
public int getLineForOffset(int offset) {
- return getLineForOffset(offset, true);
- }
-
- private int getLineForOffset(int offset, boolean getNewLineOnLineBreak) {
int high = getLineCount(), low = -1, guess;
while (high - low > 1) {
@@ -1318,10 +1296,6 @@
if (low < 0) {
return 0;
} else {
- if (!getNewLineOnLineBreak && low > 0 && getLineStart(low) == offset
- && mText.charAt(offset - 1) != '\n') {
- return low - 1;
- }
return low;
}
}
@@ -1357,14 +1331,14 @@
false, null);
final int max;
- if (line != getLineCount() - 1 && mText.charAt(lineEndOffset - 1) == '\n') {
+ if (line == getLineCount() - 1) {
+ max = lineEndOffset;
+ } else {
max = tl.getOffsetToLeftRightOf(lineEndOffset - lineStartOffset,
!isRtlCharAt(lineEndOffset - 1)) + lineStartOffset;
- } else {
- max = lineEndOffset;
}
int best = lineStartOffset;
- float bestdist = Math.abs(getHorizontal(best, primary, true) - horiz);
+ float bestdist = Math.abs(getHorizontal(best, primary) - horiz);
for (int i = 0; i < dirs.mDirections.length; i += 2) {
int here = lineStartOffset + dirs.mDirections[i];
@@ -1380,9 +1354,7 @@
guess = (high + low) / 2;
int adguess = getOffsetAtStartOf(guess);
- if (getHorizontal(adguess, primary,
- adguess == lineStartOffset || adguess != lineEndOffset) * swap
- >= horiz * swap) {
+ if (getHorizontal(adguess, primary) * swap >= horiz * swap) {
high = guess;
} else {
low = guess;
@@ -1396,11 +1368,9 @@
int aft = tl.getOffsetToLeftRightOf(low - lineStartOffset, isRtl) + lineStartOffset;
low = tl.getOffsetToLeftRightOf(aft - lineStartOffset, !isRtl) + lineStartOffset;
if (low >= here && low < there) {
- float dist = Math.abs(getHorizontal(low, primary,
- low == lineStartOffset || low != lineEndOffset) - horiz);
+ float dist = Math.abs(getHorizontal(low, primary) - horiz);
if (aft < there) {
- float other = Math.abs(getHorizontal(aft, primary,
- aft == lineStartOffset || aft != lineEndOffset) - horiz);
+ float other = Math.abs(getHorizontal(aft, primary) - horiz);
if (other < dist) {
dist = other;
@@ -1415,8 +1385,7 @@
}
}
- float dist = Math.abs(getHorizontal(here, primary,
- here == lineStartOffset || here != lineEndOffset) - horiz);
+ float dist = Math.abs(getHorizontal(here, primary) - horiz);
if (dist < bestdist) {
bestdist = dist;
@@ -1424,10 +1393,10 @@
}
}
- float dist = Math.abs(getHorizontal(max, primary,
- max == lineStartOffset || max != lineEndOffset) - horiz);
+ float dist = Math.abs(getHorizontal(max, primary) - horiz);
if (dist <= bestdist) {
+ bestdist = dist;
best = max;
}
@@ -1621,9 +1590,8 @@
int bottom = getLineTop(line+1);
boolean clamped = shouldClampCursor(line);
- float h1 = getPrimaryHorizontal(point, clamped, true) - 0.5f;
- float h2 = isLevelBoundary(point)
- ? getSecondaryHorizontal(point, clamped, true) - 0.5f : h1;
+ float h1 = getPrimaryHorizontal(point, clamped) - 0.5f;
+ float h2 = isLevelBoundary(point) ? getSecondaryHorizontal(point, clamped) - 0.5f : h1;
int caps = TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SHIFT_ON) |
TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SELECTING);
@@ -1740,7 +1708,8 @@
}
int startline = getLineForOffset(start);
- int endline = getLineForOffset(end, false);
+ int endline = getLineForOffset(end);
+
int top = getLineTop(startline);
int bottom = getLineBottom(endline);
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 5f01f7b..d41dfdc 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -98,7 +98,7 @@
if (en > end - start)
en = end - start;
- setSpan(false, spans[i], st, en, fl);
+ setSpan(false, spans[i], st, en, fl, false/*enforceParagraph*/);
}
restoreInvariants();
}
@@ -355,7 +355,8 @@
}
if (spanStart != ost || spanEnd != oen) {
- setSpan(false, mSpans[i], spanStart, spanEnd, mSpanFlags[i]);
+ setSpan(false, mSpans[i], spanStart, spanEnd, mSpanFlags[i],
+ true/*enforceParagraph*/);
changed = true;
}
}
@@ -430,13 +431,8 @@
int copySpanEnd = en - csStart + start;
int copySpanFlags = sp.getSpanFlags(spans[i]) | SPAN_ADDED;
- int flagsStart = (copySpanFlags & START_MASK) >> START_SHIFT;
- int flagsEnd = copySpanFlags & END_MASK;
-
- if(!isInvalidParagraphStart(copySpanStart, flagsStart) &&
- !isInvalidParagraphEnd(copySpanEnd, flagsEnd)) {
- setSpan(false, spans[i], copySpanStart, copySpanEnd, copySpanFlags);
- }
+ setSpan(false, spans[i], copySpanStart, copySpanEnd, copySpanFlags,
+ false/*enforceParagraph*/);
}
}
restoreInvariants();
@@ -558,7 +554,7 @@
changed = true;
setSpan(false, Selection.SELECTION_START, selectionStart, selectionStart,
- Spanned.SPAN_POINT_POINT);
+ Spanned.SPAN_POINT_POINT, true/*enforceParagraph*/);
}
if (selectionEnd > start && selectionEnd < end) {
final long diff = selectionEnd - start;
@@ -567,7 +563,7 @@
changed = true;
setSpan(false, Selection.SELECTION_END, selectionEnd, selectionEnd,
- Spanned.SPAN_POINT_POINT);
+ Spanned.SPAN_POINT_POINT, true/*enforceParagraph*/);
}
if (changed) {
restoreInvariants();
@@ -673,23 +669,34 @@
* inserted at the start or end of the span's range.
*/
public void setSpan(Object what, int start, int end, int flags) {
- setSpan(true, what, start, end, flags);
+ setSpan(true, what, start, end, flags, true/*enforceParagraph*/);
}
// Note: if send is false, then it is the caller's responsibility to restore
// invariants. If send is false and the span already exists, then this method
// will not change the index of any spans.
- private void setSpan(boolean send, Object what, int start, int end, int flags) {
+ private void setSpan(boolean send, Object what, int start, int end, int flags,
+ boolean enforceParagraph) {
checkRange("setSpan", start, end);
int flagsStart = (flags & START_MASK) >> START_SHIFT;
- if(isInvalidParagraphStart(start, flagsStart)) {
- throw new RuntimeException("PARAGRAPH span must start at paragraph boundary");
+ if (isInvalidParagraph(start, flagsStart)) {
+ if (!enforceParagraph) {
+ // do not set the span
+ return;
+ }
+ throw new RuntimeException("PARAGRAPH span must start at paragraph boundary"
+ + " (" + start + " follows " + charAt(start - 1) + ")");
}
int flagsEnd = flags & END_MASK;
- if(isInvalidParagraphEnd(end, flagsEnd)) {
- throw new RuntimeException("PARAGRAPH span must end at paragraph boundary");
+ if (isInvalidParagraph(end, flagsEnd)) {
+ if (!enforceParagraph) {
+ // do not set the span
+ return;
+ }
+ throw new RuntimeException("PARAGRAPH span must end at paragraph boundary"
+ + " (" + end + " follows " + charAt(end - 1) + ")");
}
// 0-length Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
@@ -767,26 +774,8 @@
}
}
- private final boolean isInvalidParagraphStart(int start, int flagsStart) {
- if (flagsStart == PARAGRAPH) {
- if (start != 0 && start != length()) {
- char c = charAt(start - 1);
-
- if (c != '\n') return true;
- }
- }
- return false;
- }
-
- private final boolean isInvalidParagraphEnd(int end, int flagsEnd) {
- if (flagsEnd == PARAGRAPH) {
- if (end != 0 && end != length()) {
- char c = charAt(end - 1);
-
- if (c != '\n') return true;
- }
- }
- return false;
+ private boolean isInvalidParagraph(int index, int flag) {
+ return flag == PARAGRAPH && index != 0 && index != length() && charAt(index - 1) != '\n';
}
/**
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index 4b02df86..366ec14 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -65,7 +65,7 @@
if (en > end)
en = end;
- setSpan(spans[i], st - start, en - start, fl);
+ setSpan(spans[i], st - start, en - start, fl, false/*enforceParagraph*/);
}
}
@@ -149,28 +149,36 @@
}
/* package */ void setSpan(Object what, int start, int end, int flags) {
+ setSpan(what, start, end, flags, true/*enforceParagraph*/);
+ }
+
+ private boolean isIndexFollowsNextLine(int index) {
+ return index != 0 && index != length() && charAt(index - 1) != '\n';
+ }
+
+ private void setSpan(Object what, int start, int end, int flags, boolean enforceParagraph) {
int nstart = start;
int nend = end;
checkRange("setSpan", start, end);
if ((flags & Spannable.SPAN_PARAGRAPH) == Spannable.SPAN_PARAGRAPH) {
- if (start != 0 && start != length()) {
- char c = charAt(start - 1);
-
- if (c != '\n')
- throw new RuntimeException(
- "PARAGRAPH span must start at paragraph boundary" +
- " (" + start + " follows " + c + ")");
+ if (isIndexFollowsNextLine(start)) {
+ if (!enforceParagraph) {
+ // do not set the span
+ return;
+ }
+ throw new RuntimeException("PARAGRAPH span must start at paragraph boundary"
+ + " (" + start + " follows " + charAt(start - 1) + ")");
}
- if (end != 0 && end != length()) {
- char c = charAt(end - 1);
-
- if (c != '\n')
- throw new RuntimeException(
- "PARAGRAPH span must end at paragraph boundary" +
- " (" + end + " follows " + c + ")");
+ if (isIndexFollowsNextLine(end)) {
+ if (!enforceParagraph) {
+ // do not set the span
+ return;
+ }
+ throw new RuntimeException("PARAGRAPH span must end at paragraph boundary"
+ + " (" + end + " follows " + charAt(end - 1) + ")");
}
}
diff --git a/core/java/android/text/method/AllCapsTransformationMethod.java b/core/java/android/text/method/AllCapsTransformationMethod.java
index 0cea821..15f40d5 100644
--- a/core/java/android/text/method/AllCapsTransformationMethod.java
+++ b/core/java/android/text/method/AllCapsTransformationMethod.java
@@ -17,6 +17,10 @@
import android.content.Context;
import android.graphics.Rect;
+import android.icu.text.CaseMap;
+import android.icu.text.Edits;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
@@ -35,7 +39,7 @@
private Locale mLocale;
public AllCapsTransformationMethod(Context context) {
- mLocale = context.getResources().getConfiguration().locale;
+ mLocale = context.getResources().getConfiguration().getLocales().get(0);
}
@Override
@@ -56,7 +60,61 @@
if (locale == null) {
locale = mLocale;
}
- return source.toString().toUpperCase(locale);
+
+ if (!(source instanceof Spanned)) { // No spans
+ return CaseMap.toUpper().apply(
+ locale, source, new StringBuilder(),
+ null /* we don't need the edits */);
+ }
+
+ final Edits edits = new Edits();
+ final SpannableStringBuilder result = CaseMap.toUpper().apply(
+ locale, source, new SpannableStringBuilder(), edits);
+ if (!edits.hasChanges()) {
+ // No changes happened while capitalizing. We can return the source as it was.
+ return source;
+ }
+
+ final Edits.Iterator iterator = edits.getFineIterator();
+ final Spanned spanned = (Spanned) source;
+ final int sourceLength = source.length();
+ final Object[] spans = spanned.getSpans(0, sourceLength, Object.class);
+ for (Object span : spans) {
+ final int sourceStart = spanned.getSpanStart(span);
+ final int sourceEnd = spanned.getSpanEnd(span);
+ final int flags = spanned.getSpanFlags(span);
+ // Make sure the indexes are not at the end of the string, since in that case
+ // iterator.findSourceIndex() would fail.
+ final int destStart = sourceStart == sourceLength ? result.length() :
+ mapToDest(iterator, sourceStart);
+ final int destEnd = sourceEnd == sourceLength ? result.length() :
+ mapToDest(iterator, sourceEnd);
+ result.setSpan(span, destStart, destEnd, flags);
+ }
+ return result;
+ }
+
+ private static int mapToDest(Edits.Iterator iterator, int sourceIndex) {
+ // Guaranteed to succeed if sourceIndex < source.length().
+ iterator.findSourceIndex(sourceIndex);
+ if (sourceIndex == iterator.sourceIndex()) {
+ return iterator.destinationIndex();
+ }
+ // We handle the situation differently depending on if we are in the changed slice or an
+ // unchanged one: In an unchanged slice, we can find the exact location the span
+ // boundary was before and map there.
+ //
+ // But in a changed slice, we need to treat the whole destination slice as an atomic unit.
+ // We adjust the span boundary to the end of that slice to reduce of the chance of adjacent
+ // spans in the source overlapping in the result. (The choice for the end vs the beginning
+ // is somewhat arbitrary, but was taken because we except to see slightly more spans only
+ // affecting a base character compared to spans only affecting a combining character.)
+ if (iterator.hasChange()) {
+ return iterator.destinationIndex() + iterator.newLength();
+ } else {
+ // Move the index 1:1 along with this unchanged piece of text.
+ return iterator.destinationIndex() + (sourceIndex - iterator.sourceIndex());
+ }
}
@Override
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index 7e6eb49..0f85159 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -88,7 +88,11 @@
* {@link android.webkit.WebView#findAddress(String) findAddress()} method in
* {@link android.webkit.WebView} for finding addresses, which has various
* limitations.
+ *
+ * @deprecated See {@link android.webkit.WebView#findAddress(String) findAddress()}
+ * for more explanation.
*/
+ @Deprecated
public static final int MAP_ADDRESSES = 0x08;
/**
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index b6d8aa4..546f93a 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -472,9 +472,9 @@
private int mTop;
private int mRight;
private int mBottom;
- private boolean mIsTopLeftSet;
- private boolean mIsBottomRightSet;
private View mView;
+ private int mTopLeftCalls;
+ private int mBottomRightCalls;
public ViewBounds(View view) {
mView = view;
@@ -483,8 +483,8 @@
public void setTopLeft(PointF topLeft) {
mLeft = Math.round(topLeft.x);
mTop = Math.round(topLeft.y);
- mIsTopLeftSet = true;
- if (mIsBottomRightSet) {
+ mTopLeftCalls++;
+ if (mTopLeftCalls == mBottomRightCalls) {
setLeftTopRightBottom();
}
}
@@ -492,16 +492,16 @@
public void setBottomRight(PointF bottomRight) {
mRight = Math.round(bottomRight.x);
mBottom = Math.round(bottomRight.y);
- mIsBottomRightSet = true;
- if (mIsTopLeftSet) {
+ mBottomRightCalls++;
+ if (mTopLeftCalls == mBottomRightCalls) {
setLeftTopRightBottom();
}
}
private void setLeftTopRightBottom() {
mView.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
- mIsTopLeftSet = false;
- mIsBottomRightSet = false;
+ mTopLeftCalls = 0;
+ mBottomRightCalls = 0;
}
}
}
diff --git a/core/java/android/util/LauncherIcons.java b/core/java/android/util/LauncherIcons.java
index e5aa2b5..89b9646 100644
--- a/core/java/android/util/LauncherIcons.java
+++ b/core/java/android/util/LauncherIcons.java
@@ -20,11 +20,8 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
-import android.graphics.Path;
-import android.graphics.RectF;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@@ -49,7 +46,7 @@
public LauncherIcons(Context context) {
mRes = context.getResources();
DisplayMetrics metrics = mRes.getDisplayMetrics();
- mShadowInset = (int) metrics.density / DisplayMetrics.DENSITY_DEFAULT;
+ mShadowInset = (int)(2 * metrics.density);
mCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
Paint.FILTER_BITMAP_FLAG));
mIconSize = (int) mRes.getDimensionPixelSize(android.R.dimen.app_icon_size);
@@ -91,7 +88,6 @@
return mShadowBitmap;
}
- int shadowSize = mIconSize - mShadowInset;
mShadowBitmap = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ALPHA_8);
mCanvas.setBitmap(mShadowBitmap);
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 5bc6c94..d857bf7 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -212,7 +212,9 @@
* @param tag The tag to check.
* @param level The level to check.
* @return Whether or not that this is allowed to be logged.
- * @throws IllegalArgumentException is thrown if the tag.length() > 23.
+ * @throws IllegalArgumentException is thrown if the tag.length() > 23
+ * for Nougat (7.0) releases (API <= 23) and prior, there is no
+ * tag limit of concern after this API level.
*/
public static native boolean isLoggable(String tag, int level);
diff --git a/core/java/android/util/StateSet.java b/core/java/android/util/StateSet.java
index 051de8a..4bbc0f8 100644
--- a/core/java/android/util/StateSet.java
+++ b/core/java/android/util/StateSet.java
@@ -228,6 +228,29 @@
return true;
}
+ /**
+ * Check whether a list of state specs has an attribute specified.
+ * @param stateSpecs a list of state specs we're checking.
+ * @param attr an attribute we're looking for.
+ * @return {@code true} if the attribute is contained in the state specs.
+ * @hide
+ */
+ public static boolean containsAttribute(int[][] stateSpecs, int attr) {
+ if (stateSpecs != null) {
+ for (int[] spec : stateSpecs) {
+ if (spec == null) {
+ break;
+ }
+ for (int specAttr : spec) {
+ if (specAttr == attr || -specAttr == attr) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
public static int[] trimStateSet(int[] states, int newSize) {
if (states.length == newSize) {
return states;
diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java
index 4ae5a29..2c9bb66 100644
--- a/core/java/android/util/TypedValue.java
+++ b/core/java/android/util/TypedValue.java
@@ -187,6 +187,27 @@
/**
* If the value came from a resource, these are the configurations for
* which its contents can change.
+ *
+ * <p>For example, if a resource has a value defined for the -land resource qualifier,
+ * this field will have the {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION} bit set.
+ * </p>
+ *
+ * @see android.content.pm.ActivityInfo#CONFIG_MCC
+ * @see android.content.pm.ActivityInfo#CONFIG_MNC
+ * @see android.content.pm.ActivityInfo#CONFIG_LOCALE
+ * @see android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN
+ * @see android.content.pm.ActivityInfo#CONFIG_KEYBOARD
+ * @see android.content.pm.ActivityInfo#CONFIG_KEYBOARD_HIDDEN
+ * @see android.content.pm.ActivityInfo#CONFIG_NAVIGATION
+ * @see android.content.pm.ActivityInfo#CONFIG_ORIENTATION
+ * @see android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
+ * @see android.content.pm.ActivityInfo#CONFIG_UI_MODE
+ * @see android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
+ * @see android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
+ * @see android.content.pm.ActivityInfo#CONFIG_DENSITY
+ * @see android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION
+ * @see android.content.pm.ActivityInfo#CONFIG_COLOR_MODE
+ *
*/
public @Config int changingConfigurations = -1;
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 6dedbde..3e9fab1 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -205,6 +205,7 @@
* </p>
*
* @see #getFlags
+ * @hide
*/
public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index f3c2421..f47c355 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -18,15 +18,17 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.util.ArrayMap;
-import android.util.SparseArray;
-import android.util.SparseBooleanArray;
+import android.util.ArraySet;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
/**
@@ -54,10 +56,12 @@
final Rect mOtherRect = new Rect();
final Rect mBestCandidateRect = new Rect();
private final UserSpecifiedFocusComparator mUserSpecifiedFocusComparator =
- new UserSpecifiedFocusComparator((v) -> v.getNextFocusForwardId());
+ new UserSpecifiedFocusComparator((r, v) -> isValidId(v.getNextFocusForwardId())
+ ? v.findUserSetNextFocus(r, View.FOCUS_FORWARD) : null);
private final UserSpecifiedFocusComparator mUserSpecifiedClusterComparator =
- new UserSpecifiedFocusComparator((v) -> v.getNextClusterForwardId());
- private final FocusComparator mFocusComparator = new FocusComparator();
+ new UserSpecifiedFocusComparator((r, v) -> isValidId(v.getNextClusterForwardId())
+ ? v.findUserSetNextKeyboardNavigationCluster(r, View.FOCUS_FORWARD) : null);
+ private final FocusSorter mFocusSorter = new FocusSorter();
private final ArrayList<View> mTempList = new ArrayList<View>();
@@ -258,7 +262,7 @@
@View.FocusDirection int direction) {
try {
// Note: This sort is stable.
- mUserSpecifiedClusterComparator.setFocusables(clusters);
+ mUserSpecifiedClusterComparator.setFocusables(clusters, root);
Collections.sort(clusters, mUserSpecifiedClusterComparator);
} finally {
mUserSpecifiedClusterComparator.recycle();
@@ -283,7 +287,7 @@
View focused, Rect focusedRect, int direction) {
try {
// Note: This sort is stable.
- mUserSpecifiedFocusComparator.setFocusables(focusables);
+ mUserSpecifiedFocusComparator.setFocusables(focusables, root);
Collections.sort(focusables, mUserSpecifiedFocusComparator);
} finally {
mUserSpecifiedFocusComparator.recycle();
@@ -759,120 +763,155 @@
return id != 0 && id != View.NO_ID;
}
- static FocusComparator getFocusComparator(ViewGroup root, boolean isRtl) {
- FocusComparator comparator = getInstance().mFocusComparator;
- comparator.setRoot(root);
- comparator.setIsLayoutRtl(isRtl);
- return comparator;
- }
+ static final class FocusSorter {
+ private ArrayList<Rect> mRectPool = new ArrayList<>();
+ private int mLastPoolRect;
+ private int mRtlMult;
+ private HashMap<View, Rect> mRectByView = null;
- static final class FocusComparator implements Comparator<View> {
- private final Rect mFirstRect = new Rect();
- private final Rect mSecondRect = new Rect();
- private ViewGroup mRoot = null;
- private boolean mIsLayoutRtl;
-
- public void setIsLayoutRtl(boolean b) {
- mIsLayoutRtl = b;
- }
-
- public void setRoot(ViewGroup root) {
- mRoot = root;
- }
-
- public int compare(View first, View second) {
+ private Comparator<View> mTopsComparator = (first, second) -> {
if (first == second) {
return 0;
}
- getRect(first, mFirstRect);
- getRect(second, mSecondRect);
+ Rect firstRect = mRectByView.get(first);
+ Rect secondRect = mRectByView.get(second);
- if (mFirstRect.top < mSecondRect.top) {
- return -1;
- } else if (mFirstRect.top > mSecondRect.top) {
- return 1;
- } else if (mFirstRect.left < mSecondRect.left) {
- return mIsLayoutRtl ? 1 : -1;
- } else if (mFirstRect.left > mSecondRect.left) {
- return mIsLayoutRtl ? -1 : 1;
- } else if (mFirstRect.bottom < mSecondRect.bottom) {
- return -1;
- } else if (mFirstRect.bottom > mSecondRect.bottom) {
- return 1;
- } else if (mFirstRect.right < mSecondRect.right) {
- return mIsLayoutRtl ? 1 : -1;
- } else if (mFirstRect.right > mSecondRect.right) {
- return mIsLayoutRtl ? -1 : 1;
- } else {
- // The view are distinct but completely coincident so we consider
- // them equal for our purposes. Since the sort is stable, this
- // means that the views will retain their layout order relative to one another.
+ int result = firstRect.top - secondRect.top;
+ if (result == 0) {
+ return firstRect.bottom - secondRect.bottom;
+ }
+ return result;
+ };
+
+ private Comparator<View> mSidesComparator = (first, second) -> {
+ if (first == second) {
return 0;
}
- }
- private void getRect(View view, Rect rect) {
- view.getDrawingRect(rect);
- mRoot.offsetDescendantRectToMyCoords(view, rect);
+ Rect firstRect = mRectByView.get(first);
+ Rect secondRect = mRectByView.get(second);
+
+ int result = firstRect.left - secondRect.left;
+ if (result == 0) {
+ return firstRect.right - secondRect.right;
+ }
+ return mRtlMult * result;
+ };
+
+ public void sort(View[] views, int start, int end, ViewGroup root, boolean isRtl) {
+ int count = end - start;
+ if (count < 2) {
+ return;
+ }
+ if (mRectByView == null) {
+ mRectByView = new HashMap<>();
+ }
+ mRtlMult = isRtl ? -1 : 1;
+ for (int i = mRectPool.size(); i < count; ++i) {
+ mRectPool.add(new Rect());
+ }
+ for (int i = start; i < end; ++i) {
+ Rect next = mRectPool.get(mLastPoolRect++);
+ views[i].getDrawingRect(next);
+ root.offsetDescendantRectToMyCoords(views[i], next);
+ mRectByView.put(views[i], next);
+ }
+
+ // Sort top-to-bottom
+ Arrays.sort(views, start, count, mTopsComparator);
+ // Sweep top-to-bottom to identify rows
+ int sweepBottom = mRectByView.get(views[start]).bottom;
+ int rowStart = start;
+ int sweepIdx = start + 1;
+ for (; sweepIdx < end; ++sweepIdx) {
+ Rect currRect = mRectByView.get(views[sweepIdx]);
+ if (currRect.top >= sweepBottom) {
+ // Next view is on a new row, sort the row we've just finished left-to-right.
+ if ((sweepIdx - rowStart) > 1) {
+ Arrays.sort(views, rowStart, sweepIdx, mSidesComparator);
+ }
+ sweepBottom = currRect.bottom;
+ rowStart = sweepIdx;
+ } else {
+ // Next view vertically overlaps, we need to extend our "row height"
+ sweepBottom = Math.max(sweepBottom, currRect.bottom);
+ }
+ }
+ // Sort whatever's left (final row) left-to-right
+ if ((sweepIdx - rowStart) > 1) {
+ Arrays.sort(views, rowStart, sweepIdx, mSidesComparator);
+ }
+
+ mLastPoolRect = 0;
+ mRectByView.clear();
}
}
/**
+ * Public for testing.
+ *
+ * @hide
+ */
+ @TestApi
+ public static void sort(View[] views, int start, int end, ViewGroup root, boolean isRtl) {
+ getInstance().mFocusSorter.sort(views, start, end, root, isRtl);
+ }
+
+ /**
* Sorts views according to any explicitly-specified focus-chains. If there are no explicitly
* specified focus chains (eg. no nextFocusForward attributes defined), this should be a no-op.
*/
private static final class UserSpecifiedFocusComparator implements Comparator<View> {
- private final SparseArray<View> mFocusables = new SparseArray<View>();
- private final SparseBooleanArray mIsConnectedTo = new SparseBooleanArray();
+ private final ArrayMap<View, View> mNextFoci = new ArrayMap<>();
+ private final ArraySet<View> mIsConnectedTo = new ArraySet<>();
private final ArrayMap<View, View> mHeadsOfChains = new ArrayMap<View, View>();
private final ArrayMap<View, Integer> mOriginalOrdinal = new ArrayMap<>();
- private final NextIdGetter mNextIdGetter;
+ private final NextFocusGetter mNextFocusGetter;
+ private View mRoot;
- public interface NextIdGetter {
- int get(View view);
+ public interface NextFocusGetter {
+ View get(View root, View view);
}
- UserSpecifiedFocusComparator(NextIdGetter nextIdGetter) {
- mNextIdGetter = nextIdGetter;
+ UserSpecifiedFocusComparator(NextFocusGetter nextFocusGetter) {
+ mNextFocusGetter = nextFocusGetter;
}
public void recycle() {
- mFocusables.clear();
+ mRoot = null;
mHeadsOfChains.clear();
mIsConnectedTo.clear();
mOriginalOrdinal.clear();
+ mNextFoci.clear();
}
- public void setFocusables(List<View> focusables) {
- for (int i = focusables.size() - 1; i >= 0; i--) {
- final View view = focusables.get(i);
- final int id = view.getId();
- if (isValidId(id)) {
- mFocusables.put(id, view);
- }
- final int nextId = mNextIdGetter.get(view);
- if (isValidId(nextId)) {
- mIsConnectedTo.put(nextId, true);
- }
- }
-
- for (int i = focusables.size() - 1; i >= 0; i--) {
- final View view = focusables.get(i);
- final int nextId = mNextIdGetter.get(view);
- if (isValidId(nextId) && !mIsConnectedTo.get(view.getId())) {
- setHeadOfChain(view);
- }
- }
-
+ public void setFocusables(List<View> focusables, View root) {
+ mRoot = root;
for (int i = 0; i < focusables.size(); ++i) {
mOriginalOrdinal.put(focusables.get(i), i);
}
+
+ for (int i = focusables.size() - 1; i >= 0; i--) {
+ final View view = focusables.get(i);
+ final View next = mNextFocusGetter.get(mRoot, view);
+ if (next != null && mOriginalOrdinal.containsKey(next)) {
+ mNextFoci.put(view, next);
+ mIsConnectedTo.add(next);
+ }
+ }
+
+ for (int i = focusables.size() - 1; i >= 0; i--) {
+ final View view = focusables.get(i);
+ final View next = mNextFoci.get(view);
+ if (next != null && !mIsConnectedTo.contains(view)) {
+ setHeadOfChain(view);
+ }
+ }
}
private void setHeadOfChain(View head) {
- for (View view = head; view != null;
- view = mFocusables.get(mNextIdGetter.get(view))) {
+ for (View view = head; view != null; view = mNextFoci.get(view)) {
final View otherHead = mHeadsOfChains.get(view);
if (otherHead != null) {
if (otherHead == head) {
@@ -900,7 +939,7 @@
return -1; // first is the head, it should be first
} else if (second == firstHead) {
return 1; // second is the head, it should be first
- } else if (isValidId(mNextIdGetter.get(first))) {
+ } else if (mNextFoci.get(first) != null) {
return -1; // first is not the end of the chain
} else {
return 1; // first is end of chain
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index fe91978..20f7ace 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -94,8 +94,8 @@
super.onFinishInflate();
mAppName = findViewById(com.android.internal.R.id.app_name_text);
mHeaderText = findViewById(com.android.internal.R.id.header_text);
- mExpandButton = (ImageView) findViewById(com.android.internal.R.id.expand_button);
- mIcon = (CachingIconView) findViewById(com.android.internal.R.id.icon);
+ mExpandButton = findViewById(com.android.internal.R.id.expand_button);
+ mIcon = findViewById(com.android.internal.R.id.icon);
mProfileBadge = findViewById(com.android.internal.R.id.profile_badge);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 1cb563f..3b15456 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -55,6 +55,8 @@
private static native void nativeSetAnimationTransaction();
private static native void nativeSetLayer(long nativeObject, int zorder);
+ private static native void nativeSetRelativeLayer(long nativeObject, IBinder relativeTo,
+ int zorder);
private static native void nativeSetPosition(long nativeObject, float x, float y);
private static native void nativeSetGeometryAppliesWithResize(long nativeObject);
private static native void nativeSetSize(long nativeObject, int w, int h);
@@ -461,6 +463,11 @@
nativeSetLayer(mNativeObject, zorder);
}
+ public void setRelativeLayer(IBinder relativeTo, int zorder) {
+ checkNotReleased();
+ nativeSetRelativeLayer(mNativeObject, relativeTo, zorder);
+ }
+
public void setPosition(float x, float y) {
checkNotReleased();
nativeSetPosition(mNativeObject, x, y);
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 31911cb..1a71679 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -93,7 +93,7 @@
* artifacts may occur on previous versions of the platform when its window is
* positioned asynchronously.</p>
*/
-public class SurfaceView extends View {
+public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback {
private static final String TAG = "SurfaceView";
private static final boolean DEBUG = false;
@@ -169,6 +169,8 @@
boolean mWindowVisibility = false;
boolean mLastWindowVisibility = false;
boolean mViewVisibility = false;
+ boolean mWindowStopped = false;
+
int mRequestedWidth = -1;
int mRequestedHeight = -1;
/* Set SurfaceView's format to 565 by default to maintain backward
@@ -226,12 +228,27 @@
return mSurfaceHolder;
}
+ private void updateRequestedVisibility() {
+ mRequestedVisible = mViewVisibility && mWindowVisibility && !mWindowStopped;
+ }
+
+ /** @hide */
+ @Override
+ public void windowStopped(boolean stopped) {
+ mWindowStopped = stopped;
+ updateRequestedVisibility();
+ updateSurface();
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+
+ getViewRootImpl().addWindowStoppedCallback(this);
+
mParent.requestTransparentRegion(this);
mViewVisibility = getVisibility() == VISIBLE;
- mRequestedVisible = mViewVisibility && mWindowVisibility;
+ updateRequestedVisibility();
mAttachedToWindow = true;
if (!mGlobalListenersAdded) {
@@ -246,7 +263,7 @@
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
mWindowVisibility = visibility == VISIBLE;
- mRequestedVisible = mWindowVisibility && mViewVisibility;
+ updateRequestedVisibility();
updateSurface();
}
@@ -254,7 +271,7 @@
public void setVisibility(int visibility) {
super.setVisibility(visibility);
mViewVisibility = visibility == VISIBLE;
- boolean newRequestedVisible = mWindowVisibility && mViewVisibility;
+ boolean newRequestedVisible = mWindowVisibility && mViewVisibility && !mWindowStopped;
if (newRequestedVisible != mRequestedVisible) {
// our base class (View) invalidates the layout only when
// we go from/to the GONE state. However, SurfaceView needs
@@ -278,6 +295,8 @@
@Override
protected void onDetachedFromWindow() {
+ getViewRootImpl().removeWindowStoppedCallback(this);
+
mAttachedToWindow = false;
if (mGlobalListenersAdded) {
ViewTreeObserver observer = getViewTreeObserver();
@@ -299,6 +318,7 @@
mSurfaceControl = null;
mHaveFrame = false;
+
super.onDetachedFromWindow();
}
@@ -683,8 +703,7 @@
mTranslator.translateRectInAppWindowToScreen(mScreenRect);
}
- if (mSurfaceControl != null
- && (!isHardwareAccelerated() || !mRtHandlingPositionUpdates)) {
+ if (!isHardwareAccelerated() || !mRtHandlingPositionUpdates) {
try {
if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition UI, " +
"postion = [%d, %d, %d, %d]", System.identityHashCode(this),
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a09db9c..a522652 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -321,7 +321,7 @@
* </pre></li>
* <li>From the onCreate method of an Activity, find the Button
* <pre class="prettyprint">
- * Button myButton = (Button) findViewById(R.id.my_button);
+ * Button myButton = findViewById(R.id.my_button);
* </pre></li>
* </ul>
* <p>
@@ -3920,6 +3920,14 @@
private int mBackgroundResource;
private boolean mBackgroundSizeChanged;
+ /** The default focus highlight.
+ * @see #mDefaultFocusHighlightEnabled
+ * @see Drawable#hasFocusStateSpecified()
+ */
+ private Drawable mDefaultFocusHighlight;
+ private Drawable mDefaultFocusHighlightCache;
+ private boolean mDefaultFocusHighlightSizeChanged;
+
private String mTransitionName;
static class TintInfo {
@@ -4102,6 +4110,12 @@
*/
int mNextClusterForwardId = View.NO_ID;
+ /**
+ * Whether this View should use a default focus highlight when it gets focused but doesn't
+ * have {@link android.R.attr#state_focused} defined in its background.
+ */
+ boolean mDefaultFocusHighlightEnabled = true;
+
private CheckForLongPress mPendingCheckForLongPress;
private CheckForTap mPendingCheckForTap = null;
private PerformClick mPerformClick;
@@ -5086,6 +5100,11 @@
setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
}
break;
+ case R.styleable.View_defaultFocusHighlightEnabled:
+ if (a.peekValue(attr) != null) {
+ setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
+ }
+ break;
}
}
@@ -6800,6 +6819,9 @@
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
+ // Here we check whether we still need the default focus highlight, and switch it on/off.
+ switchDefaultFocusHighlight();
+
InputMethodManager imm = InputMethodManager.peekInstance();
if (!gainFocus) {
if (isPressed()) {
@@ -6948,7 +6970,10 @@
dispatchPopulateAccessibilityEvent(event);
}
// In the beginning we called #isShown(), so we know that getParent() is not null.
- getParent().requestSendAccessibilityEvent(this, event);
+ ViewParent parent = getParent();
+ if (parent != null) {
+ getParent().requestSendAccessibilityEvent(this, event);
+ }
}
/**
@@ -9986,6 +10011,33 @@
}
/**
+ * Sets whether this View should use a default focus highlight when it gets focused but doesn't
+ * have {@link android.R.attr#state_focused} defined in its background.
+ *
+ * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
+ * highlight, {@code false} otherwise.
+ *
+ * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
+ */
+ public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
+ mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
+ }
+
+ /**
+
+ /**
+ * Returns whether this View should use a default focus highlight when it gets focused but
+ * doesn't have {@link android.R.attr#state_focused} defined in its background.
+ *
+ * @return True if this View should use a default focus highlight.
+ * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
+ */
+ @ViewDebug.ExportedProperty(category = "defaultFocusHighlightEnabled")
+ public final boolean getDefaultFocusHighlightEnabled() {
+ return mDefaultFocusHighlightEnabled;
+ }
+
+ /**
* If a user manually specified the next view id for a particular direction,
* use the root to look up the view.
* @param root The root view of the hierarchy containing this view.
@@ -11752,6 +11804,10 @@
if (dr != null && isVisible != dr.isVisible()) {
dr.setVisible(isVisible, false);
}
+ final Drawable hl = mDefaultFocusHighlight;
+ if (hl != null && isVisible != hl.isVisible()) {
+ hl.setVisible(isVisible, false);
+ }
final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
if (fg != null && isVisible != fg.isVisible()) {
fg.setVisible(isVisible, false);
@@ -12965,6 +13021,7 @@
if ((changed & DRAW_MASK) != 0) {
if ((mViewFlags & WILL_NOT_DRAW) != 0) {
if (mBackground != null
+ || mDefaultFocusHighlight != null
|| (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
mPrivateFlags &= ~PFLAG_SKIP_DRAW;
} else {
@@ -13036,6 +13093,7 @@
}
mBackgroundSizeChanged = true;
+ mDefaultFocusHighlightSizeChanged = true;
if (mForegroundInfo != null) {
mForegroundInfo.mBoundsChanged = true;
}
@@ -13927,6 +13985,7 @@
invalidate(true);
}
mBackgroundSizeChanged = true;
+ mDefaultFocusHighlightSizeChanged = true;
if (mForegroundInfo != null) {
mForegroundInfo.mBoundsChanged = true;
}
@@ -13995,6 +14054,7 @@
invalidate(true);
}
mBackgroundSizeChanged = true;
+ mDefaultFocusHighlightSizeChanged = true;
if (mForegroundInfo != null) {
mForegroundInfo.mBoundsChanged = true;
}
@@ -14057,6 +14117,7 @@
invalidate(true);
}
mBackgroundSizeChanged = true;
+ mDefaultFocusHighlightSizeChanged = true;
if (mForegroundInfo != null) {
mForegroundInfo.mBoundsChanged = true;
}
@@ -14116,6 +14177,7 @@
invalidate(true);
}
mBackgroundSizeChanged = true;
+ mDefaultFocusHighlightSizeChanged = true;
if (mForegroundInfo != null) {
mForegroundInfo.mBoundsChanged = true;
}
@@ -18720,6 +18782,9 @@
// Step 6, draw decorations (foreground, scrollbars)
onDrawForeground(canvas);
+ // Step 7, draw the default focus highlight
+ drawDefaultFocusHighlight(canvas);
+
if (debugDraw()) {
debugDrawFocus(canvas);
}
@@ -19278,6 +19343,7 @@
mPrivateFlags |= drawn;
mBackgroundSizeChanged = true;
+ mDefaultFocusHighlightSizeChanged = true;
if (mForegroundInfo != null) {
mForegroundInfo.mBoundsChanged = true;
}
@@ -19429,6 +19495,9 @@
if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
}
+ if (mDefaultFocusHighlight != null) {
+ mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
+ }
mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
onResolveDrawables(layoutDirection);
}
@@ -19487,7 +19556,8 @@
// Avoid verifying the scroll bar drawable so that we don't end up in
// an invalidation loop. This effectively prevents the scroll bar
// drawable from triggering invalidations and scheduling runnables.
- return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
+ return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
+ || (mDefaultFocusHighlight == who);
}
/**
@@ -19511,6 +19581,11 @@
changed |= bg.setState(state);
}
+ final Drawable hl = mDefaultFocusHighlight;
+ if (hl != null && hl.isStateful()) {
+ changed |= hl.setState(state);
+ }
+
final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
if (fg != null && fg.isStateful()) {
changed |= fg.setState(state);
@@ -19550,6 +19625,9 @@
if (mBackground != null) {
mBackground.setHotspot(x, y);
}
+ if (mDefaultFocusHighlight != null) {
+ mDefaultFocusHighlight.setHotspot(x, y);
+ }
if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
mForegroundInfo.mDrawable.setHotspot(x, y);
}
@@ -19586,6 +19664,106 @@
}
/**
+ * Create a default focus highlight if it doesn't exist.
+ * @return a default focus highlight.
+ */
+ private Drawable getDefaultFocusHighlightDrawable() {
+ if (mDefaultFocusHighlightCache == null) {
+ if (mContext != null) {
+ final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
+ final TypedArray ta = mContext.obtainStyledAttributes(attrs);
+ mDefaultFocusHighlightCache = ta.getDrawable(0);
+ ta.recycle();
+ }
+ }
+ return mDefaultFocusHighlightCache;
+ }
+
+ /**
+ * Set the current default focus highlight.
+ * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
+ */
+ private void setDefaultFocusHighlight(Drawable highlight) {
+ mDefaultFocusHighlight = highlight;
+ mDefaultFocusHighlightSizeChanged = true;
+ if (highlight != null) {
+ if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
+ mPrivateFlags &= ~PFLAG_SKIP_DRAW;
+ }
+ highlight.setLayoutDirection(getLayoutDirection());
+ if (highlight.isStateful()) {
+ highlight.setState(getDrawableState());
+ }
+ if (isAttachedToWindow()) {
+ highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
+ }
+ // Set callback last, since the view may still be initializing.
+ highlight.setCallback(this);
+ } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
+ && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
+ mPrivateFlags |= PFLAG_SKIP_DRAW;
+ }
+ requestLayout();
+ invalidate();
+ }
+
+ /**
+ * Check whether we need to draw a default focus highlight when this view gets focused,
+ * which requires:
+ * <ul>
+ * <li>In the background, {@link android.R.attr#state_focused} is not defined.</li>
+ * <li>This view is not in touch mode.</li>
+ * <li>This view doesn't opt out for a default focus highlight, via
+ * {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
+ * <li>This view is attached to window.</li>
+ * </ul>
+ * @return {@code true} if a default focus highlight is needed.
+ */
+ private boolean isDefaultFocusHighlightNeeded(Drawable background) {
+ final boolean hasFocusStateSpecified = background == null || !background.isStateful()
+ || !background.hasFocusStateSpecified();
+ return !isInTouchMode() && getDefaultFocusHighlightEnabled() && hasFocusStateSpecified
+ && isAttachedToWindow();
+ }
+
+ /**
+ * When this view is focused, switches on/off the default focused highlight.
+ * <p>
+ * This always happens when this view is focused, and only at this moment the default focus
+ * highlight can be visible.
+ */
+ private void switchDefaultFocusHighlight() {
+ if (isFocused()) {
+ final boolean needed = isDefaultFocusHighlightNeeded(mBackground);
+ final boolean active = mDefaultFocusHighlight != null;
+ if (needed && !active) {
+ setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
+ } else if (!needed && active) {
+ // The highlight is no longer needed, so tear it down.
+ setDefaultFocusHighlight(null);
+ }
+ }
+ }
+
+ /**
+ * Draw the default focus highlight onto the canvas.
+ * @param canvas the canvas where we're drawing the highlight.
+ */
+ private void drawDefaultFocusHighlight(Canvas canvas) {
+ if (mDefaultFocusHighlight != null) {
+ if (mDefaultFocusHighlightSizeChanged) {
+ mDefaultFocusHighlightSizeChanged = false;
+ final int l = mScrollX;
+ final int r = l + mRight - mLeft;
+ final int t = mScrollY;
+ final int b = t + mBottom - mTop;
+ mDefaultFocusHighlight.setBounds(l, t, r, b);
+ }
+ mDefaultFocusHighlight.draw(canvas);
+ }
+ }
+
+ /**
* Return an array of resource IDs of the drawable states representing the
* current state of the view.
*
@@ -19725,6 +19903,9 @@
if (mStateListAnimator != null) {
mStateListAnimator.jumpToCurrentState();
}
+ if (mDefaultFocusHighlight != null) {
+ mDefaultFocusHighlight.jumpToCurrentState();
+ }
if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
mForegroundInfo.mDrawable.jumpToCurrentState();
}
@@ -19869,6 +20050,7 @@
/* Remove the background */
mBackground = null;
if ((mViewFlags & WILL_NOT_DRAW) != 0
+ && (mDefaultFocusHighlight == null)
&& (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
mPrivateFlags |= PFLAG_SKIP_DRAW;
}
@@ -20060,7 +20242,8 @@
}
// Set callback last, since the view may still be initializing.
foreground.setCallback(this);
- } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
+ } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
+ && (mDefaultFocusHighlight == null)) {
mPrivateFlags |= PFLAG_SKIP_DRAW;
}
requestLayout();
@@ -21875,6 +22058,11 @@
// Similarly, we remove the foreground drawable's non-transparent parts.
applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
}
+ if (mDefaultFocusHighlight != null
+ && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
+ // Similarly, we remove the default focus highlight's non-transparent parts.
+ applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
+ }
}
}
return true;
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 574137b..4def0d0 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -35,7 +35,7 @@
* Defines the width of the horizontal scrollbar and the height of the vertical scrollbar in
* dips
*/
- private static final int SCROLL_BAR_SIZE = 4;
+ private static final int SCROLL_BAR_SIZE = 10;
/**
* Duration of the fade when scrollbars fade away in milliseconds
@@ -354,8 +354,7 @@
mEdgeSlop = (int) (sizeAndDensity * EDGE_SLOP + 0.5f);
mFadingEdgeLength = (int) (sizeAndDensity * FADING_EDGE_LENGTH + 0.5f);
- mScrollbarSize = res.getDimensionPixelSize(
- com.android.internal.R.dimen.config_scrollbarSize);
+ mScrollbarSize = (int) (density * SCROLL_BAR_SIZE + 0.5f);
mDoubleTapSlop = (int) (sizeAndDensity * DOUBLE_TAP_SLOP + 0.5f);
mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f);
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 9e1ceee..f9eb25d 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -61,7 +61,6 @@
import com.android.internal.R;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -1216,7 +1215,7 @@
children[count++] = child;
}
}
- Arrays.sort(children, 0, count, FocusFinder.getFocusComparator(this, false));
+ FocusFinder.sort(children, 0, count, this, isLayoutRtl());
for (int i = 0; i < count; ++i) {
children[i].addFocusables(views, direction, focusableMode);
}
@@ -1266,7 +1265,7 @@
visibleChildren[count++] = child;
}
}
- Arrays.sort(visibleChildren, 0, count, FocusFinder.getFocusComparator(this, false));
+ FocusFinder.sort(visibleChildren, 0, count, this, isLayoutRtl());
for (int i = 0; i < count; ++i) {
visibleChildren[i].addKeyboardNavigationClusters(views, direction);
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4a7b16e..a7ececf 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1249,11 +1249,17 @@
mIsAmbientMode = ambient;
}
- void setWindowVisibility(int visibility) {
- if (visibility != mAttachInfo.mWindowVisibility) {
- mAttachInfo.mWindowVisibility = visibility;
- mView.dispatchWindowVisibilityChanged(visibility);
- }
+ interface WindowStoppedCallback {
+ public void windowStopped(boolean stopped);
+ }
+ private final ArrayList<WindowStoppedCallback> mWindowStoppedCallbacks = new ArrayList<>();
+
+ void addWindowStoppedCallback(WindowStoppedCallback c) {
+ mWindowStoppedCallbacks.add(c);
+ }
+
+ void removeWindowStoppedCallback(WindowStoppedCallback c) {
+ mWindowStoppedCallbacks.remove(c);
}
void setWindowStopped(boolean stopped) {
@@ -1270,7 +1276,10 @@
if (renderer != null) {
renderer.destroyHardwareResources(mView);
}
- mView.dispatchWindowVisibilityChanged(View.GONE);
+ }
+
+ for (int i = 0; i < mWindowStoppedCallbacks.size(); i++) {
+ mWindowStoppedCallbacks.get(i).windowStopped(stopped);
}
}
}
@@ -1305,8 +1314,7 @@
}
int getHostVisibility() {
- return (mAppVisible || mForceDecorViewVisibility) && !mStopped
- ? mView.getVisibility() : View.GONE;
+ return (mAppVisible || mForceDecorViewVisibility) ? mView.getVisibility() : View.GONE;
}
/**
@@ -1663,8 +1671,8 @@
}
if (viewVisibilityChanged) {
- setWindowVisibility(viewVisibility);
-
+ mAttachInfo.mWindowVisibility = viewVisibility;
+ host.dispatchWindowVisibilityChanged(viewVisibility);
if (viewUserVisibilityChanged) {
host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE);
}
diff --git a/core/java/android/view/ViewStub.java b/core/java/android/view/ViewStub.java
index 85d10f1..e9d1b87 100644
--- a/core/java/android/view/ViewStub.java
+++ b/core/java/android/view/ViewStub.java
@@ -58,7 +58,7 @@
* The preferred way to perform the inflation of the layout resource is the following:
*
* <pre>
- * ViewStub stub = (ViewStub) findViewById(R.id.stub);
+ * ViewStub stub = findViewById(R.id.stub);
* View inflated = stub.inflate();
* </pre>
*
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 666ccf4..8445b37 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -978,8 +978,9 @@
* seeing this window, unless {@link #FLAG_SHOW_WHEN_LOCKED} has
* also been set.
* @deprecated Use {@link #FLAG_SHOW_WHEN_LOCKED} or {@link KeyguardManager#dismissKeyguard}
- * instead. The Keyguard should never be dismissed automatically repeatedly as it also
- * guards against unintentional touches.
+ * instead. Since keyguard was dismissed all the time as long as an activity with this flag
+ * on its window was focused, keyguard couldn't guard against unintentional touches on the
+ * screen, which isn't desired.
*/
@Deprecated
public static final int FLAG_DISMISS_KEYGUARD = 0x00400000;
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index d429d37..41c209c 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -192,6 +192,9 @@
* {@hide}
*/
public void onCreate(Bundle savedInstanceState) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
synchronized (mLock) {
mLastAutofilledData = savedInstanceState.getParcelable(LAST_AUTOFILLED_DATA_TAG);
@@ -237,6 +240,9 @@
* {@hide}
*/
public void onAttachedToWindow(@NonNull IBinder windowToken) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
synchronized (mLock) {
if (mSessionId == NO_SESSION) {
return;
@@ -258,6 +264,9 @@
* {@hide}
*/
public void onSaveInstanceState(Bundle outState) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
synchronized (mLock) {
if (mSessionId != NO_SESSION) {
outState.putInt(SESSION_ID_TAG, mSessionId);
@@ -278,6 +287,9 @@
* @return whether autofill is enabled for the current user.
*/
public boolean isEnabled() {
+ if (!hasAutofillFeature()) {
+ return false;
+ }
synchronized (mLock) {
ensureServiceClientAddedIfNeededLocked();
return mEnabled;
@@ -294,6 +306,9 @@
* @param view view requesting the new autofill context.
*/
public void requestAutofill(@NonNull View view) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
synchronized (mLock) {
ensureServiceClientAddedIfNeededLocked();
@@ -320,6 +335,9 @@
* @param bounds child boundaries, relative to the top window.
*/
public void requestAutofill(@NonNull View view, int childId, @NonNull Rect bounds) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
synchronized (mLock) {
ensureServiceClientAddedIfNeededLocked();
@@ -339,6 +357,9 @@
* @param view {@link View} that was entered.
*/
public void notifyViewEntered(@NonNull View view) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
AutofillCallback callback = null;
synchronized (mLock) {
ensureServiceClientAddedIfNeededLocked();
@@ -372,6 +393,9 @@
* @param view {@link View} that was exited.
*/
public void notifyViewExited(@NonNull View view) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
synchronized (mLock) {
ensureServiceClientAddedIfNeededLocked();
@@ -392,6 +416,9 @@
* @param bounds child boundaries, relative to the top window.
*/
public void notifyViewEntered(@NonNull View view, int childId, @NonNull Rect bounds) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
AutofillCallback callback = null;
synchronized (mLock) {
ensureServiceClientAddedIfNeededLocked();
@@ -426,6 +453,9 @@
* @param childId id identifying the virtual child inside the view.
*/
public void notifyViewExited(@NonNull View view, int childId) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
synchronized (mLock) {
ensureServiceClientAddedIfNeededLocked();
@@ -444,6 +474,9 @@
* @param view view whose value changed.
*/
public void notifyValueChanged(View view) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
AutofillId id = null;
boolean valueWasRead = false;
AutofillValue value = null;
@@ -486,7 +519,6 @@
}
}
-
/**
* Called to indicate the value of an autofillable virtual {@link View} changed.
*
@@ -495,6 +527,9 @@
* @param value new value of the child.
*/
public void notifyValueChanged(View view, int childId, AutofillValue value) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
synchronized (mLock) {
if (!mEnabled || mSessionId == NO_SESSION) {
return;
@@ -512,6 +547,9 @@
* call this method after the form is submitted and another page is rendered.
*/
public void commit() {
+ if (!hasAutofillFeature()) {
+ return;
+ }
synchronized (mLock) {
if (!mEnabled && mSessionId == NO_SESSION) {
return;
@@ -528,6 +566,9 @@
* call this method if the user does not post the form but moves to another form in this page.
*/
public void cancel() {
+ if (!hasAutofillFeature()) {
+ return;
+ }
synchronized (mLock) {
if (!mEnabled && mSessionId == NO_SESSION) {
return;
@@ -537,6 +578,21 @@
}
}
+ /**
+ * If the app calling this API has enabled autofill services they
+ * will be disabled.
+ */
+ public void disableOwnedAutofillServices() {
+ if (!hasAutofillFeature()) {
+ return;
+ }
+ try {
+ mService.disableOwnedAutofillServices(mContext.getUserId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
private AutofillClient getClientLocked() {
if (mContext instanceof AutofillClient) {
return (AutofillClient) mContext;
@@ -546,6 +602,9 @@
/** @hide */
public void onAuthenticationResult(Intent data) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
// TODO(b/33197203): the result code is being ignored, so this method is not reliably
// handling the cases where it's not RESULT_OK: it works fine if the service does not
// set the EXTRA_AUTHENTICATION_RESULT extra, but it could cause weird results if the
@@ -660,6 +719,9 @@
* @param callback callback to receive events.
*/
public void registerCallback(@Nullable AutofillCallback callback) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
synchronized (mLock) {
if (callback == null) return;
@@ -682,6 +744,9 @@
* @param callback callback to stop receiving events.
*/
public void unregisterCallback(@Nullable AutofillCallback callback) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
synchronized (mLock) {
if (callback == null || mCallback == null || callback != mCallback) return;
@@ -859,6 +924,10 @@
return view;
}
+ private boolean hasAutofillFeature() {
+ return mService != null;
+ }
+
/**
* Callback for auto-fill related events.
*
@@ -999,5 +1068,19 @@
});
}
}
+
+ @Override
+ public void startIntentSender(IntentSender intentSender) {
+ final AutofillManager afm = mAfm.get();
+ if (afm != null) {
+ afm.mContext.getMainThreadHandler().post(() -> {
+ try {
+ afm.mContext.startIntentSender(intentSender, null, 0, 0, 0);
+ } catch (IntentSender.SendIntentException e) {
+ Log.e(TAG, "startIntentSender() failed for intent:" + intentSender, e);
+ }
+ });
+ }
+ }
}
}
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 20d09ae..68b3ccabc 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -35,10 +35,11 @@
boolean hasCallback, int flags, String packageName);
boolean restoreSession(int sessionId, in IBinder activityToken, in IBinder appCallback);
void setWindow(int sessionId, in IBinder windowToken);
- oneway void updateSession(int sessionId, in AutofillId id, in Rect bounds,
+ void updateSession(int sessionId, in AutofillId id, in Rect bounds,
in AutofillValue value, int flags, int userId);
void finishSession(int sessionId, int userId);
void cancelSession(int sessionId, int userId);
void setAuthenticationResult(in Bundle data, int sessionId, int userId);
- oneway void setHasCallback(int sessionId, int userId, boolean hasIt);
+ void setHasCallback(int sessionId, int userId, boolean hasIt);
+ void disableOwnedAutofillServices(int userId);
}
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 7bea174..176eaac 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -59,7 +59,12 @@
void requestHideFillUi(in IBinder windowToken, in AutofillId id);
/**
- * Nitifies no fill UI will be shown.
+ * Notifies no fill UI will be shown.
*/
void notifyNoFillUi(in IBinder windowToken, in AutofillId id);
+
+ /**
+ * Starts the provided intent sender
+ */
+ void startIntentSender(in IntentSender intentSender);
}
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 71809bd..f0645b8 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -57,7 +57,6 @@
* @attr ref android.R.styleable#InputMethod_settingsActivity
* @attr ref android.R.styleable#InputMethod_isDefault
* @attr ref android.R.styleable#InputMethod_supportsSwitchingToNextInputMethod
- * @attr ref android.R.styleable#InputMethod_supportsDismissingWindow
*/
public final class InputMethodInfo implements Parcelable {
static final String TAG = "InputMethodInfo";
@@ -105,11 +104,6 @@
private final boolean mSupportsSwitchingToNextInputMethod;
/**
- * The flag whether this IME supports ways to dismiss its window (e.g. dismiss button.)
- */
- private final boolean mSupportsDismissingWindow;
-
- /**
* @param service the {@link ResolveInfo} corresponds in which the IME is implemented.
* @return a unique ID to be returned by {@link #getId()}. We have used
* {@link ComponentName#flattenToShortString()} for this purpose (and it is already
@@ -151,7 +145,6 @@
mId = computeId(service);
boolean isAuxIme = true;
boolean supportsSwitchingToNextInputMethod = false; // false as default
- boolean supportsDismissingWindow = false; // false as default
mForceDefault = false;
PackageManager pm = context.getPackageManager();
@@ -191,8 +184,6 @@
supportsSwitchingToNextInputMethod = sa.getBoolean(
com.android.internal.R.styleable.InputMethod_supportsSwitchingToNextInputMethod,
false);
- supportsDismissingWindow = sa.getBoolean(
- com.android.internal.R.styleable.InputMethod_supportsDismissingWindow, false);
sa.recycle();
final int depth = parser.getDepth();
@@ -263,7 +254,6 @@
mIsDefaultResId = isDefaultResId;
mIsAuxIme = isAuxIme;
mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
- mSupportsDismissingWindow = supportsDismissingWindow;
}
InputMethodInfo(Parcel source) {
@@ -272,7 +262,6 @@
mIsDefaultResId = source.readInt();
mIsAuxIme = source.readInt() == 1;
mSupportsSwitchingToNextInputMethod = source.readInt() == 1;
- mSupportsDismissingWindow = source.readInt() == 1;
mService = ResolveInfo.CREATOR.createFromParcel(source);
mSubtypes = new InputMethodSubtypeArray(source);
mForceDefault = false;
@@ -285,8 +274,7 @@
CharSequence label, String settingsActivity) {
this(buildDummyResolveInfo(packageName, className, label), false /* isAuxIme */,
settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
- false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
- true /* supportsDismissingWindow */);
+ false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */);
}
/**
@@ -297,8 +285,7 @@
String settingsActivity, List<InputMethodSubtype> subtypes, int isDefaultResId,
boolean forceDefault) {
this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
- true /* supportsSwitchingToNextInputMethod */,
- true /* supportsDismissingWindow */);
+ true /* supportsSwitchingToNextInputMethod */);
}
/**
@@ -307,7 +294,7 @@
*/
public InputMethodInfo(ResolveInfo ri, boolean isAuxIme, String settingsActivity,
List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
- boolean supportsSwitchingToNextInputMethod, boolean supportsDismissingWindow) {
+ boolean supportsSwitchingToNextInputMethod) {
final ServiceInfo si = ri.serviceInfo;
mService = ri;
mId = new ComponentName(si.packageName, si.name).flattenToShortString();
@@ -317,7 +304,6 @@
mSubtypes = new InputMethodSubtypeArray(subtypes);
mForceDefault = forceDefault;
mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
- mSupportsDismissingWindow = supportsDismissingWindow;
}
private static ResolveInfo buildDummyResolveInfo(String packageName, String className,
@@ -458,8 +444,7 @@
public void dump(Printer pw, String prefix) {
pw.println(prefix + "mId=" + mId
+ " mSettingsActivityName=" + mSettingsActivityName
- + " mSupportsSwitchingToNextInputMethod=" + mSupportsSwitchingToNextInputMethod
- + " mSupportsDismissingWindow=" + mSupportsDismissingWindow);
+ + " mSupportsSwitchingToNextInputMethod=" + mSupportsSwitchingToNextInputMethod);
pw.println(prefix + "mIsDefaultResId=0x"
+ Integer.toHexString(mIsDefaultResId));
pw.println(prefix + "Service:");
@@ -512,14 +497,6 @@
}
/**
- * @return true if this input method supports ways to dismiss its window.
- * @hide
- */
- public boolean supportsDismissingWindow() {
- return mSupportsDismissingWindow;
- }
-
- /**
* Used to package this object into a {@link Parcel}.
*
* @param dest The {@link Parcel} to be written.
@@ -532,7 +509,6 @@
dest.writeInt(mIsDefaultResId);
dest.writeInt(mIsAuxIme ? 1 : 0);
dest.writeInt(mSupportsSwitchingToNextInputMethod ? 1 : 0);
- dest.writeInt(mSupportsDismissingWindow ? 1 : 0);
mService.writeToParcel(dest, flags);
mSubtypes.writeToParcel(dest);
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6213a63..9202889 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1731,7 +1731,14 @@
*
* @param addr the string to search for addresses
* @return the address, or if no address is found, null
+ *
+ * @deprecated findAddress is deprecated. It only supports a subset of US
+ * addresses and has a high false positive rate. Calling findAddress also causes
+ * WebView to be loaded into the app, which significantly increases memory usage
+ * if the app doesn't already use WebView. Use {@link TextClassifier} instead for
+ * classifying text and finding addresses.
*/
+ @Deprecated
public static String findAddress(String addr) {
// TODO: Rewrite this in Java so it is not needed to start up chromium
// Could also be deprecated
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 5725b49..be54869 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -216,7 +216,7 @@
* @see #setFocusable(boolean)
* @see #checkFocus()
*/
- private boolean mDesiredFocusableState;
+ private int mDesiredFocusableState = FOCUSABLE_AUTO;
private boolean mDesiredFocusableInTouchModeState;
/** Lazily-constructed runnable for dispatching selection events. */
@@ -250,6 +250,12 @@
if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
}
+
+ mDesiredFocusableState = getFocusable();
+ if (mDesiredFocusableState == FOCUSABLE_AUTO) {
+ // Starts off without an adapter, so NOT_FOCUSABLE by default.
+ super.setFocusable(NOT_FOCUSABLE);
+ }
}
/**
@@ -710,16 +716,16 @@
}
@Override
- public void setFocusable(boolean focusable) {
+ public void setFocusable(@Focusable int focusable) {
final T adapter = getAdapter();
final boolean empty = adapter == null || adapter.getCount() == 0;
mDesiredFocusableState = focusable;
- if (!focusable) {
+ if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
mDesiredFocusableInTouchModeState = false;
}
- super.setFocusable(focusable && (!empty || isInFilterMode()));
+ super.setFocusable((!empty || isInFilterMode()) ? focusable : NOT_FOCUSABLE);
}
@Override
@@ -729,7 +735,7 @@
mDesiredFocusableInTouchModeState = focusable;
if (focusable) {
- mDesiredFocusableState = true;
+ mDesiredFocusableState = FOCUSABLE;
}
super.setFocusableInTouchMode(focusable && (!empty || isInFilterMode()));
@@ -743,7 +749,7 @@
// for the client, see View.setFocusableInTouchMode() comments for more
// details
super.setFocusableInTouchMode(focusable && mDesiredFocusableInTouchModeState);
- super.setFocusable(focusable && mDesiredFocusableState);
+ super.setFocusable(focusable ? mDesiredFocusableState : NOT_FOCUSABLE);
if (mEmptyView != null) {
updateEmptyStatus((adapter == null) || adapter.isEmpty());
}
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 06d4868..6df76fa 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -151,8 +151,8 @@
mShowRevokeUI = showRevokeUI;
mPackageName = packageName;
- ImageView permGrpIcon = (ImageView) findViewById(R.id.perm_icon);
- TextView permNameView = (TextView) findViewById(R.id.perm_name);
+ ImageView permGrpIcon = findViewById(R.id.perm_icon);
+ TextView permNameView = findViewById(R.id.perm_name);
PackageManager pm = getContext().getPackageManager();
Drawable icon = null;
diff --git a/core/java/android/widget/Button.java b/core/java/android/widget/Button.java
index 09e09b7..09ba553 100644
--- a/core/java/android/widget/Button.java
+++ b/core/java/android/widget/Button.java
@@ -37,7 +37,7 @@
*
* setContentView(R.layout.content_layout_id);
*
- * final Button button = (Button) findViewById(R.id.button_id);
+ * final Button button = findViewById(R.id.button_id);
* button.setOnClickListener(new View.OnClickListener() {
* public void onClick(View v) {
* // Perform action on click
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index 0f0e6c3..be0967f 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -124,13 +124,13 @@
addView(child);
}
- mPrevButton = (ImageButton) findViewById(R.id.prev);
+ mPrevButton = findViewById(R.id.prev);
mPrevButton.setOnClickListener(mOnClickListener);
- mNextButton = (ImageButton) findViewById(R.id.next);
+ mNextButton = findViewById(R.id.next);
mNextButton.setOnClickListener(mOnClickListener);
- mViewPager = (ViewPager) findViewById(R.id.day_picker_view_pager);
+ mViewPager = findViewById(R.id.day_picker_view_pager);
mViewPager.setAdapter(mAdapter);
mViewPager.setOnPageChangeListener(mOnPageChangedListener);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index faa2310..4fb7b19 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1915,11 +1915,10 @@
}
boolean clamped = layout.shouldClampCursor(line);
- updateCursorPosition(0, top, middle, layout.getPrimaryHorizontal(offset, clamped, true));
+ updateCursorPosition(0, top, middle, layout.getPrimaryHorizontal(offset, clamped));
if (mCursorCount == 2) {
- updateCursorPosition(1, middle, bottom,
- layout.getSecondaryHorizontal(offset, clamped, true));
+ updateCursorPosition(1, middle, bottom, layout.getSecondaryHorizontal(offset, clamped));
}
}
@@ -4340,7 +4339,7 @@
updateSelection(offset);
addPositionToTouchUpFilter(offset);
}
- final int line = getLineForOffset(layout, offset);
+ final int line = layout.getLineForOffset(offset);
mPrevLine = line;
mPositionX = getCursorHorizontalPosition(layout, offset) - mHotspotX
@@ -4367,15 +4366,6 @@
return (int) (getHorizontal(layout, offset) - 0.5f);
}
- /**
- * @param layout Text layout.
- * @param offset Character offset for the cursor.
- * @return The line the cursor should be at.
- */
- int getLineForOffset(Layout layout, int offset) {
- return layout.getLineForOffset(offset);
- }
-
@Override
public void updatePosition(int parentPositionX, int parentPositionY,
boolean parentPositionChanged, boolean parentScrolled) {
@@ -4804,7 +4794,7 @@
|| !isStartHandle() && initialOffset <= anotherHandleOffset) {
// Handles have crossed, bound it to the first selected line and
// adjust by word / char as normal.
- currLine = getLineForOffset(layout, anotherHandleOffset, !isStartHandle());
+ currLine = layout.getLineForOffset(anotherHandleOffset);
initialOffset = getOffsetAtCoordinate(layout, currLine, x);
}
@@ -4876,18 +4866,14 @@
if (isExpanding) {
// User is increasing the selection.
int wordBoundary = isStartHandle() ? wordStart : wordEnd;
- final boolean atLineBoundary = layout.getLineStart(currLine) == offset
- || layout.getLineEnd(currLine) == offset;
- final boolean atWordBoundary = getWordIteratorWithText().isBoundary(offset);
- final boolean snapToWord = !(atLineBoundary && atWordBoundary)
- && (!mInWord
- || (isStartHandle() ? currLine < mPrevLine : currLine > mPrevLine))
- && atRtl == isAtRtlRun(layout, wordBoundary);
+ final boolean snapToWord = (!mInWord
+ || (isStartHandle() ? currLine < mPrevLine : currLine > mPrevLine))
+ && atRtl == isAtRtlRun(layout, wordBoundary);
if (snapToWord) {
// Sometimes words can be broken across lines (Chinese, hyphenation).
// We still snap to the word boundary but we only use the letters on the
// current line to determine if the user is far enough into the word to snap.
- if (getLineForOffset(layout, wordBoundary) != currLine) {
+ if (layout.getLineForOffset(wordBoundary) != currLine) {
wordBoundary = isStartHandle()
? layout.getLineStart(currLine) : layout.getLineEnd(currLine);
}
@@ -5035,29 +5021,12 @@
}
private float getHorizontal(@NonNull Layout layout, int offset, boolean startHandle) {
- final int line = getLineForOffset(layout, offset);
+ final int line = layout.getLineForOffset(offset);
final int offsetToCheck = startHandle ? offset : Math.max(offset - 1, 0);
final boolean isRtlChar = layout.isRtlCharAt(offsetToCheck);
final boolean isRtlParagraph = layout.getParagraphDirection(line) == -1;
return (isRtlChar == isRtlParagraph)
- ? layout.getPrimaryHorizontal(offset, false, startHandle)
- : layout.getSecondaryHorizontal(offset, false, startHandle);
- }
-
- @Override
- public int getLineForOffset(@NonNull Layout layout, int offset) {
- return getLineForOffset(layout, offset, isStartHandle());
- }
-
- private int getLineForOffset(@NonNull Layout layout, int offset, boolean startHandle) {
- final int line = layout.getLineForOffset(offset);
- if (!startHandle && line > 0 && layout.getLineStart(line) == offset
- && mTextView.getText().charAt(offset - 1) != '\n') {
- // If end handle is at a line break in a paragraph, the handle should be at the
- // previous line.
- return line - 1;
- }
- return line;
+ ? layout.getPrimaryHorizontal(offset) : layout.getSecondaryHorizontal(offset);
}
@Override
diff --git a/core/java/android/widget/MultiAutoCompleteTextView.java b/core/java/android/widget/MultiAutoCompleteTextView.java
index 2152e43..f348d73 100644
--- a/core/java/android/widget/MultiAutoCompleteTextView.java
+++ b/core/java/android/widget/MultiAutoCompleteTextView.java
@@ -43,7 +43,7 @@
*
* ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
* android.R.layout.simple_dropdown_item_1line, COUNTRIES);
- * MultiAutoCompleteTextView textView = (MultiAutoCompleteTextView) findViewById(R.id.edit);
+ * MultiAutoCompleteTextView textView = findViewById(R.id.edit);
* textView.setAdapter(adapter);
* textView.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
* }
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 662e640..7bdd6da 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -706,7 +706,7 @@
// increment button
if (!mHasSelectorWheel) {
- mIncrementButton = (ImageButton) findViewById(R.id.increment);
+ mIncrementButton = findViewById(R.id.increment);
mIncrementButton.setOnClickListener(onClickListener);
mIncrementButton.setOnLongClickListener(onLongClickListener);
} else {
@@ -715,7 +715,7 @@
// decrement button
if (!mHasSelectorWheel) {
- mDecrementButton = (ImageButton) findViewById(R.id.decrement);
+ mDecrementButton = findViewById(R.id.decrement);
mDecrementButton.setOnClickListener(onClickListener);
mDecrementButton.setOnLongClickListener(onLongClickListener);
} else {
@@ -723,7 +723,7 @@
}
// input text
- mInputText = (EditText) findViewById(R.id.numberpicker_input);
+ mInputText = findViewById(R.id.numberpicker_input);
mInputText.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 5505f2f..9245134 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1787,7 +1787,7 @@
@Override
public Action initActionAsync(ViewTree root, ViewGroup rootParent, OnClickHandler handler) {
- final TextView target = (TextView) root.findViewById(viewId);
+ final TextView target = root.findViewById(viewId);
if (target == null) return ACTION_NOOP;
TextViewDrawableAction copy = useIcons ?
@@ -3688,12 +3688,12 @@
createTree();
}
- public View findViewById(int id) {
+ public <T extends View> T findViewById(int id) {
if (mChildren == null) {
return mRoot.findViewById(id);
}
ViewTree tree = findViewTreeById(id);
- return tree == null ? null : tree.mRoot;
+ return tree == null ? null : (T) tree.mRoot;
}
public void addChild(ViewTree child) {
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 7e2cadf..8de17c0 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -136,7 +136,7 @@
mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
*/
public void setup() {
- mTabWidget = (TabWidget) findViewById(com.android.internal.R.id.tabs);
+ mTabWidget = findViewById(com.android.internal.R.id.tabs);
if (mTabWidget == null) {
throw new RuntimeException(
"Your TabHost must have a TabWidget whose id attribute is 'android.R.id.tabs'");
@@ -171,7 +171,7 @@
}
});
- mTabContent = (FrameLayout) findViewById(com.android.internal.R.id.tabcontent);
+ mTabContent = findViewById(com.android.internal.R.id.tabcontent);
if (mTabContent == null) {
throw new RuntimeException(
"Your TabHost must have a FrameLayout whose id attribute is "
diff --git a/core/java/android/widget/TextInputTimePickerView.java b/core/java/android/widget/TextInputTimePickerView.java
index 0183343..11b7514d 100644
--- a/core/java/android/widget/TextInputTimePickerView.java
+++ b/core/java/android/widget/TextInputTimePickerView.java
@@ -76,12 +76,12 @@
inflate(context, R.layout.time_picker_text_input_material, this);
- mHourEditText = (EditText) findViewById(R.id.input_hour);
- mMinuteEditText = (EditText) findViewById(R.id.input_minute);
- mInputSeparatorView = (TextView) findViewById(R.id.input_separator);
- mErrorLabel = (TextView) findViewById(R.id.label_error);
- mHourLabel = (TextView) findViewById(R.id.label_hour);
- mMinuteLabel = (TextView) findViewById(R.id.label_minute);
+ mHourEditText = findViewById(R.id.input_hour);
+ mMinuteEditText = findViewById(R.id.input_minute);
+ mInputSeparatorView = findViewById(R.id.input_separator);
+ mErrorLabel = findViewById(R.id.label_error);
+ mHourLabel = findViewById(R.id.label_hour);
+ mMinuteLabel = findViewById(R.id.label_minute);
mHourEditText.addTextChangedListener(new TextWatcher() {
@Override
@@ -109,7 +109,7 @@
}
});
- mAmPmSpinner = (Spinner) findViewById(R.id.am_pm_spinner);
+ mAmPmSpinner = findViewById(R.id.am_pm_spinner);
final String[] amPmStrings = TimePicker.getAmPmStrings(context);
ArrayAdapter<CharSequence> adapter =
new ArrayAdapter<CharSequence>(context, R.layout.simple_spinner_dropdown_item);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index fcab703..f9f10af 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -16,7 +16,6 @@
package android.widget;
-import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH;
import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX;
import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY;
@@ -59,6 +58,7 @@
import android.graphics.fonts.FontVariationAxis;
import android.icu.text.DecimalFormatSymbols;
import android.os.AsyncTask;
+import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.LocaleList;
import android.os.Parcel;
@@ -408,7 +408,7 @@
public Drawables(Context context) {
final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
- mIsRtlCompatibilityMode = targetSdkVersion < JELLY_BEAN_MR1
+ mIsRtlCompatibilityMode = targetSdkVersion < VERSION_CODES.JELLY_BEAN_MR1
|| !context.getApplicationInfo().hasRtlSupport();
mOverride = false;
}
@@ -1363,7 +1363,7 @@
== (EditorInfo.TYPE_CLASS_NUMBER | EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD);
mUseInternationalizedInput =
- context.getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.O;
+ context.getApplicationInfo().targetSdkVersion >= VERSION_CODES.O;
if (inputMethod != null) {
Class<?> c;
@@ -1408,7 +1408,7 @@
} else if (numeric != 0) {
createEditorIfNeeded();
mEditor.mKeyListener = DigitsKeyListener.getInstance(
- mUseInternationalizedInput ? getTextLocale() : null,
+ null, // locale
(numeric & SIGNED) != 0,
(numeric & DECIMAL) != 0);
inputType = mEditor.mKeyListener.getInputType();
@@ -3400,11 +3400,14 @@
return mTextPaint.getTextLocales();
}
- private void changeListenerLocaleTo(@NonNull Locale locale) {
+ private void changeListenerLocaleTo(@Nullable Locale locale) {
if (mListenerChanged) {
// If a listener has been explicitly set, don't change it. We may break something.
return;
}
+ // The following null check is not absolutely necessary since all calling points of
+ // changeListenerLocaleTo() guarantee a non-null mEditor at the moment. But this is left
+ // here in case others would want to call this method in the future.
if (mEditor != null) {
KeyListener listener = mEditor.mKeyListener;
if (listener instanceof DigitsKeyListener) {
@@ -3418,8 +3421,17 @@
} else {
return;
}
+ final boolean wasPasswordType = isPasswordInputType(mEditor.mInputType);
setKeyListenerOnly(listener);
setInputTypeFromEditor();
+ if (wasPasswordType) {
+ final int newInputClass = mEditor.mInputType & EditorInfo.TYPE_MASK_CLASS;
+ if (newInputClass == EditorInfo.TYPE_CLASS_TEXT) {
+ mEditor.mInputType |= EditorInfo.TYPE_TEXT_VARIATION_PASSWORD;
+ } else if (newInputClass == EditorInfo.TYPE_CLASS_NUMBER) {
+ mEditor.mInputType |= EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD;
+ }
+ }
}
}
@@ -3434,7 +3446,6 @@
public void setTextLocale(@NonNull Locale locale) {
mLocalesChanged = true;
mTextPaint.setTextLocale(locale);
- changeListenerLocaleTo(locale);
if (mLayout != null) {
nullLayouts();
requestLayout();
@@ -3456,7 +3467,6 @@
public void setTextLocales(@NonNull @Size(min = 1) LocaleList locales) {
mLocalesChanged = true;
mTextPaint.setTextLocales(locales);
- changeListenerLocaleTo(locales.get(0));
if (mLayout != null) {
nullLayouts();
requestLayout();
@@ -3468,9 +3478,7 @@
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (!mLocalesChanged) {
- final LocaleList locales = LocaleList.getDefault();
- mTextPaint.setTextLocales(locales);
- changeListenerLocaleTo(locales.get(0));
+ mTextPaint.setTextLocales(LocaleList.getDefault());
if (mLayout != null) {
nullLayouts();
requestLayout();
@@ -5586,6 +5594,29 @@
mEditor.mInputType = type;
}
+ /**
+ * @return {@code null} if the key listener should use pre-O (locale-independent). Otherwise
+ * a {@code Locale} object that can be used to customize key various listeners.
+ * @see DateKeyListener#getInstance(Locale)
+ * @see DateTimeKeyListener#getInstance(Locale)
+ * @see DigitsKeyListener#getInstance(Locale)
+ * @see TimeKeyListener#getInstance(Locale)
+ */
+ @Nullable
+ private Locale getCustomLocaleForKeyListenerOrNull() {
+ if (!mUseInternationalizedInput) {
+ // If the application does not target O, stick to the previous behavior.
+ return null;
+ }
+ final LocaleList locales = getImeHintLocales();
+ if (locales == null) {
+ // If the application does not explicitly specify IME hint locale, also stick to the
+ // previous behavior.
+ return null;
+ }
+ return locales.get(0);
+ }
+
private void setInputType(int type, boolean direct) {
final int cls = type & EditorInfo.TYPE_MASK_CLASS;
KeyListener input;
@@ -5603,15 +5634,26 @@
}
input = TextKeyListener.getInstance(autotext, cap);
} else if (cls == EditorInfo.TYPE_CLASS_NUMBER) {
+ final Locale locale = getCustomLocaleForKeyListenerOrNull();
input = DigitsKeyListener.getInstance(
- mUseInternationalizedInput ? getTextLocale() : null,
+ locale,
(type & EditorInfo.TYPE_NUMBER_FLAG_SIGNED) != 0,
(type & EditorInfo.TYPE_NUMBER_FLAG_DECIMAL) != 0);
- if (mUseInternationalizedInput) {
- type = input.getInputType(); // Override type, if necessary for i18n.
+ if (locale != null) {
+ // Override type, if necessary for i18n.
+ int newType = input.getInputType();
+ final int newClass = newType & EditorInfo.TYPE_MASK_CLASS;
+ if (newClass != EditorInfo.TYPE_CLASS_NUMBER) {
+ // The class is different from the original class. So we need to override
+ // 'type'. But we want to keep the password flag if it's there.
+ if ((type & EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD) != 0) {
+ newType |= EditorInfo.TYPE_TEXT_VARIATION_PASSWORD;
+ }
+ type = newType;
+ }
}
} else if (cls == EditorInfo.TYPE_CLASS_DATETIME) {
- final Locale locale = mUseInternationalizedInput ? getTextLocale() : null;
+ final Locale locale = getCustomLocaleForKeyListenerOrNull();
switch (type & EditorInfo.TYPE_MASK_VARIATION) {
case EditorInfo.TYPE_DATETIME_VARIATION_DATE:
input = DateKeyListener.getInstance(locale);
@@ -5884,6 +5926,9 @@
* Change "hint" locales associated with the text view, which will be reported to an IME with
* {@link EditorInfo#hintLocales} when it has focus.
*
+ * Starting with Android O, this also causes internationalized listeners to be created (or
+ * change locale) based on the first locale in the input locale list.
+ *
* <p><strong>Note:</strong> If you want new "hint" to take effect immediately you need to
* call {@link InputMethodManager#restartInput(View)}.</p>
* @param hintLocales List of the languages that the user is supposed to switch to no matter
@@ -5895,6 +5940,9 @@
createEditorIfNeeded();
mEditor.createInputContentTypeIfNeeded();
mEditor.mInputContentType.imeHintLocales = hintLocales;
+ if (mUseInternationalizedInput) {
+ changeListenerLocaleTo(hintLocales == null ? null : hintLocales.get(0));
+ }
}
/**
@@ -8470,7 +8518,7 @@
// right where it is most likely to be annoying.
final boolean clamped = grav > 0;
// FIXME: Is it okay to truncate this, or should we round?
- final int x = (int) layout.getPrimaryHorizontal(offset, clamped, true);
+ final int x = (int) layout.getPrimaryHorizontal(offset, clamped);
final int top = layout.getLineTop(line);
final int bottom = layout.getLineTop(line + 1);
diff --git a/core/java/android/widget/TwoLineListItem.java b/core/java/android/widget/TwoLineListItem.java
index 0445ebd..553b86e 100644
--- a/core/java/android/widget/TwoLineListItem.java
+++ b/core/java/android/widget/TwoLineListItem.java
@@ -70,8 +70,8 @@
protected void onFinishInflate() {
super.onFinishInflate();
- mText1 = (TextView) findViewById(com.android.internal.R.id.text1);
- mText2 = (TextView) findViewById(com.android.internal.R.id.text2);
+ mText1 = findViewById(com.android.internal.R.id.text1);
+ mText2 = findViewById(com.android.internal.R.id.text2);
}
/**
diff --git a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
index ee5d339..032c775 100644
--- a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
+++ b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
@@ -59,13 +59,13 @@
String component = Settings.Secure.getString(getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
if (TextUtils.isEmpty(component)) {
- TextView prompt = (TextView) findViewById(R.id.accessibility_button_prompt);
+ TextView prompt = findViewById(R.id.accessibility_button_prompt);
prompt.setVisibility(View.VISIBLE);
}
mMagnificationTarget = new AccessibilityButtonTarget(this, MAGNIFICATION_COMPONENT_ID,
R.string.accessibility_magnification_chooser_text,
- R.drawable.resolver_icon_placeholder);
+ R.drawable.ic_accessibility_magnification);
mTargets = getServiceAccessibilityButtonTargets(this);
if (Settings.Secure.getInt(getContentResolver(),
@@ -78,7 +78,7 @@
finish();
}
- GridView gridview = (GridView) findViewById(R.id.accessibility_button_chooser_grid);
+ GridView gridview = findViewById(R.id.accessibility_button_chooser_grid);
gridview.setAdapter(new TargetAdapter());
gridview.setOnItemClickListener((parent, view, position, id) -> {
onTargetSelected(mTargets.get(position));
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 3a31b37..35d4ba8 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -38,6 +38,7 @@
int checkPackage(int uid, String packageName);
List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops);
List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops);
+ List<AppOpsManager.PackageOps> getUidOps(int uid, in int[] ops);
void setUidMode(int code, int uid, int mode);
void setMode(int code, int uid, String packageName, int mode);
void resetAllModes(int reqUserId, String reqPackageName);
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 622b708..b596678 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -287,7 +287,7 @@
return;
}
- final ResolverDrawerLayout rdl = (ResolverDrawerLayout) findViewById(R.id.contentPanel);
+ final ResolverDrawerLayout rdl = findViewById(R.id.contentPanel);
if (rdl != null) {
rdl.setOnDismissedListener(new ResolverDrawerLayout.OnDismissedListener() {
@Override
@@ -922,10 +922,10 @@
}
- mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
+ mAdapterView = findViewById(R.id.resolver_list);
if (count == 0 && mAdapter.mPlaceholderCount == 0) {
- final TextView emptyView = (TextView) findViewById(R.id.empty);
+ final TextView emptyView = findViewById(R.id.empty);
emptyView.setVisibility(View.VISIBLE);
mAdapterView.setVisibility(View.GONE);
} else {
@@ -959,7 +959,7 @@
public void setTitleAndIcon() {
if (mAdapter.getCount() == 0 && mAdapter.mPlaceholderCount == 0) {
- final TextView titleView = (TextView) findViewById(R.id.title);
+ final TextView titleView = findViewById(R.id.title);
if (titleView != null) {
titleView.setVisibility(View.GONE);
}
@@ -970,14 +970,14 @@
: getTitleForAction(getTargetIntent().getAction(), mDefaultTitleResId);
if (!TextUtils.isEmpty(title)) {
- final TextView titleView = (TextView) findViewById(R.id.title);
+ final TextView titleView = findViewById(R.id.title);
if (titleView != null) {
titleView.setText(title);
}
setTitle(title);
// Try to initialize the title icon if we have a view for it and a title to match
- final ImageView titleIcon = (ImageView) findViewById(R.id.title_icon);
+ final ImageView titleIcon = findViewById(R.id.title_icon);
if (titleIcon != null) {
ApplicationInfo ai = null;
try {
@@ -994,7 +994,7 @@
}
}
- final ImageView iconView = (ImageView) findViewById(R.id.icon);
+ final ImageView iconView = findViewById(R.id.icon);
final DisplayResolveInfo iconInfo = mAdapter.getFilteredItem();
if (iconView != null && iconInfo != null) {
new LoadIconIntoViewTask(iconInfo, iconView).execute();
@@ -1003,7 +1003,7 @@
public void resetAlwaysOrOnceButtonBar() {
if (mSupportsAlwaysUseOption) {
- final ViewGroup buttonLayout = (ViewGroup) findViewById(R.id.button_bar);
+ final ViewGroup buttonLayout = findViewById(R.id.button_bar);
if (buttonLayout != null) {
buttonLayout.setVisibility(View.VISIBLE);
mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 916241c..7fbfb8b 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -114,7 +114,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 153 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 154 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -2071,15 +2071,16 @@
@Override
public boolean reset(boolean detachIfReset) {
boolean active = false;
+ // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach().
+ active |= !mSubTimer.reset(false);
active |= !super.reset(detachIfReset);
- active |= !mSubTimer.reset(detachIfReset);
return !active;
}
@Override
public void detach() {
- super.detach();
mSubTimer.detach();
+ super.detach();
}
@Override
@@ -5462,7 +5463,6 @@
LongSamplingCounter mUserCpuTime;
LongSamplingCounter mSystemCpuTime;
- LongSamplingCounter mCpuPower;
LongSamplingCounter[][] mCpuClusterSpeed;
/**
@@ -5473,7 +5473,7 @@
/**
* The statistics we have collected for this uid's syncs.
*/
- final OverflowArrayMap<StopwatchTimer> mSyncStats;
+ final OverflowArrayMap<DualTimer> mSyncStats;
/**
* The statistics we have collected for this uid's jobs.
@@ -5510,17 +5510,16 @@
mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
- mCpuPower = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
@Override public Wakelock instantiateObject() {
return new Wakelock(mBsi, Uid.this);
}
};
- mSyncStats = mBsi.new OverflowArrayMap<StopwatchTimer>(uid) {
- @Override public StopwatchTimer instantiateObject() {
- return new StopwatchTimer(mBsi.mClocks, Uid.this, SYNC, null,
- mBsi.mOnBatteryTimeBase);
+ mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
+ @Override public DualTimer instantiateObject() {
+ return new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
+ mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
}
};
mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
@@ -6161,11 +6160,6 @@
}
@Override
- public long getCpuPowerMaUs(int which) {
- return mCpuPower.getCountLocked(which);
- }
-
- @Override
public long getTimeAtCpuSpeed(int cluster, int step, int which) {
if (mCpuClusterSpeed != null) {
if (cluster >= 0 && cluster < mCpuClusterSpeed.length) {
@@ -6310,7 +6304,6 @@
mUserCpuTime.reset(false);
mSystemCpuTime.reset(false);
- mCpuPower.reset(false);
if (mCpuClusterSpeed != null) {
for (LongSamplingCounter[] speeds : mCpuClusterSpeed) {
@@ -6337,9 +6330,9 @@
}
}
mWakelockStats.cleanup();
- final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
+ final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
for (int is=syncStats.size()-1; is>=0; is--) {
- StopwatchTimer timer = syncStats.valueAt(is);
+ DualTimer timer = syncStats.valueAt(is);
if (timer.reset(false)) {
syncStats.removeAt(is);
timer.detach();
@@ -6476,7 +6469,6 @@
mUserCpuTime.detach();
mSystemCpuTime.detach();
- mCpuPower.detach();
if (mCpuClusterSpeed != null) {
for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) {
@@ -6509,12 +6501,12 @@
wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
}
- final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
+ final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
int NS = syncStats.size();
out.writeInt(NS);
for (int is=0; is<NS; is++) {
out.writeString(syncStats.keyAt(is));
- StopwatchTimer timer = syncStats.valueAt(is);
+ DualTimer timer = syncStats.valueAt(is);
Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
}
@@ -6676,7 +6668,6 @@
mUserCpuTime.writeToParcel(out);
mSystemCpuTime.writeToParcel(out);
- mCpuPower.writeToParcel(out);
if (mCpuClusterSpeed != null) {
out.writeInt(1);
@@ -6733,8 +6724,8 @@
for (int j = 0; j < numSyncs; j++) {
String syncName = in.readString();
if (in.readInt() != 0) {
- mSyncStats.add(syncName,
- new StopwatchTimer(mBsi.mClocks, Uid.this, SYNC, null, timeBase, in));
+ mSyncStats.add(syncName, new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
+ mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
}
}
@@ -6912,7 +6903,6 @@
mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
- mCpuPower = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
if (in.readInt() != 0) {
int numCpuClusters = in.readInt();
@@ -8001,7 +7991,7 @@
}
public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
- StopwatchTimer timer = mSyncStats.instantiateObject();
+ DualTimer timer = mSyncStats.instantiateObject();
timer.readSummaryFromParcelLocked(in);
mSyncStats.add(name, timer);
}
@@ -8054,14 +8044,14 @@
}
public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
- StopwatchTimer t = mSyncStats.startObject(name);
+ DualTimer t = mSyncStats.startObject(name);
if (t != null) {
t.startRunningLocked(elapsedRealtimeMs);
}
}
public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
- StopwatchTimer t = mSyncStats.stopObject(name);
+ DualTimer t = mSyncStats.stopObject(name);
if (t != null) {
t.stopRunningLocked(elapsedRealtimeMs);
}
@@ -9704,8 +9694,7 @@
mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null :
new KernelUidCpuTimeReader.Callback() {
@Override
- public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs,
- long powerMaUs) {
+ public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) {
final Uid u = getUidStatsLocked(mapUid(uid));
// Accumulate the total system and user time.
@@ -9719,7 +9708,7 @@
TimeUtils.formatDuration(userTimeUs / 1000, sb);
sb.append(" s=");
TimeUtils.formatDuration(systemTimeUs / 1000, sb);
- sb.append(" p=").append(powerMaUs / 1000).append("mAms\n");
+ sb.append("\n");
}
if (numWakelocksF > 0) {
@@ -9735,13 +9724,11 @@
TimeUtils.formatDuration(userTimeUs / 1000, sb);
sb.append(" s=");
TimeUtils.formatDuration(systemTimeUs / 1000, sb);
- sb.append(" p=").append(powerMaUs / 1000).append("mAms");
Slog.d(TAG, sb.toString());
}
u.mUserCpuTime.addCountLocked(userTimeUs);
u.mSystemCpuTime.addCountLocked(systemTimeUs);
- u.mCpuPower.addCountLocked(powerMaUs);
// Add the cpu speeds to this UID. These are used as a ratio
// for computing the power this UID used.
@@ -11035,7 +11022,6 @@
u.mUserCpuTime.readSummaryFromParcelLocked(in);
u.mSystemCpuTime.readSummaryFromParcelLocked(in);
- u.mCpuPower.readSummaryFromParcelLocked(in);
if (in.readInt() != 0) {
final int numClusters = in.readInt();
@@ -11431,7 +11417,6 @@
u.mUserCpuTime.writeSummaryFromParcelLocked(out);
u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
- u.mCpuPower.writeSummaryFromParcelLocked(out);
if (u.mCpuClusterSpeed != null) {
out.writeInt(1);
@@ -11502,7 +11487,7 @@
}
}
- final ArrayMap<String, StopwatchTimer> syncStats = u.mSyncStats.getMap();
+ final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
int NS = syncStats.size();
out.writeInt(NS);
for (int is=0; is<NS; is++) {
diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
index e8919ed..181e1ac 100644
--- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
@@ -50,14 +50,12 @@
* @param uid UID of the app
* @param userTimeUs time spent executing in user space in microseconds
* @param systemTimeUs time spent executing in kernel space in microseconds
- * @param powerMaUs power consumed executing, in milli-ampere microseconds
*/
- void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs, long powerMaUs);
+ void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs);
}
private SparseLongArray mLastUserTimeUs = new SparseLongArray();
private SparseLongArray mLastSystemTimeUs = new SparseLongArray();
- private SparseLongArray mLastPowerMaUs = new SparseLongArray();
private long mLastTimeReadUs = 0;
/**
@@ -77,26 +75,18 @@
final int uid = Integer.parseInt(uidStr.substring(0, uidStr.length() - 1), 10);
final long userTimeUs = Long.parseLong(splitter.next(), 10);
final long systemTimeUs = Long.parseLong(splitter.next(), 10);
- final long powerMaUs;
- if (splitter.hasNext()) {
- powerMaUs = Long.parseLong(splitter.next(), 10) / 1000;
- } else {
- powerMaUs = 0;
- }
// Only report if there is a callback and if this is not the first read.
if (callback != null && mLastTimeReadUs != 0) {
long userTimeDeltaUs = userTimeUs;
long systemTimeDeltaUs = systemTimeUs;
- long powerDeltaMaUs = powerMaUs;
int index = mLastUserTimeUs.indexOfKey(uid);
if (index >= 0) {
userTimeDeltaUs -= mLastUserTimeUs.valueAt(index);
systemTimeDeltaUs -= mLastSystemTimeUs.valueAt(index);
- powerDeltaMaUs -= mLastPowerMaUs.valueAt(index);
final long timeDiffUs = nowUs - mLastTimeReadUs;
- if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 || powerDeltaMaUs < 0) {
+ if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0) {
StringBuilder sb = new StringBuilder("Malformed cpu data for UID=");
sb.append(uid).append("!\n");
sb.append("Time between reads: ");
@@ -106,36 +96,28 @@
TimeUtils.formatDuration(mLastUserTimeUs.valueAt(index) / 1000, sb);
sb.append(" s=");
TimeUtils.formatDuration(mLastSystemTimeUs.valueAt(index) / 1000, sb);
- sb.append(" p=").append(mLastPowerMaUs.valueAt(index) / 1000);
- sb.append("mAms\n");
- sb.append("Current times: u=");
+ sb.append("\nCurrent times: u=");
TimeUtils.formatDuration(userTimeUs / 1000, sb);
sb.append(" s=");
TimeUtils.formatDuration(systemTimeUs / 1000, sb);
- sb.append(" p=").append(powerMaUs / 1000);
- sb.append("mAms\n");
- sb.append("Delta: u=");
+ sb.append("\nDelta: u=");
TimeUtils.formatDuration(userTimeDeltaUs / 1000, sb);
sb.append(" s=");
TimeUtils.formatDuration(systemTimeDeltaUs / 1000, sb);
- sb.append(" p=").append(powerDeltaMaUs / 1000).append("mAms");
Slog.e(TAG, sb.toString());
userTimeDeltaUs = 0;
systemTimeDeltaUs = 0;
- powerDeltaMaUs = 0;
}
}
- if (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0 || powerDeltaMaUs != 0) {
- callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs,
- powerDeltaMaUs);
+ if (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0) {
+ callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs);
}
}
mLastUserTimeUs.put(uid, userTimeUs);
mLastSystemTimeUs.put(uid, systemTimeUs);
- mLastPowerMaUs.put(uid, powerMaUs);
}
} catch (IOException e) {
Slog.e(TAG, "Failed to read uid_cputime: " + e.getMessage());
@@ -152,7 +134,6 @@
if (index >= 0) {
mLastUserTimeUs.removeAt(index);
mLastSystemTimeUs.removeAt(index);
- mLastPowerMaUs.removeAt(index);
}
try (FileWriter writer = new FileWriter(sRemoveUidProcFile)) {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 44fa99d..142effb 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -186,8 +186,8 @@
private static void preloadOpenGL() {
String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
- if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false) ||
- driverPackageName == null || driverPackageName.isEmpty()) {
+ if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false) &&
+ (driverPackageName == null || driverPackageName.isEmpty())) {
EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
}
}
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index 1abb59b..a70209c 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -74,6 +74,7 @@
private final Rect mOldStableInsets = new Rect();
private final Rect mSystemInsets = new Rect();
private final Rect mStableInsets = new Rect();
+ private final Rect mTmpRect = new Rect();
public BackdropFrameRenderer(DecorView decorView, ThreadedRenderer renderer, Rect initialBounds,
Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable,
@@ -370,12 +371,6 @@
DisplayListCanvas canvas = mSystemBarBackgroundNode.start(width, height);
mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
final int topInset = DecorView.getColorViewTopInset(mStableInsets.top, mSystemInsets.top);
- final int bottomInset = DecorView.getColorViewBottomInset(stableInsets.bottom,
- systemInsets.bottom);
- final int rightInset = DecorView.getColorViewRightInset(stableInsets.right,
- systemInsets.right);
- final int leftInset = DecorView.getColorViewLeftInset(stableInsets.left,
- systemInsets.left);
if (mStatusBarColor != null) {
mStatusBarColor.setBounds(0, 0, left + width, topInset);
mStatusBarColor.draw(canvas);
@@ -385,14 +380,8 @@
// don't want the navigation bar background be moving around when resizing in docked mode.
// However, we need it for the transitions into/out of docked mode.
if (mNavigationBarColor != null && fullscreen) {
- final int size = DecorView.getNavBarSize(bottomInset, rightInset, leftInset);
- if (DecorView.isNavBarToRightEdge(bottomInset, rightInset)) {
- mNavigationBarColor.setBounds(width - size, 0, width, height);
- } else if (DecorView.isNavBarToLeftEdge(bottomInset, leftInset)) {
- mNavigationBarColor.setBounds(0, 0, size, height);
- } else {
- mNavigationBarColor.setBounds(0, height - size, width, height);
- }
+ DecorView.getNavigationBarRect(width, height, stableInsets, systemInsets, mTmpRect);
+ mNavigationBarColor.setBounds(mTmpRect);
mNavigationBarColor.draw(canvas);
}
mSystemBarBackgroundNode.end(canvas);
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 7282492..baf6db9 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -119,6 +119,21 @@
// The height of a window which has not in DIP.
private final static int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5;
+ public static final ColorViewAttributes STATUS_BAR_COLOR_VIEW_ATTRIBUTES =
+ new ColorViewAttributes(SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
+ Gravity.TOP, Gravity.LEFT, Gravity.RIGHT,
+ Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME,
+ com.android.internal.R.id.statusBarBackground,
+ FLAG_FULLSCREEN);
+
+ public static final ColorViewAttributes NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES =
+ new ColorViewAttributes(
+ SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
+ Gravity.BOTTOM, Gravity.RIGHT, Gravity.LEFT,
+ Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
+ com.android.internal.R.id.navigationBarBackground,
+ 0 /* hideWindowFlag */);
+
// Cludge to address b/22668382: Set the shadow size to the maximum so that the layer
// size calculation takes the shadow size into account. We set the elevation currently
// to max until the first layout command has been executed.
@@ -162,18 +177,10 @@
// View added at runtime to draw under the navigation bar area
private View mNavigationGuard;
- private final ColorViewState mStatusColorViewState = new ColorViewState(
- SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
- Gravity.TOP, Gravity.LEFT, Gravity.RIGHT,
- Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.statusBarBackground,
- FLAG_FULLSCREEN);
- private final ColorViewState mNavigationColorViewState = new ColorViewState(
- SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
- Gravity.BOTTOM, Gravity.RIGHT, Gravity.LEFT,
- Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.navigationBarBackground,
- 0 /* hideWindowFlag */);
+ private final ColorViewState mStatusColorViewState =
+ new ColorViewState(STATUS_BAR_COLOR_VIEW_ATTRIBUTES);
+ private final ColorViewState mNavigationColorViewState =
+ new ColorViewState(NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES);
private final Interpolator mShowInterpolator;
private final Interpolator mHideInterpolator;
@@ -983,35 +990,50 @@
return false;
}
- static int getColorViewTopInset(int stableTop, int systemTop) {
+ public static int getColorViewTopInset(int stableTop, int systemTop) {
return Math.min(stableTop, systemTop);
}
- static int getColorViewBottomInset(int stableBottom, int systemBottom) {
+ public static int getColorViewBottomInset(int stableBottom, int systemBottom) {
return Math.min(stableBottom, systemBottom);
}
- static int getColorViewRightInset(int stableRight, int systemRight) {
+ public static int getColorViewRightInset(int stableRight, int systemRight) {
return Math.min(stableRight, systemRight);
}
- static int getColorViewLeftInset(int stableLeft, int systemLeft) {
+ public static int getColorViewLeftInset(int stableLeft, int systemLeft) {
return Math.min(stableLeft, systemLeft);
}
- static boolean isNavBarToRightEdge(int bottomInset, int rightInset) {
+ public static boolean isNavBarToRightEdge(int bottomInset, int rightInset) {
return bottomInset == 0 && rightInset > 0;
}
- static boolean isNavBarToLeftEdge(int bottomInset, int leftInset) {
+ public static boolean isNavBarToLeftEdge(int bottomInset, int leftInset) {
return bottomInset == 0 && leftInset > 0;
}
- static int getNavBarSize(int bottomInset, int rightInset, int leftInset) {
+ public static int getNavBarSize(int bottomInset, int rightInset, int leftInset) {
return isNavBarToRightEdge(bottomInset, rightInset) ? rightInset
: isNavBarToLeftEdge(bottomInset, leftInset) ? leftInset : bottomInset;
}
+ public static void getNavigationBarRect(int canvasWidth, int canvasHeight, Rect stableInsets,
+ Rect contentInsets, Rect outRect) {
+ final int bottomInset = getColorViewBottomInset(stableInsets.bottom, contentInsets.bottom);
+ final int leftInset = getColorViewLeftInset(stableInsets.left, contentInsets.left);
+ final int rightInset = getColorViewLeftInset(stableInsets.right, contentInsets.right);
+ final int size = getNavBarSize(bottomInset, rightInset, leftInset);
+ if (isNavBarToRightEdge(bottomInset, rightInset)) {
+ outRect.set(canvasWidth - size, 0, canvasWidth, canvasHeight);
+ } else if (isNavBarToLeftEdge(bottomInset, leftInset)) {
+ outRect.set(0, 0, size, canvasHeight);
+ } else {
+ outRect.set(0, canvasHeight - size, canvasWidth, canvasHeight);
+ }
+ }
+
WindowInsets updateColorViews(WindowInsets insets, boolean animate) {
WindowManager.LayoutParams attrs = mWindow.getAttributes();
int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
@@ -1131,9 +1153,14 @@
}
private int calculateStatusBarColor() {
- int flags = mWindow.getAttributes().flags;
- return (flags & FLAG_TRANSLUCENT_STATUS) != 0 ? mSemiTransparentStatusBarColor
- : (flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 ? mWindow.mStatusBarColor
+ return calculateStatusBarColor(mWindow.getAttributes().flags,
+ mSemiTransparentStatusBarColor, mWindow.mStatusBarColor);
+ }
+
+ public static int calculateStatusBarColor(int flags, int semiTransparentStatusBarColor,
+ int statusBarColor) {
+ return (flags & FLAG_TRANSLUCENT_STATUS) != 0 ? semiTransparentStatusBarColor
+ : (flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 ? statusBarColor
: Color.BLACK;
}
@@ -1160,13 +1187,9 @@
private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
int size, boolean verticalBar, boolean seascape, int sideMargin,
boolean animate, boolean force) {
- state.present = (sysUiVis & state.systemUiHideFlag) == 0
- && (mWindow.getAttributes().flags & state.hideWindowFlag) == 0
- && ((mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
- || force);
- boolean show = state.present
- && (color & Color.BLACK) != 0
- && ((mWindow.getAttributes().flags & state.translucentFlag) == 0 || force);
+ state.present = state.attributes.isPresent(sysUiVis, mWindow.getAttributes().flags, force);
+ boolean show = state.attributes.isVisible(state.present, color,
+ mWindow.getAttributes().flags, force);
boolean showView = show && !isResizing() && size > 0;
boolean visibilityChanged = false;
@@ -1175,15 +1198,15 @@
int resolvedHeight = verticalBar ? LayoutParams.MATCH_PARENT : size;
int resolvedWidth = verticalBar ? size : LayoutParams.MATCH_PARENT;
int resolvedGravity = verticalBar
- ? (seascape ? state.seascapeGravity : state.horizontalGravity)
- : state.verticalGravity;
+ ? (seascape ? state.attributes.seascapeGravity : state.attributes.horizontalGravity)
+ : state.attributes.verticalGravity;
if (view == null) {
if (showView) {
state.view = view = new View(mContext);
view.setBackgroundColor(color);
- view.setTransitionName(state.transitionName);
- view.setId(state.id);
+ view.setTransitionName(state.attributes.transitionName);
+ view.setId(state.attributes.id);
visibilityChanged = true;
view.setVisibility(INVISIBLE);
state.targetVisibility = VISIBLE;
@@ -1665,7 +1688,7 @@
}
};
} else {
- ViewStub stub = (ViewStub) findViewById(R.id.action_mode_bar_stub);
+ ViewStub stub = findViewById(R.id.action_mode_bar_stub);
if (stub != null) {
mPrimaryActionModeView = (ActionBarContextView) stub.inflate();
mPrimaryActionModePopup = null;
@@ -2240,8 +2263,9 @@
@Override
public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> list, int deviceId) {
final PanelFeatureState st = mWindow.getPanelState(FEATURE_OPTIONS_PANEL, false);
- if (!mWindow.isDestroyed() && st != null && mWindow.getCallback() != null) {
- mWindow.getCallback().onProvideKeyboardShortcuts(list, st.menu, deviceId);
+ final Menu menu = st != null ? st.menu : null;
+ if (!mWindow.isDestroyed() && mWindow.getCallback() != null) {
+ mWindow.getCallback().onProvideKeyboardShortcuts(list, menu, deviceId);
}
}
@@ -2271,6 +2295,15 @@
boolean visible;
int color;
+ final ColorViewAttributes attributes;
+
+ ColorViewState(ColorViewAttributes attributes) {
+ this.attributes = attributes;
+ }
+ }
+
+ public static class ColorViewAttributes {
+
final int id;
final int systemUiHideFlag;
final int translucentFlag;
@@ -2280,9 +2313,9 @@
final String transitionName;
final int hideWindowFlag;
- ColorViewState(int systemUiHideFlag,
- int translucentFlag, int verticalGravity, int horizontalGravity,
- int seascapeGravity, String transitionName, int id, int hideWindowFlag) {
+ private ColorViewAttributes(int systemUiHideFlag, int translucentFlag, int verticalGravity,
+ int horizontalGravity, int seascapeGravity, String transitionName, int id,
+ int hideWindowFlag) {
this.id = id;
this.systemUiHideFlag = systemUiHideFlag;
this.translucentFlag = translucentFlag;
@@ -2292,6 +2325,24 @@
this.transitionName = transitionName;
this.hideWindowFlag = hideWindowFlag;
}
+
+ public boolean isPresent(int sysUiVis, int windowFlags, boolean force) {
+ return (sysUiVis & systemUiHideFlag) == 0
+ && (windowFlags & hideWindowFlag) == 0
+ && ((windowFlags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
+ || force);
+ }
+
+ public boolean isVisible(boolean present, int color, int windowFlags, boolean force) {
+ return present
+ && (color & Color.BLACK) != 0
+ && ((windowFlags & translucentFlag) == 0 || force);
+ }
+
+ public boolean isVisible(int sysUiVis, int color, int windowFlags, boolean force) {
+ final boolean present = isPresent(sysUiVis, windowFlags, force);
+ return isVisible(present, color, windowFlags, force);
+ }
}
/**
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 7b966de..243916b 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -1593,7 +1593,7 @@
if (featureId == FEATURE_PROGRESS || featureId == FEATURE_INDETERMINATE_PROGRESS) {
updateProgressBars(value);
} else if (featureId == FEATURE_CUSTOM_TITLE) {
- FrameLayout titleContainer = (FrameLayout) findViewById(R.id.title_container);
+ FrameLayout titleContainer = findViewById(R.id.title_container);
if (titleContainer != null) {
mLayoutInflater.inflate(value, titleContainer);
}
@@ -2690,7 +2690,7 @@
invalidatePanelMenu(FEATURE_ACTION_BAR);
}
} else {
- mTitleView = (TextView) findViewById(R.id.title);
+ mTitleView = findViewById(R.id.title);
if (mTitleView != null) {
if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
final View titleContainer = findViewById(R.id.title_container);
@@ -2967,7 +2967,7 @@
if (mContentParent == null && shouldInstallDecor) {
installDecor();
}
- mCircularProgressBar = (ProgressBar) findViewById(R.id.progress_circular);
+ mCircularProgressBar = findViewById(R.id.progress_circular);
if (mCircularProgressBar != null) {
mCircularProgressBar.setVisibility(View.INVISIBLE);
}
@@ -2981,7 +2981,7 @@
if (mContentParent == null && shouldInstallDecor) {
installDecor();
}
- mHorizontalProgressBar = (ProgressBar) findViewById(R.id.progress_horizontal);
+ mHorizontalProgressBar = findViewById(R.id.progress_horizontal);
if (mHorizontalProgressBar != null) {
mHorizontalProgressBar.setVisibility(View.INVISIBLE);
}
diff --git a/core/java/com/android/internal/util/BitUtils.java b/core/java/com/android/internal/util/BitUtils.java
index a208ccb..e349f3d 100644
--- a/core/java/com/android/internal/util/BitUtils.java
+++ b/core/java/com/android/internal/util/BitUtils.java
@@ -55,4 +55,25 @@
&& maskedEquals(a.getMostSignificantBits(), b.getMostSignificantBits(),
mask.getMostSignificantBits());
}
+
+ public static int[] unpackBits(long val) {
+ int size = Long.bitCount(val);
+ int[] result = new int[size];
+ int index = 0;
+ int bitPos = 0;
+ while (val > 0) {
+ if ((val & 1) == 1) result[index++] = bitPos;
+ val = val >> 1;
+ bitPos++;
+ }
+ return result;
+ }
+
+ public static long packBits(int[] bits) {
+ long packed = 0;
+ for (int b : bits) {
+ packed |= (1 << b);
+ }
+ return packed;
+ }
}
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
index 4659d3c..ce89501 100644
--- a/core/java/com/android/internal/util/DumpUtils.java
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -121,12 +121,15 @@
final String[] pkgs = context.getPackageManager().getPackagesForUid(uid);
if (pkgs != null) {
for (String pkg : pkgs) {
- if (appOps.checkOpNoThrow(AppOpsManager.OP_GET_USAGE_STATS, uid,
- pkg) == AppOpsManager.MODE_ALLOWED) {
- appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS, uid, pkg);
- if (DEBUG) Slog.v(TAG, "Found package " + pkg + " with "
- + "android:get_usage_stats access");
- return true;
+ switch (appOps.checkOpNoThrow(AppOpsManager.OP_GET_USAGE_STATS, uid, pkg)) {
+ case AppOpsManager.MODE_ALLOWED:
+ if (DEBUG) Slog.v(TAG, "Found package " + pkg + " with "
+ + "android:get_usage_stats allowed");
+ return true;
+ case AppOpsManager.MODE_DEFAULT:
+ if (DEBUG) Slog.v(TAG, "Found package " + pkg + " with "
+ + "android:get_usage_stats default");
+ return true;
}
}
}
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index 919cf99..83a2838 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -89,14 +89,14 @@
setBackgroundDrawable(mBackground);
- mTitleView = (TextView) findViewById(com.android.internal.R.id.title);
+ mTitleView = findViewById(com.android.internal.R.id.title);
if (mTextAppearance != -1) {
mTitleView.setTextAppearance(mTextAppearanceContext,
mTextAppearance);
}
- mShortcutView = (TextView) findViewById(com.android.internal.R.id.shortcut);
- mSubMenuArrowView = (ImageView) findViewById(com.android.internal.R.id.submenuarrow);
+ mShortcutView = findViewById(com.android.internal.R.id.shortcut);
+ mSubMenuArrowView = findViewById(com.android.internal.R.id.submenuarrow);
if (mSubMenuArrowView != null) {
mSubMenuArrowView.setImageDrawable(mSubMenuArrow);
}
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index c3a7460..65cd4fa2 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -569,10 +569,10 @@
void pullChildren() {
if (mContent == null) {
mContent = findViewById(com.android.internal.R.id.content);
- mActionBarTop = (ActionBarContainer) findViewById(
+ mActionBarTop = findViewById(
com.android.internal.R.id.action_bar_container);
mDecorToolbar = getDecorToolbar(findViewById(com.android.internal.R.id.action_bar));
- mActionBarBottom = (ActionBarContainer) findViewById(
+ mActionBarBottom = findViewById(
com.android.internal.R.id.split_action_bar);
}
}
@@ -707,7 +707,7 @@
mDecorToolbar.setSplitToolbar(splitActionBar);
mDecorToolbar.setSplitWhenNarrow(splitWhenNarrow);
- final ActionBarContextView cab = (ActionBarContextView) findViewById(
+ final ActionBarContextView cab = findViewById(
com.android.internal.R.id.action_context_bar);
cab.setSplitView(mActionBarBottom);
cab.setSplitToolbar(splitActionBar);
diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java
index f63afad..afb2a5e 100644
--- a/core/java/com/android/internal/widget/MediaNotificationView.java
+++ b/core/java/com/android/internal/widget/MediaNotificationView.java
@@ -152,7 +152,7 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mRightIcon = (ImageView) findViewById(com.android.internal.R.id.right_icon);
+ mRightIcon = findViewById(com.android.internal.R.id.right_icon);
mActions = findViewById(com.android.internal.R.id.media_actions);
mHeader = findViewById(com.android.internal.R.id.notification_header);
mMainColumn = findViewById(com.android.internal.R.id.notification_main_column);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 33fabfc..96285cd 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -96,6 +96,7 @@
android_os_SystemProperties.cpp \
android_os_Trace.cpp \
android_os_UEventObserver.cpp \
+ android_os_VintfObject.cpp \
android_net_LocalSocketImpl.cpp \
android_net_NetUtils.cpp \
android_net_TrafficStats.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index e237ce9..8ca4794 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -159,6 +159,7 @@
extern int register_android_os_MessageQueue(JNIEnv* env);
extern int register_android_os_Parcel(JNIEnv* env);
extern int register_android_os_SELinux(JNIEnv* env);
+extern int register_android_os_VintfObject(JNIEnv *env);
extern int register_android_os_seccomp(JNIEnv* env);
extern int register_android_os_SystemProperties(JNIEnv *env);
extern int register_android_os_SystemClock(JNIEnv* env);
@@ -1302,6 +1303,7 @@
REG_JNI(register_android_os_HwBlob),
REG_JNI(register_android_os_HwParcel),
REG_JNI(register_android_os_HwRemoteBinder),
+ REG_JNI(register_android_os_VintfObject),
REG_JNI(register_android_nio_utils),
REG_JNI(register_android_graphics_Canvas),
REG_JNI(register_android_graphics_Graphics),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 3dc1be6..a38acd3 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -616,7 +616,7 @@
paint.setBlendMode(SkBlendMode::kSrc);
paint.setFilterQuality(kLow_SkFilterQuality); // bilinear filtering
- SkCanvas canvas(outputBitmap);
+ SkCanvas canvas(outputBitmap, SkCanvas::ColorBehavior::kLegacy);
canvas.scale(sx, sy);
canvas.drawBitmap(decodingBitmap, 0.0f, 0.0f, &paint);
} else {
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 3010dc1..fc90fb3 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -45,21 +45,24 @@
constexpr jint RESOLVE_BY_FONT_TABLE = -1;
struct NativeFamilyBuilder {
+ NativeFamilyBuilder(uint32_t langId, int variant)
+ : langId(langId), variant(variant), allowUnsupportedFont(false) {}
uint32_t langId;
int variant;
+ bool allowUnsupportedFont;
std::vector<minikin::Font> fonts;
std::vector<minikin::FontVariation> axes;
};
static jlong FontFamily_initBuilder(JNIEnv* env, jobject clazz, jstring lang, jint variant) {
- NativeFamilyBuilder* builder = new NativeFamilyBuilder();
+ NativeFamilyBuilder* builder;
if (lang != nullptr) {
ScopedUtfChars str(env, lang);
- builder->langId = minikin::FontStyle::registerLanguageList(str.c_str());
+ builder = new NativeFamilyBuilder(
+ minikin::FontStyle::registerLanguageList(str.c_str()), variant);
} else {
- builder->langId = minikin::FontStyle::registerLanguageList("");
+ builder = new NativeFamilyBuilder(minikin::FontStyle::registerLanguageList(""), variant);
}
- builder->variant = variant;
return reinterpret_cast<jlong>(builder);
}
@@ -67,12 +70,22 @@
if (builderPtr == 0) {
return 0;
}
+ std::unique_ptr<NativeFamilyBuilder> builder(
+ reinterpret_cast<NativeFamilyBuilder*>(builderPtr));
+ std::shared_ptr<minikin::FontFamily> family = std::make_shared<minikin::FontFamily>(
+ builder->langId, builder->variant, std::move(builder->fonts));
+ if (family->getCoverage().length() == 0 && !builder->allowUnsupportedFont) {
+ return 0;
+ }
+ return reinterpret_cast<jlong>(new FontFamilyWrapper(std::move(family)));
+}
+
+static void FontFamily_allowUnsupportedFont(jlong builderPtr) {
+ if (builderPtr == 0) {
+ return;
+ }
NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
- FontFamilyWrapper* family = new FontFamilyWrapper(
- std::make_shared<minikin::FontFamily>(
- builder->langId, builder->variant, std::move(builder->fonts)));
- delete builder;
- return reinterpret_cast<jlong>(family);
+ builder->allowUnsupportedFont = true;
}
static void FontFamily_abort(jlong builderPtr) {
@@ -258,6 +271,7 @@
static const JNINativeMethod gFontFamilyMethods[] = {
{ "nInitBuilder", "(Ljava/lang/String;I)J", (void*)FontFamily_initBuilder },
{ "nCreateFamily", "(J)J", (void*)FontFamily_create },
+ { "nAllowUnsupportedFont", "(J)V", (void*)FontFamily_allowUnsupportedFont },
{ "nAbort", "(J)V", (void*)FontFamily_abort },
{ "nUnrefFamily", "(J)V", (void*)FontFamily_unref },
{ "nAddFont", "(JLjava/nio/ByteBuffer;III)Z", (void*)FontFamily_addFont },
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index d0b07d0..86c97a1 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -42,6 +42,13 @@
return reinterpret_cast<jlong>(face);
}
+static jlong Typeface_createFromTypefaceWithExactStyle(JNIEnv* env, jobject, jlong nativeInstance,
+ jint weight, jboolean italic) {
+ Typeface* baseTypeface = reinterpret_cast<Typeface*>(nativeInstance);
+ return reinterpret_cast<jlong>(
+ Typeface::createFromTypefaceWithStyle(baseTypeface, weight, italic));
+}
+
static jlong Typeface_createFromTypefaceWithVariation(JNIEnv* env, jobject, jlong familyHandle,
jobject listOfAxis) {
std::vector<minikin::FontVariation> variations;
@@ -75,7 +82,13 @@
return face->fSkiaStyle;
}
-static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray) {
+static jint Typeface_getBaseWeight(JNIEnv* env, jobject obj, jlong faceHandle) {
+ Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
+ return face->fBaseWeight;
+}
+
+static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray,
+ int weight, int italic) {
ScopedLongArrayRO families(env, familyArray);
std::vector<std::shared_ptr<minikin::FontFamily>> familyVec;
familyVec.reserve(families.size());
@@ -83,7 +96,8 @@
FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
familyVec.emplace_back(family->family);
}
- return reinterpret_cast<jlong>(Typeface::createFromFamilies(std::move(familyVec)));
+ return reinterpret_cast<jlong>(
+ Typeface::createFromFamilies(std::move(familyVec), weight, italic));
}
static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) {
@@ -113,12 +127,15 @@
static const JNINativeMethod gTypefaceMethods[] = {
{ "nativeCreateFromTypeface", "(JI)J", (void*)Typeface_createFromTypeface },
+ { "nativeCreateFromTypefaceWithExactStyle", "(JIZ)J",
+ (void*)Typeface_createFromTypefaceWithExactStyle },
{ "nativeCreateFromTypefaceWithVariation", "(JLjava/util/List;)J",
(void*)Typeface_createFromTypefaceWithVariation },
{ "nativeCreateWeightAlias", "(JI)J", (void*)Typeface_createWeightAlias },
{ "nativeUnref", "(J)V", (void*)Typeface_unref },
{ "nativeGetStyle", "(J)I", (void*)Typeface_getStyle },
- { "nativeCreateFromArray", "([J)J",
+ { "nativeGetBaseWeight", "(J)I", (void*)Typeface_getBaseWeight },
+ { "nativeCreateFromArray", "([JII)J",
(void*)Typeface_createFromArray },
{ "nativeSetDefault", "(J)V", (void*)Typeface_setDefault },
{ "nativeGetSupportedAxes", "(J)[I", (void*)Typeface_getSupportedAxes },
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 4322105..de9445d 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -327,7 +327,9 @@
subHeap = HEAP_DALVIK_ZYGOTE;
} else if (strstr(name, "/dev/ashmem/dalvik-indirect ref") == name) {
subHeap = HEAP_DALVIK_INDIRECT_REFERENCE_TABLE;
- } else if (strstr(name, "/dev/ashmem/dalvik-jit-code-cache") == name) {
+ } else if (strstr(name, "/dev/ashmem/dalvik-jit-code-cache") == name ||
+ strstr(name, "/dev/ashmem/dalvik-data-code-cache") == name ||
+ strstr(name, "/dev/ashmem/dalvik-CompilerMetadata") == name) {
subHeap = HEAP_DALVIK_CODE_CACHE;
} else {
subHeap = HEAP_DALVIK_ACCOUNTING; // Default to accounting.
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 8f7908a..d740a76 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -617,6 +617,21 @@
return parcel->getOpenAshmemSize();
}
+static jint android_os_Parcel_compareData(JNIEnv* env, jclass clazz, jlong thisNativePtr,
+ jlong otherNativePtr)
+{
+ Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
+ if (thisParcel == NULL) {
+ return 0;
+ }
+ Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
+ if (otherParcel == NULL) {
+ return thisParcel->getOpenAshmemSize();
+ }
+
+ return thisParcel->compareData(*otherParcel);
+}
+
static jlong android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jlong thisNativePtr,
jlong otherNativePtr, jint offset, jint length)
{
@@ -781,6 +796,7 @@
{"nativeMarshall", "(J)[B", (void*)android_os_Parcel_marshall},
{"nativeUnmarshall", "(J[BII)J", (void*)android_os_Parcel_unmarshall},
+ {"nativeCompareData", "(JJ)I", (void*)android_os_Parcel_compareData},
{"nativeAppendFrom", "(JJII)J", (void*)android_os_Parcel_appendFrom},
// @FastNative
{"nativeHasFileDescriptors", "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
new file mode 100644
index 0000000..1883ecb
--- /dev/null
+++ b/core/jni/android_os_VintfObject.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VintfObject"
+//#define LOG_NDEBUG 0
+
+#include <JNIHelp.h>
+#include <vintf/VintfObject.h>
+#include <vintf/parse_xml.h>
+
+#include "core_jni_helpers.h"
+
+namespace android {
+
+using vintf::HalManifest;
+using vintf::RuntimeInfo;
+using vintf::VintfObject;
+using vintf::gHalManifestConverter;
+
+static jstring android_os_VintfObject_getDeviceManifest(JNIEnv* env, jclass clazz)
+{
+ const HalManifest *manifest = VintfObject::GetDeviceHalManifest();
+ if (manifest == nullptr) {
+ return nullptr;
+ }
+ std::string xml = gHalManifestConverter(*manifest);
+ return env->NewStringUTF(xml.c_str());
+}
+
+static jstring android_os_VintfObject_getFrameworkManifest(JNIEnv* env, jclass clazz)
+{
+ const HalManifest *manifest = VintfObject::GetFrameworkHalManifest();
+ if (manifest == nullptr) {
+ return nullptr;
+ }
+ std::string xml = gHalManifestConverter(*manifest);
+ return env->NewStringUTF(xml.c_str());
+}
+
+static jint android_os_VintfObject_verify(JNIEnv *env, jclass clazz, jobjectArray packageInfo) {
+ size_t count = env->GetArrayLength(packageInfo);
+ std::vector<std::string> cPackageInfo{count};
+ for (size_t i = 0; i < count; ++i) {
+ jstring element = (jstring)env->GetObjectArrayElement(packageInfo, i);
+ const char *cString = env->GetStringUTFChars(element, NULL /* isCopy */);
+ cPackageInfo[i] = cString;
+ env->ReleaseStringUTFChars(element, cString);
+ }
+ int32_t status = VintfObject::CheckCompatibility(cPackageInfo, false /* mount */);
+ return status;
+}
+
+// ----------------------------------------------------------------------------
+
+static const JNINativeMethod gVintfObjectMethods[] = {
+ {"getDeviceManifest", "()Ljava/lang/String;", (void*)android_os_VintfObject_getDeviceManifest},
+ {"getFrameworkManifest", "()Ljava/lang/String;", (void*)android_os_VintfObject_getFrameworkManifest},
+ {"verify", "([Ljava/lang/String;)I", (void*)android_os_VintfObject_verify},
+};
+
+const char* const kVintfObjectPathName = "android/os/VintfObject";
+
+int register_android_os_VintfObject(JNIEnv* env)
+{
+ return RegisterMethodsOrDie(env, kVintfObjectPathName, gVintfObjectMethods,
+ NELEM(gVintfObjectMethods));
+}
+
+};
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index abcd1e7..1aed501 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -192,18 +192,12 @@
if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) {
/*
- * It's an Error: Reraise the exception, detach this thread, and
- * wait for the fireworks. Die even more blatantly after a minute
- * if the gentler attempt doesn't do the trick.
- *
- * The GetJavaVM function isn't on the "approved" list of JNI calls
- * that can be made while an exception is pending, so we want to
- * get the VM ptr, throw the exception, and then detach the thread.
+ * It's an Error: Reraise the exception and ask the runtime to abort.
+ * This will dump the pending exception as well as all thread traces
+ * to the log.
*/
env->Throw(excep);
- env->ExceptionDescribe();
- ALOGE("Forcefully exiting");
- exit(1);
+ env->FatalError("java.lang.Error thrown during binder transaction.");
}
bail:
diff --git a/core/jni/android_util_Log.cpp b/core/jni/android_util_Log.cpp
index 20dfe78..56505af 100644
--- a/core/jni/android_util_Log.cpp
+++ b/core/jni/android_util_Log.cpp
@@ -58,16 +58,7 @@
return false;
}
- jboolean result = false;
- if ((strlen(chars)+sizeof(LOG_NAMESPACE)) > PROPERTY_KEY_MAX) {
- char buf2[200];
- snprintf(buf2, sizeof(buf2), "Log tag \"%s\" exceeds limit of %zu characters\n",
- chars, PROPERTY_KEY_MAX - sizeof(LOG_NAMESPACE));
-
- jniThrowException(env, "java/lang/IllegalArgumentException", buf2);
- } else {
- result = isLoggable(chars, level);
- }
+ jboolean result = isLoggable(chars, level);
env->ReleaseStringUTFChars(tag, chars);
return result;
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index dc365b4..8b82314 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -289,6 +289,14 @@
}
}
+static void nativeSetRelativeLayer(JNIEnv* env, jclass clazz, jlong nativeObject,
+ jobject relativeTo, jint zorder) {
+ auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ sp<IBinder> handle = ibinderForJavaObject(env, relativeTo);
+
+ ctrl->setRelativeLayer(handle, zorder);
+}
+
static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat x, jfloat y) {
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
status_t err = ctrl->setPosition(x, y);
@@ -774,6 +782,8 @@
(void*)nativeSetAnimationTransaction },
{"nativeSetLayer", "(JI)V",
(void*)nativeSetLayer },
+ {"nativeSetRelativeLayer", "(JLandroid/os/IBinder;I)V",
+ (void*)nativeSetRelativeLayer },
{"nativeSetPosition", "(JFF)V",
(void*)nativeSetPosition },
{"nativeSetGeometryAppliesWithResize", "(J)V",
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index 98c9e78..ce951de 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -499,7 +499,7 @@
SettingProto automatic_storage_manager_downloads_days_to_retain = 163;
SettingProto qs_tiles = 164;
SettingProto demo_user_setup_complete = 165;
- SettingProto web_action_enabled = 166;
+ SettingProto instant_apps_enabled = 166;
SettingProto device_paired = 167;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a27c5ac..000c8c4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -37,6 +37,7 @@
<protected-broadcast android:name="android.intent.action.BOOT_COMPLETED" />
<protected-broadcast android:name="android.intent.action.PACKAGE_INSTALL" />
<protected-broadcast android:name="android.intent.action.PACKAGE_ADDED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_FIRST_ADDED" />
<protected-broadcast android:name="android.intent.action.PACKAGE_REPLACED" />
<protected-broadcast android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<protected-broadcast android:name="android.intent.action.PACKAGE_REMOVED" />
@@ -491,7 +492,9 @@
<protected-broadcast android:name="android.intent.action.ACTION_RADIO_OFF" />
<protected-broadcast android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED" />
+ <protected-broadcast android:name="android.accounts.action.ACCOUNT_REMOVED" />
<protected-broadcast android:name="android.accounts.action.VISIBLE_ACCOUNTS_CHANGED" />
+
<protected-broadcast android:name="com.android.sync.SYNC_CONN_STATUS_CHANGED" />
<protected-broadcast android:name="com.android.phone.SIP_INCOMING_CALL" />
@@ -532,6 +535,10 @@
<protected-broadcast android:name="android.content.pm.action.SESSION_COMMITTED" />
<protected-broadcast android:name="android.os.action.USER_RESTRICTIONS_CHANGED" />
+ <protected-broadcast android:name="android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT" />
+ <protected-broadcast android:name="android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED" />
+ <protected-broadcast android:name="android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED" />
+ <protected-broadcast android:name="android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED" />
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
@@ -804,7 +811,7 @@
<p>Protection level: dangerous-->
<permission android:name="android.permission.READ_PHONE_NUMBERS"
android:permissionGroup="android.permission-group.PHONE"
- android:label="@string/permlab_readPhoneNumber"
+ android:label="@string/permlab_readPhoneNumbers"
android:description="@string/permdesc_readPhoneNumbers"
android:protectionLevel="dangerous|ephemeral" />
@@ -1519,6 +1526,16 @@
<permission android:name="android.permission.DVB_DEVICE"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by carrier state
+ @hide <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by user state
+ @hide <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_USER_OEM_UNLOCK_STATE"
+ android:protectionLevel="signature|privileged" />
+
<!-- @SystemApi Allows reading the OEM unlock state
@hide <p>Not for use by third-party applications. -->
<permission android:name="android.permission.READ_OEM_UNLOCK_STATE"
@@ -2519,6 +2536,13 @@
<permission android:name="android.permission.MODIFY_PARENTAL_CONTROLS"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows an application to notify TV inputs by sending broadcasts.
+ <p>Protection level: signature|privileged
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.NOTIFY_TV_INPUTS"
+ android:protectionLevel="signature|privileged" />
+
<!-- Must be required by a {@link android.media.routing.MediaRouteService}
to ensure that only the system can interact with it.
@hide -->
diff --git a/core/res/res/drawable-hdpi/ic_accessibility_magnification.png b/core/res/res/drawable-hdpi/ic_accessibility_magnification.png
new file mode 100755
index 0000000..a91bc6e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_accessibility_magnification.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_accessibility_magnification.png b/core/res/res/drawable-mdpi/ic_accessibility_magnification.png
new file mode 100755
index 0000000..9ec5107
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_accessibility_magnification.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_accessibility_magnification.png b/core/res/res/drawable-xhdpi/ic_accessibility_magnification.png
new file mode 100755
index 0000000..0b3a32e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_accessibility_magnification.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_accessibility_magnification.png b/core/res/res/drawable-xxhdpi/ic_accessibility_magnification.png
new file mode 100755
index 0000000..3eeb1c9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_accessibility_magnification.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_accessibility_magnification.png b/core/res/res/drawable-xxxhdpi/ic_accessibility_magnification.png
new file mode 100755
index 0000000..7d37612
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/ic_accessibility_magnification.png
Binary files differ
diff --git a/core/res/res/drawable/autofill_dataset_picker_background.xml b/core/res/res/drawable/autofill_dataset_picker_background.xml
new file mode 100644
index 0000000..b5617e1
--- /dev/null
+++ b/core/res/res/drawable/autofill_dataset_picker_background.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<inset xmlns:android="http://schemas.android.com/apk/res/android">
+ <shape android:shape="rectangle">
+ <corners android:radius="2dp" />
+ <solid android:color="?attr/colorBackground" />
+ </shape>
+</inset>
diff --git a/core/res/res/drawable/autofilled_highlight.xml b/core/res/res/drawable/autofilled_highlight.xml
index c7aacb9..3a2815c 100644
--- a/core/res/res/drawable/autofilled_highlight.xml
+++ b/core/res/res/drawable/autofilled_highlight.xml
@@ -15,12 +15,6 @@
* limitations under the License.
-->
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:insetLeft="4dp"
- android:insetRight="4dp"
- android:insetBottom="4dp"
- android:insetTop="4dp">
- <shape>
- <solid android:color="@color/autofilled_highlight" />
- </shape>
-</inset>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/autofilled_highlight" />
+</shape>
diff --git a/core/res/res/drawable/scrollbar_handle_material.xml b/core/res/res/drawable/scrollbar_handle_material.xml
index f020112..33efbba 100644
--- a/core/res/res/drawable/scrollbar_handle_material.xml
+++ b/core/res/res/drawable/scrollbar_handle_material.xml
@@ -19,4 +19,7 @@
android:shape="rectangle">
<solid
android:color="#84ffffff" />
+ <size
+ android:width="4dp"
+ android:height="4dp" />
</shape>
diff --git a/core/res/res/layout/autofill_dataset_picker.xml b/core/res/res/layout/autofill_dataset_picker.xml
index 133265b..528efca 100644
--- a/core/res/res/layout/autofill_dataset_picker.xml
+++ b/core/res/res/layout/autofill_dataset_picker.xml
@@ -14,11 +14,18 @@
limitations under the License.
-->
-<ListView xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/autofill_dataset_picker"
- android:layout_width="wrap_content"
+ android:layout_width="fill_parent"
android:layout_height="fill_parent"
- android:divider="@null"
- android:background="#ffffffff"
- android:elevation="@dimen/floating_window_z">
-</ListView>
+ style="@style/AutofillDatasetPicker">
+
+ <ListView
+ android:id="@+id/autofill_dataset_list"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:divider="@null"
+ android:visibility="gone">
+ </ListView>
+
+</FrameLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 59e183f..2155c8f 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Skakel oor na teksmodus vir die tydinvoer."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Skakel oor na horlosiemodus vir die tydinvoer."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Outovulopsies"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Inhoud kan nie outomaties ingevul word nie"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Stoor na <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Stoor <xliff:g id="TYPE">%1$s</xliff:g> na <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Stoor <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> in <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Stoor <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> in <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Stoor"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Nee, dankie"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"wagwoord"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adres"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredietkaart"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"gebruikernaam"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"e-posadres"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Bly kalm en soek skuiling naby."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Ontruim kusgebiede en riviergebiede dadelik en gaan na \'n veiliger plek, soos \'n hoogliggende omgewing."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Bly kalm en soek skuiling naby."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 07d03ce..41a0153 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ለጊዜ ግቤቱ ወደ የጽሑፍ ግቤት ሁነታ ቀይር።"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ለጊዜ ግቤቱ ወደ የሰዓት ሁነታ ቀይር።"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"የራስ-ሙላ አማራጮች"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"ይዘቶች በራስ-ሰር ሊሞሉ አይችሉም"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"ወደ <xliff:g id="LABEL">%1$s</xliff:g> ይቀመጥ?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> ወደ <xliff:g id="LABEL">%2$s</xliff:g> ይቀመጥ?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>፣ <xliff:g id="TYPE_1">%2$s</xliff:g> ወደ <xliff:g id="LABEL">%3$s</xliff:g> ይቀመጡ?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>፣ <xliff:g id="TYPE_1">%2$s</xliff:g>፣ <xliff:g id="TYPE_2">%3$s</xliff:g> ወደ <xliff:g id="LABEL">%4$s</xliff:g> ይቀመጡ?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"አስቀምጥ"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"አይ፣ አመሰግናለሁ"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"የይለፍ ቃል"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"አድራሻ"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ክሬዲት ካርድ"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"የተጠቃሚ ስም"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"የኢሜይል አድራሻ"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"ረጋ ይበሉና በአቅራቢያ ያለ መጠለያ ይፈልጉ።"</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"ወዲያውኑ ከባህር ዳርቻ አካባቢዎች እና የወንዝ ዳርቻ አካባቢዎች ይውጡና እንደ ከፍ ያለ መሬት ያሉ ከአደጋ የተሻለ ደህንነት ወዳቸው ቦታዎች ይሂዱ።"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"ረጋ ይበሉና በአቅራቢያ ያለ መጠለያ ይፈልጉ።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 06ac681..570e3c4 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1856,19 +1856,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"يُرجى التبديل إلى وضع إدخال النص لإدخال الوقت."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"يُرجى التبديل إلى وضع الساعة لإدخال الوقت."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"خيارات الملء التلقائي"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"يتعذر إجراء ملء تلقائي للمحتويات"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"هل تريد الحفظ في <xliff:g id="LABEL">%1$s</xliff:g>؟"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"هل تريد حفظ <xliff:g id="TYPE">%1$s</xliff:g> في <xliff:g id="LABEL">%2$s</xliff:g>؟"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"هل تريد حفظ <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> في <xliff:g id="LABEL">%3$s</xliff:g>؟"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"هل تريد حفظ <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> و<xliff:g id="TYPE_2">%3$s</xliff:g> في <xliff:g id="LABEL">%4$s</xliff:g>؟"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"حفظ"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"لا، شكرًا"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"كلمة مرور"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"عنوان"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"بطاقة ائتمان"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"اسم المستخدم"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"عنوان البريد الإلكتروني"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"يُرجى الثبات والبحث عن ملاذ بالجوار."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"يُرجى النزوح في الحال من المناطق الساحلية وضفاف النهر إلى مكان أكثر أمانًا مثل الأراضي المرتفعة."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"يُرجى الثبات والبحث عن ملاذ بالجوار."</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 1d137d0..6da988a 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Zamanı daxil etmək üçün mətnlə daxiletmə rejiminə keçin"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Zamanı daxil etmək üçün saat rejiminə keçin"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Avtodoldurma seçimləri"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Kontentlər avtomatik olaraq doldurula bilməz"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> etiketində yadda saxlanılsın?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g> etiketində yadda saxlanılsın?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> <xliff:g id="LABEL">%3$s</xliff:g> etiketində yadda saxlanılsın?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> <xliff:g id="LABEL">%4$s</xliff:g> etiketində yadda saxlanılsın?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Yadda saxlayın"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Xeyr, çox sağ olun"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"parol"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"ünvan"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredit kartı"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"istifadəçi adı"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"e-poçt ünvanı"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Sakit qalın və yaxınlıqda sığınacaq axtarın."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Dərhal sahil bölgələrindən və çay kənarı ərazilərdən daha təhlükəsiz yüksək yerlərə evakuasiya edin."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Sakit qalın və yaxınlıqda sığınacaq axtarın."</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 8828633..86bb518 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -90,17 +90,16 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"ID pozivaoca podrazumevano nije ograničen. Sledeći poziv: Nije ograničen."</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Usluga nije dobavljena."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Ne možete da promenite podešavanje ID-a korisnika."</string>
- <string name="RestrictedOnData" msgid="8653794784690065540">"Usluga za podatke je blokirana."</string>
- <string name="RestrictedOnEmergency" msgid="6581163779072833665">"Usluga za hitne slučajeve je blokirana."</string>
- <string name="RestrictedOnNormal" msgid="4953867011389750673">"Glasovna usluga je blokirana."</string>
- <string name="RestrictedOnAllVoice" msgid="3396963652108151260">"Sve glasovne usluge su blokirane."</string>
- <string name="RestrictedOnSms" msgid="8314352327461638897">"SMS usluga je blokirana."</string>
- <string name="RestrictedOnVoiceData" msgid="996636487106171320">"Glasovna usluga/usluga prenosa podataka su blokirane."</string>
- <string name="RestrictedOnVoiceSms" msgid="1888588152792023873">"Glasovna usluga i SMS usluga su blokirane."</string>
- <string name="RestrictedOnAll" msgid="5643028264466092821">"Sve glasovne i SMS usluge, kao i usluge prenosa podataka su blokirane."</string>
+ <string name="RestrictedOnDataTitle" msgid="1322504692764166532">"Nema usluge prenosa podataka"</string>
+ <string name="RestrictedOnEmergencyTitle" msgid="1236071219598685236">"Nema usluge za hitne pozive"</string>
+ <string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"Nema glasovne usluge"</string>
+ <string name="RestrictedOnAllVoiceTitle" msgid="158800171499150681">"Nema glasovne usluge/usluge za hitne pozive"</string>
+ <string name="RestrictedOnDataContent" msgid="8997474569390996587">"Mobilni operater je privremeno suspendovao uslugu prenosa podataka na ovoj lokaciji"</string>
+ <string name="RestrictedOnEmergencyContent" msgid="4573217945494650061">"Mobilni operater je privremeno suspendovao hitne pozive na ovoj lokaciji"</string>
+ <string name="RestrictedOnNormalContent" msgid="1579434198284512182">"Mobilni operater je privremeno suspendovao glasovne pozive na ovoj lokaciji"</string>
+ <string name="RestrictedOnAllVoiceContent" msgid="5243580774142557047">"Mobilni operater je privremeno suspendovao glasovne i hitne pozive na ovoj lokaciji"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="4008877505368566980">"Povezivanje sa mrežom nije uspelo"</string>
- <!-- no translation found for NetworkPreferenceSwitchSummary (4164230263214915351) -->
- <skip />
+ <string name="NetworkPreferenceSwitchSummary" msgid="4164230263214915351">"Da biste poboljšali prijem, probajte da promenite izabrani tip u odeljku Sistem > Mreža i internet > Mobilne mreže > Željeni tip mreže."</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"Korisnik zahteva POTPUN režim TTY"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"Korisnik zahteva PRENOS ZVUKA za režim TTY"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"Korisnik zahteva PRENOS GLASA za režim TTY"</string>
@@ -140,8 +139,7 @@
</string-array>
<string name="wifi_calling_off_summary" msgid="8720659586041656098">"Isključeno"</string>
<string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Prednost ima Wi-Fi"</string>
- <!-- no translation found for wfc_mode_cellular_preferred_summary (1988279625335345908) -->
- <skip />
+ <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Želim mobilne podatke"</string>
<string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Samo Wi-Fi"</string>
<string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije prosleđeno"</string>
<string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -180,18 +178,16 @@
<item quantity="other">Instalirani su autoriteti za izdavanje sertifikata</item>
</plurals>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Od strane nepoznate treće strane"</string>
- <string name="ssl_ca_cert_noti_by_administrator" msgid="550758088185764312">"Od strane administratora profila za posao"</string>
+ <string name="ssl_ca_cert_noti_by_administrator" msgid="3541729986326153557">"Od strane administratora profila za Work"</string>
<string name="ssl_ca_cert_noti_managed" msgid="4030263497686867141">"Od strane <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string>
<string name="work_profile_deleted" msgid="5005572078641980632">"Poslovni profil je izbrisan"</string>
- <string name="work_profile_deleted_description" msgid="6305147513054341102">"Poslovni profil je izbrisan jer nedostaje administratorska aplikacija."</string>
- <string name="work_profile_deleted_details" msgid="226615743462361248">"Administratorska aplikacija poslovnog profila nedostaje ili je oštećena. Zbog toga su vaš poslovni profil i povezani podaci izbrisani. Obratite se administratoru za pomoć."</string>
- <string name="work_profile_deleted_description_dpm_wipe" msgid="6019770344820507579">"Profil za Work više nije dostupan na ovom uređaju."</string>
- <!-- no translation found for network_logging_notification_title (6399790108123704477) -->
- <skip />
- <!-- no translation found for network_logging_notification_text (7930089249949354026) -->
- <skip />
+ <string name="work_profile_deleted_description" msgid="1100529432509639864">"Profil za Work je izbrisan jer nedostaje aplikacija za administratore"</string>
+ <string name="work_profile_deleted_details" msgid="6307630639269092360">"Aplikacija za administratore na profilu za Work nedostaje ili je oštećena. Zbog toga su profil za Work i povezani podaci izbrisani. Obratite se administratoru za pomoć."</string>
+ <string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Profil za Work više nije dostupan na ovom uređaju"</string>
+ <string name="network_logging_notification_title" msgid="6399790108123704477">"Uređajem se upravlja"</string>
+ <string name="network_logging_notification_text" msgid="7930089249949354026">"Organizacija upravlja ovim uređajem i može da nadgleda mrežni saobraćaj. Dodirnite za detalje."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Uređaj će biti obrisan"</string>
- <string name="factory_reset_message" msgid="4905025204141900666">"Administratorskoj aplikaciji nedostaju neke komponente ili je oštećena i ne može da se koristi. Uređaj će sada biti obrisan. Obratite se administratoru za pomoć."</string>
+ <string name="factory_reset_message" msgid="7972496262232832457">"Ne možete da koristite ovu aplikaciju za administratore. Uređaj će sada biti obrisan.\n\nAko imate pitanja, kontaktirajte administratora organizacije."</string>
<string name="me" msgid="6545696007631404292">"Ja"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opcije za tablet"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opcije za TV"</string>
@@ -413,8 +409,8 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Dozvoljava aplikaciji da pristupa funkcijama telefona na uređaju. Ova dozvola omogućava aplikaciji da utvrdi broj telefona i ID-ove uređaja, zatim da li je poziv aktivan, kao i broj daljinskog uređaja sa kojim je uspostavljen poziv."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"preusmeravanje poziva preko sistema"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Dozvoljava aplikaciji da preusmerava pozive preko sistema da bi poboljšala doživljaj pozivanja."</string>
- <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"čitanje broja telefona"</string>
- <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Dozvoljava aplikaciji da pristupa broju telefona na uređaju."</string>
+ <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"čitanje brojeva telefona"</string>
+ <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Dozvoljava aplikaciji da pristupa brojevima telefona na uređaju."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"sprečavanje prelaska tableta u stanje spavanja"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"sprečavanje TV-a da pređe u stanje spavanja"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"sprečavanje prelaska telefona u stanje spavanja"</string>
@@ -554,7 +550,7 @@
<string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Dozvoljava aplikaciji da čita i upisuje konfiguraciju podešavanja Ne uznemiravaj."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Podešavanje pravila za lozinku"</string>
<string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontroliše dužinu i znakove dozvoljene u lozinkama i PIN-ovima za zaključavanje ekrana."</string>
- <string name="policylab_watchLogin" msgid="914130646942199503">"Nadgledanje pokušaja otključavanja ekrana"</string>
+ <string name="policylab_watchLogin" msgid="5091404125971980158">"Nadgledajte pokušaje otključavanja ekrana"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Prati broj netačno unetih lozinki prilikom otključavanja ekrana i zaključava tablet ili briše podatke sa tableta ako je netačna lozinka uneta previše puta."</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Nadgleda broj netačnih lozinki koje unesete pri otključavanju ekrana i zaključava TV ili briše sve podatke sa njega ako se unese previše netačnih lozinki."</string>
<string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Prati broj netačno unetih lozinki pri otključavanju ekrana i zaključava telefon ili briše sve podatke sa telefona ako je netačna lozinka uneta previše puta."</string>
@@ -990,8 +986,7 @@
<string name="selectTextMode" msgid="1018691815143165326">"Izaberi tekst"</string>
<string name="undo" msgid="7905788502491742328">"Opozovi"</string>
<string name="redo" msgid="7759464876566803888">"Ponovi"</string>
- <!-- no translation found for autofill (3035779615680565188) -->
- <skip />
+ <string name="autofill" msgid="3035779615680565188">"Automatsko popunjavanje"</string>
<string name="textSelectionCABTitle" msgid="5236850394370820357">"Izbor teksta"</string>
<string name="addToDictionary" msgid="4352161534510057874">"Dodaj u rečnik"</string>
<string name="deleteText" msgid="6979668428458199034">"Izbriši"</string>
@@ -1123,7 +1118,13 @@
<string name="network_switch_metered" msgid="4671730921726992671">"Prešli ste na tip mreže <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
<string name="network_switch_metered_detail" msgid="5325661434777870353">"Uređaj koristi tip mreže <xliff:g id="NEW_NETWORK">%1$s</xliff:g> kada tip mreže <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nema pristup internetu. Možda će se naplaćivati troškovi."</string>
<string name="network_switch_metered_toast" msgid="5779283181685974304">"Prešli ste sa tipa mreže <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na tip mreže <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
- <!-- no translation found for network_switch_type_name:0 (3979506840912951943) -->
+ <string-array name="network_switch_type_name">
+ <item msgid="3979506840912951943">"mobilni podaci"</item>
+ <item msgid="75483255295529161">"Wi-Fi"</item>
+ <item msgid="6862614801537202646">"Bluetooth"</item>
+ <item msgid="5447331121797802871">"Eternet"</item>
+ <item msgid="8257233890381651999">"VPN"</item>
+ </string-array>
<string name="network_switch_type_name_unknown" msgid="4552612897806660656">"nepoznat tip mreže"</string>
<string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nije moguće povezati sa Wi-Fi mrežom"</string>
<string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ima lošu internet vezu."</string>
@@ -1193,7 +1194,7 @@
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Izveštaj o grešci se generiše…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Želite li da podelite izveštaj o grešci?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Deli se izveštaj o grešci…"</string>
- <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"IT administrator je zatražio izveštaj o grešci radi lakšeg rešavanja problema u vezi sa ovim uređajem. Aplikacije i podaci mogu da se dele."</string>
+ <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"Administrator je zatražio izveštaj o grešci radi lakšeg rešavanja problema u vezi sa ovim uređajem. Aplikacije i podaci mogu da se dele."</string>
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"DELI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODBIJ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Promenite tastaturu"</string>
@@ -1204,7 +1205,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Aplikacija <xliff:g id="NAME">%s</xliff:g> se prikazuje preko drugih aplikacija"</string>
- <string name="alert_windows_notification_title" msgid="4532185840598192445">"Aplik. <xliff:g id="NAME">%s</xliff:g> se prikazuje preko drugih aplik."</string>
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> se prikazuje preko drugih aplik."</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Ako ne želite ovu funkciju za <xliff:g id="NAME">%s</xliff:g>, dodirnite da biste otvorili podešavanja i isključili je."</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ISKLJUČI"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> se priprema"</string>
@@ -1380,8 +1381,7 @@
<string name="data_usage_warning_body" msgid="6660692274311972007">"Dodirnite za potrošnju i podešavanja."</string>
<string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Nema više 2G-3G podataka"</string>
<string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Nema više 4G podataka"</string>
- <!-- no translation found for data_usage_mobile_limit_title (6561099244084267376) -->
- <skip />
+ <string name="data_usage_mobile_limit_title" msgid="6561099244084267376">"Dostigli ste ograničenje podataka"</string>
<string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"Nema više Wi-Fi podataka"</string>
<string name="data_usage_limit_body" msgid="291731708279614081">"Potrošili ste podatke za ovaj mesec"</string>
<string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Prekoračen prenos 2G-3G podataka"</string>
@@ -1480,18 +1480,21 @@
<string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Ukloni"</string>
<string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Želite da pojačate zvuk iznad preporučenog nivoa?\n\nSlušanje glasne muzike duže vreme može da vam ošteti sluh."</string>
- <string name="accessibility_shortcut_warning_dialog_title" msgid="5998592821749881862">"Prečica za pristupačnost je UKLJUČENA"</string>
- <string name="accessibility_shortcut_toogle_warning" msgid="2987297770937717543">"Uključite ili isključite uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g> tako što ćete istovremeno zadržati oba dugmeta za jačinu zvuka 3 sekunde.\n\nMožete da promenite uslugu u odeljku Podešavanja > Pristupačnost."</string>
- <string name="disable_accessibility_shortcut" msgid="3683951963271793789">"Isključi prečicu"</string>
- <string name="leave_accessibility_shortcut_on" msgid="8762106842437042969">"Ostavi uključeno"</string>
+ <string name="accessibility_shortcut_warning_dialog_title" msgid="8404780875025725199">"Želite li da koristite prečicu za pristupačnost?"</string>
+ <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"Kada je prečica uključena, pritisnite oba dugmeta za jačinu zvuka da biste pokrenuli funkciju pristupačnosti.\n\n Aktuelna funkcija pristupačnosti:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Možete da promenite funkciju u odeljku Podešavanja > Pristupačnost."</string>
+ <string name="disable_accessibility_shortcut" msgid="627625354248453445">"Isključi prečicu"</string>
+ <string name="leave_accessibility_shortcut_on" msgid="7653111894438512680">"Koristi prečicu"</string>
<string name="accessibility_shortcut_enabling_service" msgid="7771852911861522636">"Prečica za pristupačnost je uključila uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="2747243438223109821">"Prečica za pristupačnost je isključila uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="accessibility_button_prompt_text" msgid="4234556536456854251">"Izaberite funkciju koja će se koristiti kada dodirnete dugme za pristupačnost:"</string>
+ <string name="accessibility_button_instructional_text" msgid="6942300463612999993">"Pritisnite i zadržite dugme za pristupačnost da biste menjali funkcije."</string>
+ <string name="accessibility_magnification_chooser_text" msgid="1227146738764986237">"Uvećanje"</string>
<string name="user_switched" msgid="3768006783166984410">"Aktuelni korisnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="2871009331809089783">"Prebacivanje na <xliff:g id="NAME">%1$s</xliff:g>…"</string>
<string name="user_logging_out_message" msgid="8939524935808875155">"Odjavljuje se <xliff:g id="NAME">%1$s</xliff:g>…"</string>
<string name="owner_name" msgid="2716755460376028154">"Vlasnik"</string>
<string name="error_message_title" msgid="4510373083082500195">"Greška"</string>
- <string name="error_message_change_not_allowed" msgid="1347282344200417578">"Administrator nije dozvolio ovu promenu"</string>
+ <string name="error_message_change_not_allowed" msgid="1238035947357923497">"Administrator nije dozvolio ovu promenu"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nije pronađena nijedna aplikacija koja bi mogla da obavi ovu radnju"</string>
<string name="revoke" msgid="5404479185228271586">"Opozovi"</string>
<string name="mediasize_iso_a0" msgid="1994474252931294172">"ISO A0"</string>
@@ -1583,7 +1586,7 @@
<string name="reason_service_unavailable" msgid="7824008732243903268">"Usluga štampanja nije omogućena"</string>
<string name="print_service_installed_title" msgid="2246317169444081628">"Usluga <xliff:g id="NAME">%s</xliff:g> je instalirana"</string>
<string name="print_service_installed_message" msgid="5897362931070459152">"Dodirnite da biste omogućili"</string>
- <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"Unesite PIN administratora"</string>
+ <string name="restr_pin_enter_admin_pin" msgid="8641662909467236832">"Unesite PIN administratora"</string>
<string name="restr_pin_enter_pin" msgid="3395953421368476103">"Unesite PIN"</string>
<string name="restr_pin_incorrect" msgid="8571512003955077924">"Netačno"</string>
<string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"Aktuelni PIN"</string>
@@ -1612,16 +1615,16 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> na poslu"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. poslovni imejl <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="7693684144593484">"Da biste otkačili ovaj ekran, dodirnite i zadržite Nazad i Pregled."</string>
- <string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacija je zakačena: otkačinjanje nije dozvoljeno na ovom uređaju."</string>
+ <string name="lock_to_app_toast" msgid="6820571533009838261">"Da biste otkačili ovaj ekran, dodirnite i zadržite dugmad Nazad i Pregled"</string>
+ <string name="lock_to_app_toast_locked" msgid="7849470948648628704">"Ova aplikacija ne može da se otkači"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran je zakačen"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Ekran je otkačen"</string>
<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="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>
+ <string name="package_installed_device_owner" msgid="6875717669960212648">"Instalirao je administrator"</string>
+ <string name="package_updated_device_owner" msgid="1847154566357862089">"Ažurirao je administrator"</string>
+ <string name="package_deleted_device_owner" msgid="2307122077550236438">"Izbrisao je administrator"</string>
<string name="battery_saver_description" msgid="1960431123816253034">"Da bi produžila vreme trajanja baterije, ušteda baterije smanjuje performanse uređaja i ograničava vibraciju, usluge lokacije i većinu pozadinskih podataka. Imejl, razmena poruka i druge aplikacije koje se oslanjaju na sinhronizaciju možda neće da se ažuriraju ako ih ne otvorite.\n\nUšteda baterije se automatski isključuje kada se uređaj puni."</string>
<string name="data_saver_description" msgid="6015391409098303235">"Da bi se smanjila potrošnja podataka, Ušteda podataka sprečava neke aplikacije da šalju ili primaju podatke u pozadini. Aplikacija koju trenutno koristite može da pristupa podacima, ali će to činiti ređe. Na primer, slike se neće prikazivati dok ih ne dodirnete."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"Uključiti Uštedu podataka?"</string>
@@ -1715,8 +1718,8 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Svi jezici"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Svi regioni"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Pretraži"</string>
- <string name="work_mode_off_title" msgid="8954725060677558855">"Režim za Work je ISKLJUČEN"</string>
- <string name="work_mode_off_message" msgid="3286169091278094476">"Dozvoljava profilu za Work da funkcioniše, uključujući aplikacije, sinhronizaciju u pozadini i srodne funkcije."</string>
+ <string name="work_mode_off_title" msgid="2615362773958585967">"Uključiti režim za Work?"</string>
+ <string name="work_mode_off_message" msgid="2961559609199223594">"Ovo će uključiti profil za Work, uključujući aplikacije, sinhronizaciju u pozadini i srodne funkcije."</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Uključi"</string>
<string name="new_sms_notification_title" msgid="8442817549127555977">"Imate nove poruke"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorite aplikaciju za SMS da biste pregledali"</string>
@@ -1759,22 +1762,26 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Unesite vreme"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Pređite u režim unosa teksta radi unosa vremena."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Pređite u režim sata radi unosa vremena."</string>
- <!-- no translation found for autofill_picker_accessibility_title (8469043291648711535) -->
- <skip />
+ <string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opcije automatskog popunjavanja"</string>
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Sadržaj ne može automatski da se popuni"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Želite li da sačuvate u: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Želite li da sačuvate stavku <xliff:g id="TYPE">%1$s</xliff:g> u: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Želite li da sačuvate stavke <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> u <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Želite li da sačuvate stavke <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> u <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Sačuvaj"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"lozinka"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adresa"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditna kartica"</string>
- <!-- no translation found for etws_primary_default_message_earthquake (5541962250262769193) -->
- <skip />
- <!-- no translation found for etws_primary_default_message_tsunami (1887685943498368548) -->
- <skip />
- <!-- no translation found for etws_primary_default_message_earthquake_and_tsunami (998797956848445862) -->
- <skip />
- <!-- no translation found for etws_primary_default_message_test (2709597093560037455) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"korisničko ime"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"imejl adresa"</string>
+ <string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Ostanite mirni i potražite sklonište u okolini."</string>
+ <string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Odmah se sklonite iz priobalnih regiona i oblasti pored reka na neko bezbednije mesto, na primer, na neko uzvišenje."</string>
+ <string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Ostanite mirni i potražite sklonište u okolini."</string>
+ <string name="etws_primary_default_message_test" msgid="2709597093560037455">"Testiranje poruka u hitnim slučajevima"</string>
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
+ <string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM kartica nije dozvoljena"</string>
+ <string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM kartica nije podešena"</string>
+ <string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM kartica nije dozvoljena"</string>
+ <string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefon nije dozvoljen"</string>
</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index d12a104..2702b13 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -91,17 +91,16 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Налады ідэнтыфікатару АВН па змаўчанні: не абмяжавана. Наступны выклік: не абмежавана"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Служба не прадастаўляецца."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Вы не можаце змяніць налады ідэнтыфікатара абанента, якi тэлефануе."</string>
- <string name="RestrictedOnData" msgid="8653794784690065540">"Служба дадзеных блакуецца."</string>
- <string name="RestrictedOnEmergency" msgid="6581163779072833665">"Аварыйная служба блакуецца."</string>
- <string name="RestrictedOnNormal" msgid="4953867011389750673">"Галасавая служба заблакаваная."</string>
- <string name="RestrictedOnAllVoice" msgid="3396963652108151260">"Усе галасавыя службы заблакаваны."</string>
- <string name="RestrictedOnSms" msgid="8314352327461638897">"Служба SMS заблакаваная."</string>
- <string name="RestrictedOnVoiceData" msgid="996636487106171320">"Службы перадачы голаса/дадзеных заблакаваны."</string>
- <string name="RestrictedOnVoiceSms" msgid="1888588152792023873">"Службы перадачы голаса і SMS заблакаваныя."</string>
- <string name="RestrictedOnAll" msgid="5643028264466092821">"Усе службы перадачы дадзеных, галасавыя і SMS-службы заблакаваны."</string>
+ <string name="RestrictedOnDataTitle" msgid="1322504692764166532">"Няма сэрвісу перадачы даных"</string>
+ <string name="RestrictedOnEmergencyTitle" msgid="1236071219598685236">"Няма сэрвісу экстранных выклікаў"</string>
+ <string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"Няма сэрвісу галасавых выклікаў"</string>
+ <string name="RestrictedOnAllVoiceTitle" msgid="158800171499150681">"Няма сэрвісу галасавых / экстранных выклікаў"</string>
+ <string name="RestrictedOnDataContent" msgid="8997474569390996587">"Ваш аператар часова прыпыніў працу сэрвісу перадачы даных у гэтым месцы"</string>
+ <string name="RestrictedOnEmergencyContent" msgid="4573217945494650061">"Ваш аператар часова прыпыніў працу сэрвісу экстранных выклікаў у гэтым месцы"</string>
+ <string name="RestrictedOnNormalContent" msgid="1579434198284512182">"Ваш аператар часова прыпыніў працу сэрвісу галасавых выклікаў у гэтым месцы"</string>
+ <string name="RestrictedOnAllVoiceContent" msgid="5243580774142557047">"Ваш аператар часова прыпыніў працу сэрвісу галасавых і экстранных выклікаў у гэтым месцы"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="4008877505368566980">"Немагчыма падключыцца да сеткі"</string>
- <!-- no translation found for NetworkPreferenceSwitchSummary (4164230263214915351) -->
- <skip />
+ <string name="NetworkPreferenceSwitchSummary" msgid="4164230263214915351">"Каб палепшыць якасць прыёму, паспрабуйце змяніць тып, выбраны ў меню \"Сістэма > Сетка і інтэрнэт > Мабільныя сеткі > Прыярытэтны тып сеткі\"."</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"Аднарангавая прылада запытала рэжым TTY FULL"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"Аднарангавая прылада запытала рэжым TTY НСО"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"Аднарангавая прылада запытала рэжым TTY VCO"</string>
@@ -141,8 +140,7 @@
</string-array>
<string name="wifi_calling_off_summary" msgid="8720659586041656098">"Выкл."</string>
<string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Прыярытэт Wi-Fi"</string>
- <!-- no translation found for wfc_mode_cellular_preferred_summary (1988279625335345908) -->
- <skip />
+ <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Прыярытэт мабільнай сеткі"</string>
<string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Толькі Wi-Fi"</string>
<string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не пераадрасоўваецца"</string>
<string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -182,18 +180,16 @@
<item quantity="other">Усталяваны цэнтры сертыфікацыі</item>
</plurals>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Невядомая трэцяя асоба"</string>
- <string name="ssl_ca_cert_noti_by_administrator" msgid="550758088185764312">"Адміністратар вашага працоўнага профілю"</string>
+ <string name="ssl_ca_cert_noti_by_administrator" msgid="3541729986326153557">"Адміністратар вашага працоўнага профілю"</string>
<string name="ssl_ca_cert_noti_managed" msgid="4030263497686867141">"<xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string>
<string name="work_profile_deleted" msgid="5005572078641980632">"Рабочы профіль выдалены"</string>
- <string name="work_profile_deleted_description" msgid="6305147513054341102">"Рабочы профіль выдалены з-за адсутнасці праграмы адміністравання."</string>
- <string name="work_profile_deleted_details" msgid="226615743462361248">"Праграма для адміністравання рабочага профілю адсутнічае або пашкоджана. У выніку гэтага ваш рабочы профіль і звязаныя з ім даныя былі выдаленыя. Звярніцеся па дапамогу да адміністратара."</string>
- <string name="work_profile_deleted_description_dpm_wipe" msgid="6019770344820507579">"Ваш працоўны профіль больш не даступны на гэтай прыладзе."</string>
- <!-- no translation found for network_logging_notification_title (6399790108123704477) -->
- <skip />
- <!-- no translation found for network_logging_notification_text (7930089249949354026) -->
- <skip />
+ <string name="work_profile_deleted_description" msgid="1100529432509639864">"Працоўны профіль выдалены з-за адсутнасці праграмы адміністратара"</string>
+ <string name="work_profile_deleted_details" msgid="6307630639269092360">"Праграма адміністратара для працоўнага профілю адсутнічае або пашкоджана. У выніку гэтага ваш працоўны профіль і звязаныя з ім даныя былі выдалены. Звярніцеся па дапамогу да адміністратара."</string>
+ <string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Ваш працоўны профіль больш не даступны на гэтай прыладзе"</string>
+ <string name="network_logging_notification_title" msgid="6399790108123704477">"Прылада знаходзіцца пад кіраваннем"</string>
+ <string name="network_logging_notification_text" msgid="7930089249949354026">"Ваша арганізацыя кіруе гэтай прыладай і можа сачыць за сеткавым трафікам. Дакраніцеся для атрымання дадатковай інфармацыі."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Даныя вашай прылады будуць сцерты"</string>
- <string name="factory_reset_message" msgid="4905025204141900666">"Праграма для адміністравання не можа быць выкарыстана, таму што ў яе адсутнічаюць кампаненты або яна пашкоджана. Зараз даныя вашай прылады будуць сцерты. Звярніцеся па дапамогу да адміністратара."</string>
+ <string name="factory_reset_message" msgid="7972496262232832457">"Немагчыма выкарыстоўваць праграму адміністратара. Зараз звесткі на вашай прыладзе будуць выдалены.\n\nКалі ў вас ёсць пытанні, звярніцеся да адміністратара вашай арганізацыі."</string>
<string name="me" msgid="6545696007631404292">"Я"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Параметры планшэта"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Параметры ТБ"</string>
@@ -416,8 +412,8 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Дазваляе прыкладанням атрымлiваць доступ да функцый тэлефона на прыладзе. Дзякуючы гэтаму дазволу прыкладанне можа вызначаць iдэнтыфiкатары нумару тэлефона i прылады, незалежна ад таго, цi актыўны выклiк, i аддалены нумар, на якi робiцца выклiк."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"перанакіраванне выклікаў праз сістэму"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Дазваляе праграме перанакіроўваць выклікі праз сістэму ў мэтах паляпшэння выклікаў."</string>
- <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"чытаць нумар тэлефона"</string>
- <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Праграма зможа атрымліваць доступ да тэлефоннага нумара прылады."</string>
+ <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"счытваць нумары тэлефонаў"</string>
+ <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Дазваляе праграме атрымліваць доступ да нумароў тэлефонаў на прыладзе."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"прадухіліць планшэт ад пераходу ў рэжым сну"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"прадухіленне пераходу тэлевізара ў рэжым сну"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"забараняць тэлефону пераходзіць ў рэжым сну"</string>
@@ -557,7 +553,7 @@
<string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Дазваляе праграме чытаць і выконваць запіс у канфігурацыю рэжыму «Не турбаваць»."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Устанавіць правілы паролю"</string>
<string name="policydesc_limitPassword" msgid="2502021457917874968">"Кіраваць даўжынёй і сімваламі, дазволенымі пры ўводзе пароляў і PIN-кодаў блакіроўкі экрана."</string>
- <string name="policylab_watchLogin" msgid="914130646942199503">"Сачыць за спробамі разблакоўкі экрана"</string>
+ <string name="policylab_watchLogin" msgid="5091404125971980158">"Сачыць за спробамі разблакіроўкі экрана"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Сачыць за колькасцю няправільных набраных пароляў падчас разблакоўкі экрана і блакаваць планшэт або сціраць усе дадзеныя на ім, калі няправільны пароль набраны занадта шмат разоў."</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Сачыць за колькасцю няправільна набраных пароляў падчас разблакіроўкі экрана і блакіраваць тэлевізар або сціраць усе даныя на ім, калі няправільны пароль набраны занадта шмат разоў."</string>
<string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Сачыць за колькасцю няправільных набраных пароляў падчас разблакоўкі экрана і блакаваць тяэлефон або сціраць усе дадзеныя на ім, калі набрана занадта шмат няправільных пароляў."</string>
@@ -1010,8 +1006,7 @@
<string name="selectTextMode" msgid="1018691815143165326">"Выбраць тэкст"</string>
<string name="undo" msgid="7905788502491742328">"Адрабіць"</string>
<string name="redo" msgid="7759464876566803888">"Узнавіць"</string>
- <!-- no translation found for autofill (3035779615680565188) -->
- <skip />
+ <string name="autofill" msgid="3035779615680565188">"Аўтазапаўненне"</string>
<string name="textSelectionCABTitle" msgid="5236850394370820357">"Вылучэнне тэксту"</string>
<string name="addToDictionary" msgid="4352161534510057874">"Дадаць у слоўнік"</string>
<string name="deleteText" msgid="6979668428458199034">"Выдалiць"</string>
@@ -1143,7 +1138,13 @@
<string name="network_switch_metered" msgid="4671730921726992671">"Выкананы пераход да <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
<string name="network_switch_metered_detail" msgid="5325661434777870353">"Прылада выкарыстоўвае <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, калі ў <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> няма доступу да інтэрнэту. Можа спаганяцца дадатковая плата."</string>
<string name="network_switch_metered_toast" msgid="5779283181685974304">"Выкананы пераход з <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> да <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
- <!-- no translation found for network_switch_type_name:0 (3979506840912951943) -->
+ <string-array name="network_switch_type_name">
+ <item msgid="3979506840912951943">"мабільная перадача даных"</item>
+ <item msgid="75483255295529161">"Wi-Fi"</item>
+ <item msgid="6862614801537202646">"Bluetooth"</item>
+ <item msgid="5447331121797802871">"Ethernet"</item>
+ <item msgid="8257233890381651999">"VPN"</item>
+ </string-array>
<string name="network_switch_type_name_unknown" msgid="4552612897806660656">"невядомы тып сеткі"</string>
<string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Немагчыма падключыцца да Wi-Fi"</string>
<string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" дрэннае падключэнне да Інтэрнэту."</string>
@@ -1213,7 +1214,7 @@
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Стварэнне справаздачы пра памылку…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Падзяліцца справаздачай пра памылку?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Перадача справаздачы пра памылку..."</string>
- <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"ІТ-адміністратар запытаў справаздачу пра памылку для яе ліквідацыі на гэтай прыладзе. Можа адбыцца абагуленне праграм і даных."</string>
+ <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"Ваш адміністратар запытаў справаздачу пра памылку для яе ліквідацыі на гэтай прыладзе. Звесткі праграм і даныя могуць быць абагулены."</string>
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"АБАГУЛІЦЬ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"АДХІЛІЦЬ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Змяніць клавіятуру"</string>
@@ -1224,7 +1225,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГДЕЁЖЗІЙКЛМНОПРСТУЎФХЦЧШ\'ЫЬЭЮЯ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> паказваецца паверх іншых праграм"</string>
- <string name="alert_windows_notification_title" msgid="4532185840598192445">"<xliff:g id="NAME">%s</xliff:g> паказв. паверх інш. праграм."</string>
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> паказв. паверх іншых праграм"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Калі вы не хочаце, каб праграма <xliff:g id="NAME">%s</xliff:g> выкарыстоўвала гэту функцыю, дакраніцеся, каб адкрыць налады і адключыць гэта."</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"АДКЛЮЧЫЦЬ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Падрыхтоўка <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1401,8 +1402,7 @@
<string name="data_usage_warning_body" msgid="6660692274311972007">"Прагляд выкарыстання і налад."</string>
<string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Дасягнуты ліміт трафіку 2G-3G"</string>
<string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Дасягнуты ліміт трафіку 4G"</string>
- <!-- no translation found for data_usage_mobile_limit_title (6561099244084267376) -->
- <skip />
+ <string name="data_usage_mobile_limit_title" msgid="6561099244084267376">"Дасягн. ліміт маб. перад. даных"</string>
<string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"Дасягн. ліміт перад. даных Wi-Fi"</string>
<string name="data_usage_limit_body" msgid="291731708279614081">"Перад.даных спын. да канца цыкла"</string>
<string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Перавышаны ліміт 2G-3G"</string>
@@ -1501,18 +1501,21 @@
<string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Выдалiць"</string>
<string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Павялiчыць гук вышэй рэкамендаванага ўзроўню?\n\nДоўгае праслухоўванне музыкi на вялiкай гучнасцi можа пашкодзiць ваш слых."</string>
- <string name="accessibility_shortcut_warning_dialog_title" msgid="5998592821749881862">"Камбінацыя хуткага доступу для спецыяльных магчымасцей АКТЫВАВАНА"</string>
- <string name="accessibility_shortcut_toogle_warning" msgid="2987297770937717543">"Уключайце ці адключайце <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, утрымліваючы абедзве кнопкі рэгулявання гучнасці націснутымі на працягу 3 секунд.\n\nВы можаце змяніць сэрвіс у меню \"Налады > Спецыяльныя магчымасці\"."</string>
- <string name="disable_accessibility_shortcut" msgid="3683951963271793789">"Дэактываваць камбінацыю хуткага доступу"</string>
- <string name="leave_accessibility_shortcut_on" msgid="8762106842437042969">"Пакінуць актываванай"</string>
+ <string name="accessibility_shortcut_warning_dialog_title" msgid="8404780875025725199">"Выкарыстоўваць камбінацыю хуткага доступу для спецыяльных магчымасцей?"</string>
+ <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"Калі камбінацыя хуткага доступу ўключана, вы можаце націснуць абедзве кнопкі гучнасці і ўтрымліваць іх 3 секунды, каб уключыць функцыю спецыяльных магчымасцей.\n\n Бягучая функцыя спецыяльных магчымасцей:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Вы можаце змяніць гэту функцыю ў меню \"Налады > Спецыяльныя магчымасці\"."</string>
+ <string name="disable_accessibility_shortcut" msgid="627625354248453445">"Дэактываваць камбінацыю хуткага доступу"</string>
+ <string name="leave_accessibility_shortcut_on" msgid="7653111894438512680">"Выкарыстоўваць камбінацыю хуткага доступу"</string>
<string name="accessibility_shortcut_enabling_service" msgid="7771852911861522636">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> быў уключаны з дапамогай камбінацыі хуткага доступу для спецыяльных магчымасцей"</string>
<string name="accessibility_shortcut_disabling_service" msgid="2747243438223109821">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> быў адключаны з дапамогай камбінацыі хуткага доступу для спецыяльных магчымасцей"</string>
+ <string name="accessibility_button_prompt_text" msgid="4234556536456854251">"Выберыце функцыю для выкарыстання пры націску кнопкі \"Спецыяльныя магчымасці\":"</string>
+ <string name="accessibility_button_instructional_text" msgid="6942300463612999993">"Каб змяняць функцыі, краніце і ўтрымлівайце кнопку \"Спецыяльныя магчымасці\"."</string>
+ <string name="accessibility_magnification_chooser_text" msgid="1227146738764986237">"Павелічэнне"</string>
<string name="user_switched" msgid="3768006783166984410">"Бягучы карыстальнік <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="2871009331809089783">"Пераход да <xliff:g id="NAME">%1$s</xliff:g>..."</string>
<string name="user_logging_out_message" msgid="8939524935808875155">"<xliff:g id="NAME">%1$s</xliff:g> выходзіць з сістэмы…"</string>
<string name="owner_name" msgid="2716755460376028154">"Уладальнік"</string>
<string name="error_message_title" msgid="4510373083082500195">"Памылка"</string>
- <string name="error_message_change_not_allowed" msgid="1347282344200417578">"Ваш адміністратар не дазваляе гэту змену"</string>
+ <string name="error_message_change_not_allowed" msgid="1238035947357923497">"Ваш адміністратар не дазваляе гэту змену"</string>
<string name="app_not_found" msgid="3429141853498927379">"Прыкладанне для гэтага дзеяння не знойдзенае"</string>
<string name="revoke" msgid="5404479185228271586">"Ануляваць"</string>
<string name="mediasize_iso_a0" msgid="1994474252931294172">"ISO A0"</string>
@@ -1604,7 +1607,7 @@
<string name="reason_service_unavailable" msgid="7824008732243903268">"Служба друку не ўключана"</string>
<string name="print_service_installed_title" msgid="2246317169444081628">"Усталявана служба <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="print_service_installed_message" msgid="5897362931070459152">"Краніце, каб уключыць"</string>
- <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"Увядзіце PIN-код адміністратара"</string>
+ <string name="restr_pin_enter_admin_pin" msgid="8641662909467236832">"Увядзіце PIN-код адміністратара"</string>
<string name="restr_pin_enter_pin" msgid="3395953421368476103">"Увядзіце PIN-код"</string>
<string name="restr_pin_incorrect" msgid="8571512003955077924">"Няправільны"</string>
<string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"Бягучы PIN-код"</string>
@@ -1634,16 +1637,16 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (праца)"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"Другая праца <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"Трэцяя праца <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="7693684144593484">"Каб адмацаваць гэты экран, дакраніцеся і ўтрымлівайце кнопкі \"Назад\" і \"Агляд\"."</string>
- <string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Праграма замацавана: адмацаванне на гэтай прыладзе не дапускаецца."</string>
+ <string name="lock_to_app_toast" msgid="6820571533009838261">"Каб адмацаваць гэты экран, краніце і ўтрымлівайце кнопкі \"Назад\" і \"Агляд\""</string>
+ <string name="lock_to_app_toast_locked" msgid="7849470948648628704">"Гэту праграму нельга адмацаваць"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Экран замацаваны"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Экран адмацаваны"</string>
<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="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>
+ <string name="package_installed_device_owner" msgid="6875717669960212648">"Усталяваны вашым адміністратарам"</string>
+ <string name="package_updated_device_owner" msgid="1847154566357862089">"Абноўлены вашым адміністратарам"</string>
+ <string name="package_deleted_device_owner" msgid="2307122077550236438">"Выдалены вашым адміністратарам"</string>
<string name="battery_saver_description" msgid="1960431123816253034">"Каб падоўжыць час працы акумулятара, у рэжыме эканоміі зараду памяншаецца прадукцыйнасць вашай прылады, абмяжоўваецца выкарыстанне вібрацыі, службаў вызначэння месцазнаходжання і большасці задач фонавай перадачы даных. Электронная пошта, абмен паведамленнямі і іншыя праграмы, якія выкарыстоўваюць сінхранізацыю, могуць не абнаўляцца, пакуль вы іх не адкрыеце.\n\nРэжым эканоміі зараду адключаецца аўтаматычна, калі прылада зараджаецца."</string>
<string name="data_saver_description" msgid="6015391409098303235">"Каб паменшыць выкарыстанне даных, Эканомія трафіку не дазваляе некаторым праграмам адпраўляць ці атрымліваць даныя ў фонавым рэжыме. Праграма, якую вы зараз выкарыстоўваеце, можа атрымліваць доступ да даных, але можа рабіць гэта радзей. Гэта можа азначаць, напрыклад, што відарысы не паказваюцца, пакуль вы не дакраняцеся да іх."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"Уключыць Эканомію трафіка?"</string>
@@ -1746,8 +1749,8 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Усе мовы"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Усе рэгіёны"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Шукаць"</string>
- <string name="work_mode_off_title" msgid="8954725060677558855">"Рэжым працы АДКЛЮЧАНЫ"</string>
- <string name="work_mode_off_message" msgid="3286169091278094476">"Дазволіць функцыянаванне працоўнага профілю, у тым ліку праграм, фонавай сінхранізацыі і звязаных з імі функцый."</string>
+ <string name="work_mode_off_title" msgid="2615362773958585967">"Уключыць працоўны рэжым?"</string>
+ <string name="work_mode_off_message" msgid="2961559609199223594">"Гэта прывядзе да ўключэння вашага працоўнага профілю, у тым ліку праграм, фонавай сінхранізацыі і звязаных з імі функцый"</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Уключыць"</string>
<string name="new_sms_notification_title" msgid="8442817549127555977">"У вас ёсць новыя паведамленні"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Праглядзець праз праграму для SMS"</string>
@@ -1790,22 +1793,26 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Увядзіце час"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Пераключыцца на рэжым тэксту пры ўводзе часу."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Пераключыцца на рэжым гадзінніка пры ўводзе часу."</string>
- <!-- no translation found for autofill_picker_accessibility_title (8469043291648711535) -->
- <skip />
+ <string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Параметры аўтазапаўнення"</string>
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Для гэтага змесціва аўтазапаўненне немагчымае"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Захаваць у <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Захаваць наступнае: <xliff:g id="TYPE">%1$s</xliff:g> у <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Захаваць <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> у <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Захаваць <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> у <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Захаваць"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Не, дзякуй"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"пароль"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"адрас"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"крэдытная картка"</string>
- <!-- no translation found for etws_primary_default_message_earthquake (5541962250262769193) -->
- <skip />
- <!-- no translation found for etws_primary_default_message_tsunami (1887685943498368548) -->
- <skip />
- <!-- no translation found for etws_primary_default_message_earthquake_and_tsunami (998797956848445862) -->
- <skip />
- <!-- no translation found for etws_primary_default_message_test (2709597093560037455) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"карыстальнік"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"адрас электроннай пошты"</string>
+ <string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Заставайцеся спакойнымі і пашукайце прытулак паблізу."</string>
+ <string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Неадкладна эвакуіруйцеся з прыбярэжных раёнаў у больш бяспечнае месца, напрыклад на ўзвышша."</string>
+ <string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Заставайцеся спакойнымі і пашукайце прытулак паблізу."</string>
+ <string name="etws_primary_default_message_test" msgid="2709597093560037455">"Праверка экстранных паведамленняў"</string>
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
+ <string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM-карта не дапускаецца"</string>
+ <string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM-карты няма"</string>
+ <string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM-карта не дапускаецца"</string>
+ <string name="mmcc_illegal_me" msgid="4438696681169345015">"Тэлефон не дапускаецца"</string>
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 2a77fac..cfb8177 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Превключете към режима за въвеждане на текст, за да въведете часа."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Превключете към режима за часовник, за да въведете часа."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Опции за автоматично попълване"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Съдържанието не може да бъде попълнено автоматично"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Да се запази ли в/ъв „<xliff:g id="LABEL">%1$s</xliff:g>“?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> да се запази ли в/ъв „<xliff:g id="LABEL">%2$s</xliff:g>“?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Искате ли да запазите <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> в/ъв „<xliff:g id="LABEL">%3$s</xliff:g>“?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Искате ли да запазите <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> в/ъв „<xliff:g id="LABEL">%4$s</xliff:g>“?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Запазване"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Не, благодаря"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"Паролата"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"Адресът"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"Кредитната карта"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"потребителско име"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"имейл адрес"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Запазете спокойствие и потърсете убежище в района."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Евакуирайте се незабавно от крайбрежните и крайречните региони на по-безопасно място – например такова с по-високо надморско равнище."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Запазете спокойствие и потърсете убежище в района."</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 3a5fdec..83db42c 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1733,19 +1733,20 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"সময় ইনপুট দেওয়ার জন্য পাঠ্য ইনপুট মোডে যান।"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"সময় ইনপুট দেওয়ার জন্য ঘড়ি মোডে যান।"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"আপনাআপনি পূরণ করার বিকল্পগুলি"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"বিষয়বস্তুগুলি অটো-ফিল করা যাবে না"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> এ সংরক্ষণ করবেন?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="LABEL">%2$s</xliff:g> এ <xliff:g id="TYPE">%1$s</xliff:g> সংরক্ষণ করবেন?"</string>
+ <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
+ <skip />
<string name="autofill_save_yes" msgid="6398026094049005921">"সংরক্ষণ করুন"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"না থাক"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"পাসওয়ার্ড"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"ঠিকানা"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ক্রেডিট কার্ড"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"ইউজারনেম"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"ইমেল ঠিকানা"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"শান্ত থাকুন, আশেপাশে আশ্রয় খুঁজুন।"</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"উপকূলবর্তী এবং নদীর পাশের অঞ্চল থেকে অবিলম্বে উঁচু কোনো জায়গার দিকে যান।"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"শান্ত থাকুন, আশেপাশে আশ্রয় খুঁজুন।"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 92294dc..6b8fa78 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -90,17 +90,16 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Prikaz ID-a pozivaoca u zadanim postavkama nije zabranjen. Sljedeći poziv: nije zabranjen"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"Uslugu nije moguće koristiti."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Ne možete promijeniti postavke ID-a pozivaoca."</string>
- <string name="RestrictedOnData" msgid="8653794784690065540">"Usluga prijenosa podataka je blokirana."</string>
- <string name="RestrictedOnEmergency" msgid="6581163779072833665">"Hitni pozivi su blokirani."</string>
- <string name="RestrictedOnNormal" msgid="4953867011389750673">"Govorne usluge su blokirane."</string>
- <string name="RestrictedOnAllVoice" msgid="3396963652108151260">"Sve govorne usluge su blokirane."</string>
- <string name="RestrictedOnSms" msgid="8314352327461638897">"SMS usluga je blokirana."</string>
- <string name="RestrictedOnVoiceData" msgid="996636487106171320">"Blokirane su govorne usluge i usluge prijenosa podataka."</string>
- <string name="RestrictedOnVoiceSms" msgid="1888588152792023873">"Blokirane su govorne/SMS usluge."</string>
- <string name="RestrictedOnAll" msgid="5643028264466092821">"Blokirane su sve govorne i SMS usluge te usluge prijenosa podataka."</string>
+ <string name="RestrictedOnDataTitle" msgid="1322504692764166532">"Nema usluge prijenosa mobilnih podataka"</string>
+ <string name="RestrictedOnEmergencyTitle" msgid="1236071219598685236">"Nema usluge za hitne slučajeve"</string>
+ <string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"Nema usluge govornih poziva"</string>
+ <string name="RestrictedOnAllVoiceTitle" msgid="158800171499150681">"Nema govornih/hitnih usluga"</string>
+ <string name="RestrictedOnDataContent" msgid="8997474569390996587">"Vaš operater je privremeno obustavio uslugu prijenosa mobilnih podataka na ovoj lokaciji"</string>
+ <string name="RestrictedOnEmergencyContent" msgid="4573217945494650061">"Vaš operater je privremeno obustavio hite pozive na ovoj lokaciji"</string>
+ <string name="RestrictedOnNormalContent" msgid="1579434198284512182">"Vaš operater je privremeno obustavio govorne pozive na ovoj lokaciji"</string>
+ <string name="RestrictedOnAllVoiceContent" msgid="5243580774142557047">"Vaš operater je na ovoj lokaciji privremeno obustavio govorne i hitne pozive."</string>
<string name="NetworkPreferenceSwitchTitle" msgid="4008877505368566980">"Nije moguće dosegnuti mrežu"</string>
- <!-- no translation found for NetworkPreferenceSwitchSummary (4164230263214915351) -->
- <skip />
+ <string name="NetworkPreferenceSwitchSummary" msgid="4164230263214915351">"Za poboljšanje prijema, pokušajte promijeniti tip odabran u meniju Sistem > Mreža i internet > Mobilne mreže > Preferirani tip mreže."</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"Ravnopravni uređaj zatražio TTY PUNI način rada"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"Ravnopravni uređaj zatražio TTY HCO način rada"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"Ravnopravni uređaj zatražio TTY VCO način rada"</string>
@@ -140,8 +139,7 @@
</string-array>
<string name="wifi_calling_off_summary" msgid="8720659586041656098">"Isključeno"</string>
<string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Prednost ima Wi-Fi"</string>
- <!-- no translation found for wfc_mode_cellular_preferred_summary (1988279625335345908) -->
- <skip />
+ <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferira se mobilna mreža"</string>
<string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Samo Wi-Fi"</string>
<string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije proslijeđen"</string>
<string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -180,18 +178,16 @@
<item quantity="other">Instalirane su ustanove za izdavanje certifikata</item>
</plurals>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Od nepoznate treće strane"</string>
- <string name="ssl_ca_cert_noti_by_administrator" msgid="550758088185764312">"od strane administratora vašeg profila za posao"</string>
+ <string name="ssl_ca_cert_noti_by_administrator" msgid="3541729986326153557">"Administrator vašeg radnog profila"</string>
<string name="ssl_ca_cert_noti_managed" msgid="4030263497686867141">"Od <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string>
<string name="work_profile_deleted" msgid="5005572078641980632">"Poslovni profil je obrisan"</string>
- <string name="work_profile_deleted_description" msgid="6305147513054341102">"Poslovni profil je obrisan jer nedostaje aplikacija administratora."</string>
- <string name="work_profile_deleted_details" msgid="226615743462361248">"Aplikacija administratora za poslovni profil nedostaje ili je neispravna. Zbog toga su vaš poslovni profil i vezani podaci obrisani. Za pomoć se obratite administratoru."</string>
- <string name="work_profile_deleted_description_dpm_wipe" msgid="6019770344820507579">"Profil za posao više nije dostupan na ovom uređaju."</string>
- <!-- no translation found for network_logging_notification_title (6399790108123704477) -->
- <skip />
- <!-- no translation found for network_logging_notification_text (7930089249949354026) -->
- <skip />
+ <string name="work_profile_deleted_description" msgid="1100529432509639864">"Radni profil je izbrisan jer nedostaje aplikacija administratora"</string>
+ <string name="work_profile_deleted_details" msgid="6307630639269092360">"Nedostaje aplikacija administratora za radni profil ili je neispravna. Zbog toga su vaš radni profil i povezani podaci izbrisani. Obratite administratoru za pomoć."</string>
+ <string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"Radni profil više nije dostupan na ovom uređaju"</string>
+ <string name="network_logging_notification_title" msgid="6399790108123704477">"Uređajem se upravlja."</string>
+ <string name="network_logging_notification_text" msgid="7930089249949354026">"Vaša organizacija upravlja ovim uređajem i može pratiti mrežni saobraćaj. Dodirnite za detalje."</string>
<string name="factory_reset_warning" msgid="5423253125642394387">"Uređaj će biti izbrisan"</string>
- <string name="factory_reset_message" msgid="4905025204141900666">"Aplikaciji administratora nedostaju komponente ili je neispravna, i ne može se koristiti. Vaš uređaj će sada biti izbrisan. Za pomoć se obratite administratoru."</string>
+ <string name="factory_reset_message" msgid="7972496262232832457">"Nije moguće koristiti aplikaciju administratora. Potpuno će se izbrisati podaci na vašem uređaju.\n\nAko imate pitanja, obratite se administratoru vaše organizacije."</string>
<string name="me" msgid="6545696007631404292">"Ja"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opcije tableta"</string>
<string name="power_dialog" product="tv" msgid="6153888706430556356">"Opcije za TV"</string>
@@ -413,8 +409,8 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Omogućava aplikaciji pristup telefonskim funkcijama uređaja. Ova dozvola omogućava aplikaciji određivanje telefonskog i identifikacionog broja uređaja, bez obzira da li je poziv aktivan i da li je uspostavljena veza sa pozivanim brojem."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"usmjeravanje poziva preko sistema"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Dopušta aplikaciji da pozive usmjeri preko sistema radi poboljšanja iskustva pozivanja."</string>
- <string name="permlab_readPhoneNumber" msgid="6421295519255154171">"čitanje telefonskog broja"</string>
- <string name="permdesc_readPhoneNumber" msgid="9135856402838173711">"Dopušta aplikaciji pristup telefonskom broju telefona."</string>
+ <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"čitanje telefonskih brojeva"</string>
+ <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Dozvoljava aplikaciji pristup telefonskim brojevima uređaja."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"sprečavanje tableta da uđe u režim mirovanja"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"spriječi ulazak TV-a u režim mirovanja"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"sprečavanje telefona da uđe u režim mirovanja"</string>
@@ -554,7 +550,7 @@
<string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Omogućava aplikaciji da čita i upisuje konfiguraciju opcije Ne ometaj."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Postavljanje pravila za lozinke"</string>
<string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolira dužinu i znakove koji su dozvoljeni u lozinkama za zaključavanje ekrana i PIN kodovima."</string>
- <string name="policylab_watchLogin" msgid="914130646942199503">"Prati pokušaje otključavanja ekrana"</string>
+ <string name="policylab_watchLogin" msgid="5091404125971980158">"Prati pokušaje otključavanja ekrana"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Prati broj pogrešno unijetih lozinki prilikom otključavanja ekrana i zaključava tablet ili briše sve podatke s njega ukoliko se previše puta unese pogrešna lozinka."</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Prati koliko puta je lozinka neispravno otkucana prilikom otključavanja ekrana i zaključaj TV ili izbriši sve podatke s TV-a ako se lozinka neispravno ukuca previše puta."</string>
<string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Prati broj pogrešno unesenih lozinki prilikom otključavanja ekrana i zaključava telefon ili briše sve podatke s telefona ukoliko se previše puta unese pogrešna lozinka."</string>
@@ -990,8 +986,7 @@
<string name="selectTextMode" msgid="1018691815143165326">"Odaberi tekst"</string>
<string name="undo" msgid="7905788502491742328">"Vrati"</string>
<string name="redo" msgid="7759464876566803888">"Ponovo uradi"</string>
- <!-- no translation found for autofill (3035779615680565188) -->
- <skip />
+ <string name="autofill" msgid="3035779615680565188">"Automatsko popunjavanje"</string>
<string name="textSelectionCABTitle" msgid="5236850394370820357">"Odabir teksta"</string>
<string name="addToDictionary" msgid="4352161534510057874">"Dodaj u rječnik"</string>
<string name="deleteText" msgid="6979668428458199034">"Izbriši"</string>
@@ -1125,7 +1120,13 @@
<string name="network_switch_metered" msgid="4671730921726992671">"Prebačeno na: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
<string name="network_switch_metered_detail" msgid="5325661434777870353">"Kada na uređaju <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nema pristup internetu, koristi se <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Moguća je naplata usluge."</string>
<string name="network_switch_metered_toast" msgid="5779283181685974304">"Prebačeno iz mreže <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> u <xliff:g id="NEW_NETWORK">%2$s</xliff:g> mrežu"</string>
- <!-- no translation found for network_switch_type_name:0 (3979506840912951943) -->
+ <string-array name="network_switch_type_name">
+ <item msgid="3979506840912951943">"mobilni podaci"</item>
+ <item msgid="75483255295529161">"Wi-Fi"</item>
+ <item msgid="6862614801537202646">"Bluetooth"</item>
+ <item msgid="5447331121797802871">"Ethernet"</item>
+ <item msgid="8257233890381651999">"VPN"</item>
+ </string-array>
<string name="network_switch_type_name_unknown" msgid="4552612897806660656">"nepoznata vrsta mreže"</string>
<string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Problem prilikom spajanja na Wi-Fi mrežu"</string>
<string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ima lošu internet vezu."</string>
@@ -1198,7 +1199,7 @@
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Prijem izvještaja o grešci..."</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Podijeliti izvještaj o grešci?"</string>
<string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Dijeljenje izvještaja o grešci..."</string>
- <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Vaš IT administrator je zatražio izvještaj o grešci kako bi pomogao u rješavanju problema ovog uređaja. Aplikacije i podaci se mogu dijeliti."</string>
+ <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"Vaš administrator je zatražio izvještaj o greškama kako bi pomogao u rješavanju problema ovog uređaja. Moguće je dijeljenje aplikacija i podataka."</string>
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"PODIJELI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODBACI"</string>
<string name="select_input_method" msgid="8547250819326693584">"Promijeni tastaturu"</string>
@@ -1209,7 +1210,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Aplikacija <xliff:g id="NAME">%s</xliff:g> prekriva ostale aplikacije"</string>
- <string name="alert_windows_notification_title" msgid="4532185840598192445">"Aplikacija <xliff:g id="NAME">%s</xliff:g> prekriva ostale aplikacije."</string>
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"Aplikacija <xliff:g id="NAME">%s</xliff:g> prekriva druge apl."</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Ako ne želite da <xliff:g id="NAME">%s</xliff:g> koristi ovu funkciju, dodirnite da otvorite postavke i isključite je."</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ISKLJUČI"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Priprema se <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1385,8 +1386,7 @@
<string name="data_usage_warning_body" msgid="6660692274311972007">"Dodirnite za prikaz upotrebe i postavki."</string>
<string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Dostignut limit za 2G-3G podatke"</string>
<string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Dostignut limit za 4G podatke"</string>
- <!-- no translation found for data_usage_mobile_limit_title (6561099244084267376) -->
- <skip />
+ <string name="data_usage_mobile_limit_title" msgid="6561099244084267376">"Dostignut limit za mob. podatke"</string>
<string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"Dostignut limit Wi-Fi podataka"</string>
<string name="data_usage_limit_body" msgid="291731708279614081">"Podaci pauz. za ostatak ciklusa"</string>
<string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Premašeni 2G-3G podaci"</string>
@@ -1486,18 +1486,21 @@
<string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Ukloni"</string>
<string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Želite li pojačati zvuk iznad preporučenog nivoa?\n\nDužim slušanjem glasnog zvuka možete oštetiti sluh."</string>
- <string name="accessibility_shortcut_warning_dialog_title" msgid="5998592821749881862">"Prečica za pristupačnost je UKLJUČENA"</string>
- <string name="accessibility_shortcut_toogle_warning" msgid="2987297770937717543">"Držite oba dugmeta za podešavanje jačine zvuka 3 sekunde da uključite ili isključite uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>.\n\nUslugu možete promijeniti ako odete u Postavke > Pristupačnost."</string>
- <string name="disable_accessibility_shortcut" msgid="3683951963271793789">"Isključi prečicu"</string>
- <string name="leave_accessibility_shortcut_on" msgid="8762106842437042969">"Ostavi uključeno"</string>
+ <string name="accessibility_shortcut_warning_dialog_title" msgid="8404780875025725199">"Želite li koristiti Prečicu za pristupačnost?"</string>
+ <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"Kada je prečica uključena, pritiskom na oba dugmeta za podešavanje jačine zvuka u trajanju od 3 sekunde pokrenut će se funkcija za pristupačnost.\n\n Trenutna funkcija za pristupačnost je:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funkciju možete promijeniti ako odete u Postavke > Pristupačnost."</string>
+ <string name="disable_accessibility_shortcut" msgid="627625354248453445">"Isključi prečicu"</string>
+ <string name="leave_accessibility_shortcut_on" msgid="7653111894438512680">"Koristi prečicu"</string>
<string name="accessibility_shortcut_enabling_service" msgid="7771852911861522636">"Prečica za pristupačnost je uključila uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
<string name="accessibility_shortcut_disabling_service" msgid="2747243438223109821">"Prečica za pristupačnost je isključila uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+ <string name="accessibility_button_prompt_text" msgid="4234556536456854251">"Izaberite funkciju koja će se koristiti kada dodirnete dugme Pristupačnost:"</string>
+ <string name="accessibility_button_instructional_text" msgid="6942300463612999993">"Da promijenite funkcije, dodirnite i držite dugme Pristupačnost."</string>
+ <string name="accessibility_magnification_chooser_text" msgid="1227146738764986237">"Uvećanje"</string>
<string name="user_switched" msgid="3768006783166984410">"Trenutni korisnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="2871009331809089783">"Prebacivanje na korisnika <xliff:g id="NAME">%1$s</xliff:g>..."</string>
<string name="user_logging_out_message" msgid="8939524935808875155">"Odjava korisnika <xliff:g id="NAME">%1$s</xliff:g>…"</string>
<string name="owner_name" msgid="2716755460376028154">"Vlasnik"</string>
<string name="error_message_title" msgid="4510373083082500195">"Greška"</string>
- <string name="error_message_change_not_allowed" msgid="1347282344200417578">"Promjenu ne dopušta vaš administrator"</string>
+ <string name="error_message_change_not_allowed" msgid="1238035947357923497">"Vaš administrator ne dozvoljava ovu promjenu"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nije pronađena aplikacija koja će upravljati ovom akcijom."</string>
<string name="revoke" msgid="5404479185228271586">"Opozovi"</string>
<string name="mediasize_iso_a0" msgid="1994474252931294172">"ISO A0"</string>
@@ -1589,7 +1592,7 @@
<string name="reason_service_unavailable" msgid="7824008732243903268">"Usluga štampanja nije omogućena."</string>
<string name="print_service_installed_title" msgid="2246317169444081628">"Usluga <xliff:g id="NAME">%s</xliff:g> je instalirana"</string>
<string name="print_service_installed_message" msgid="5897362931070459152">"Dodirnite da omogućite"</string>
- <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"Unesite administratorski PIN"</string>
+ <string name="restr_pin_enter_admin_pin" msgid="8641662909467236832">"Upišite PIN kôd administratora"</string>
<string name="restr_pin_enter_pin" msgid="3395953421368476103">"Unesite PIN"</string>
<string name="restr_pin_incorrect" msgid="8571512003955077924">"Netačno"</string>
<string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"Trenutni PIN"</string>
@@ -1618,16 +1621,16 @@
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5048136430082124036">"2. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="2808305070321719040">"3. poslovni <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_toast" msgid="7693684144593484">"Da biste otkačili ovaj ekran, dodirnite i držite dugme Nazad i Pregled."</string>
- <string name="lock_to_app_toast_locked" msgid="9125176335701699164">"Aplikacija je prikačena. Na ovom uređaju nije dozvoljeno otkačivanje."</string>
+ <string name="lock_to_app_toast" msgid="6820571533009838261">"Da otkačite ovaj ekran, dodirnite i držite dugmad Nazad i Pregled."</string>
+ <string name="lock_to_app_toast_locked" msgid="7849470948648628704">"Ova aplikacija se ne može otkačiti"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran je zakačen"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Ekran je otkačen"</string>
<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="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>
+ <string name="package_installed_device_owner" msgid="6875717669960212648">"Instalirao je vaš administrator"</string>
+ <string name="package_updated_device_owner" msgid="1847154566357862089">"Ažurirao je vaš administrator"</string>
+ <string name="package_deleted_device_owner" msgid="2307122077550236438">"Izbrisao je vaš administrator"</string>
<string name="battery_saver_description" msgid="1960431123816253034">"Da bi se trajanje baterije produžilo, opcija za štednju baterije minimizira rad uređaja i ograničava vibriranje, usluge lokacije i većinu prijenosa podataka u pozadini. E-pošta, poruke i druge aplikacije koje se oslanjaju na sinhronizaciju ne mogu biti ažurirane dok ih ne otvorite.\n\nŠtednja baterije se automatski isključi prilikom punjenja uređaja."</string>
<string name="data_saver_description" msgid="6015391409098303235">"Da bi se smanjio prijenos podataka, usluga Ušteda podataka sprečava da neke aplikacije šalju ili primaju podatke u pozadini. Aplikacija koju trenutno koristite može pristupiti podacima, ali se to može desiti rjeđe. To može značiti, naprimjer, da se slike ne prikazuju sve dok ih ne dodirnete."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"Uključiti Uštedu podataka?"</string>
@@ -1721,8 +1724,8 @@
<string name="language_picker_section_all" msgid="3097279199511617537">"Svi jezici"</string>
<string name="region_picker_section_all" msgid="8966316787153001779">"Sve regije"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Pretraga"</string>
- <string name="work_mode_off_title" msgid="8954725060677558855">"Radni način rada je ISKLJUČEN"</string>
- <string name="work_mode_off_message" msgid="3286169091278094476">"Omogući radnom profilu da funkcionira, uključujući aplikacije, sinhronizaciju u pozadini i povezane funkcije."</string>
+ <string name="work_mode_off_title" msgid="2615362773958585967">"Želite uključiti radni način?"</string>
+ <string name="work_mode_off_message" msgid="2961559609199223594">"Ovim će se uključiti vaš radni profil, uključujući aplikacije, sinhronizacija u pozadini i povezane funkcije"</string>
<string name="work_mode_turn_on" msgid="2062544985670564875">"Uključi"</string>
<string name="new_sms_notification_title" msgid="8442817549127555977">"Imate nove poruke"</string>
<string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorite SMS aplikaciju da biste pregledali poruke"</string>
@@ -1765,22 +1768,26 @@
<string name="time_picker_prompt_label" msgid="7588093983899966783">"Upišite vrijeme"</string>
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Prebacite u način unosa teksta za unos vremena."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Prebacite u način rada kao sat za unos vremena."</string>
- <!-- no translation found for autofill_picker_accessibility_title (8469043291648711535) -->
- <skip />
+ <string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opcije za automatsko popunjavanje"</string>
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Sadržaje nije moguće automatski popuniti"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Želite li sačuvati u: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Želite li sačuvati stavku <xliff:g id="TYPE">%1$s</xliff:g> u: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Želite li <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> sačuvati u <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Želite li <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> sačuvati u <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Sačuvaj"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"lozinka"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adresa"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditna kartica"</string>
- <!-- no translation found for etws_primary_default_message_earthquake (5541962250262769193) -->
- <skip />
- <!-- no translation found for etws_primary_default_message_tsunami (1887685943498368548) -->
- <skip />
- <!-- no translation found for etws_primary_default_message_earthquake_and_tsunami (998797956848445862) -->
- <skip />
- <!-- no translation found for etws_primary_default_message_test (2709597093560037455) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"korisničko ime"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"adresa e-pošte"</string>
+ <string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Ostanite smireni i potražite sklonište u blizini."</string>
+ <string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Odmah se evakuirajte iz priobalnih područja i područja oko rijeka na sigurnije mjesto kao što su viši predjeli."</string>
+ <string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Ostanite smireni i potražite sklonište u blizini."</string>
+ <string name="etws_primary_default_message_test" msgid="2709597093560037455">"Test poruka za hitne slučajeve"</string>
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
+ <string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM kartica nije dozvoljena"</string>
+ <string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM kartica nije dodijeljena"</string>
+ <string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM kartica nije dozvoljena"</string>
+ <string name="mmcc_illegal_me" msgid="4438696681169345015">"Telefon nije dozvoljen"</string>
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index ada00d2..0a63cdf 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1185,7 +1185,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"S\'està superposant <xliff:g id="NAME">%s</xliff:g> a altres aplicacions"</string>
- <string name="alert_windows_notification_title" msgid="3697657294867638947">"Superposant <xliff:g id="NAME">%s</xliff:g> a altres apps"</string>
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> s\'està superposant a altres apps"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Si no vols que <xliff:g id="NAME">%s</xliff:g> utilitzi aquesta funció, toca per obrir la configuració i desactiva-la."</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESACTIVA"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"S\'està preparant <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Canvia al mode d\'introducció de text per introduir l\'hora."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Canvia al mode de rellotge per introduir l\'hora."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opcions d\'emplenament automàtic"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"El contingut no es pot emplenar automàticament"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Vols desar-ho a <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Vols desar la informació del camp <xliff:g id="TYPE">%1$s</xliff:g> a <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Vols desar la informació dels camps <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Vols desar la informació dels camps <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> a <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Desa"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"No, gràcies"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"contrasenya"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adreça"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"targeta de crèdit"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"nom d\'usuari"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"adreça electrònica"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Mantén la calma i busca refugi a prop."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Abandona immediatament les regions costaneres i riberenques, i cerca un lloc més segur, com ara un terreny elevat."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Mantén la calma i busca refugi a prop."</string>
@@ -1753,5 +1752,5 @@
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM no compatible"</string>
<string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM no proporcionada"</string>
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM no compatible"</string>
- <string name="mmcc_illegal_me" msgid="4438696681169345015">"Telèfonno no compatible"</string>
+ <string name="mmcc_illegal_me" msgid="4438696681169345015">"Telèfon no no compatible"</string>
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index eab7078..0b9b95d 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1794,19 +1794,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Chcete-li zadat čas, přepněte na režim textu."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Chcete-li zadat čas, přepněte na režim hodin."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Možnosti automatického vyplňování"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Obsah nelze automaticky vyplnit"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Uložit do služby <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Uložit položku <xliff:g id="TYPE">%1$s</xliff:g> do služby <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Má se <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> uložit do služby <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Má se <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g> uložit do služby <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Uložit"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Ne, děkuji"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"heslo"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adresa"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"platební karta"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"uživatelské jméno"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"e-mailová adresa"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Zachovejte klid a přesuňte se na bezpečné místo v okolí."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Z pobřežních oblastí a okolí řek se co nejrychleji přesuňte do většího bezpečí (například na výše položené místo)."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Zachovejte klid a přesuňte se na bezpečné místo v okolí."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index e66a146..1708834 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Skift til teksttilstand for at angive klokkeslæt."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Skift til urtilstand for at angive klokkeslæt."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Valgmuligheder for AutoFyld"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Indhold kan ikke udfyldes automatisk"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Skal indholdet gemmes i <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Skal <xliff:g id="TYPE">%1$s</xliff:g> gemmes i <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Vil du gemme <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> til <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Vil du gemme <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> til <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Gem"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Nej tak"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"adgangskode"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adresse"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditkort"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"brugernavn"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"mailadresse"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Bevar roen, og søg ly i nærheden."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Forlad omgående kyst- og flodområder, og søg mod et mere sikkert sted, f.eks. et højere terræn."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Bevar roen, og søg ly i nærheden."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index a0ebdeb..6e930ff 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"In den Texteingabemodus wechseln, um die Uhrzeit einzugeben."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"In den Uhrzeitmodus wechseln, um die Uhrzeit einzugeben."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"AutoFill-Optionen"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Inhalte können nicht automatisch ausgefüllt werden"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"In <xliff:g id="LABEL">%1$s</xliff:g> speichern?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> in <xliff:g id="LABEL">%2$s</xliff:g> speichern?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"\"<xliff:g id="TYPE_0">%1$s</xliff:g>\" und \"<xliff:g id="TYPE_1">%2$s</xliff:g>\" in \"<xliff:g id="LABEL">%3$s</xliff:g>\" speichern?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"\"<xliff:g id="TYPE_0">%1$s</xliff:g>\", \"<xliff:g id="TYPE_1">%2$s</xliff:g>\" und \"<xliff:g id="TYPE_2">%3$s</xliff:g>\" in \"<xliff:g id="LABEL">%4$s</xliff:g>\" speichern?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Speichern"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Nein danke"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"Passwort"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"Adresse"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"Kreditkarte"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"Nutzername"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"E-Mail-Adresse"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Bleibe ruhig und suche in der Nähe Schutz."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Verlasse so schnell wie möglich Flussufer und Küstengebiete und suche in einer höher gelegenen Umgebung Schutz."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Bleibe ruhig und suche in der Nähe Schutz."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 5805f83..99fa2e5 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Κάντε εναλλαγή στη λειτουργία εισαγωγής κειμένου, για την εισαγωγή της ώρας."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Κάντε εναλλαγή στη λειτουργία ρολογιού, για την εισαγωγή της ώρας."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Επιλογές αυτόματης συμπλήρωσης"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Δεν είναι δυνατή η αυτόματη συμπλήρωση των περιεχομένων"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Αποθήκευση σε <xliff:g id="LABEL">%1$s</xliff:g>;"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Αποθήκευση <xliff:g id="TYPE">%1$s</xliff:g> σε <xliff:g id="LABEL">%2$s</xliff:g>;"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Αποθήκευση <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> σε <xliff:g id="LABEL">%3$s</xliff:g>;"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Αποθήκευση <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> σε <xliff:g id="LABEL">%4$s</xliff:g>;"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Αποθήκευση"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Όχι, ευχαριστώ"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"κωδικός πρόσβασης"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"διεύθυνση"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"πιστωτική κάρτα"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"όνομα χρήστη"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"διεύθυνση email"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Μείνετε ψύχραιμοι και αναζητήστε κάποιο κοντινό καταφύγιο."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Εκκενώστε αμέσως τις παράκτιες περιοχές και τις περιοχές δίπλα σε ποτάμια και μετακινηθείτε σε ένα ασφαλέστερο μέρος, όπως περιοχές με υψόμετρο."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Μείνετε ψύχραιμοι και αναζητήστε κάποιο κοντινό καταφύγιο."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 500754d..0a6a7d5 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Switch to text input mode for the time input."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Switch to clock mode for the time input."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Auto-fill options"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Contents can’t be auto-filled"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Save to <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Save <xliff:g id="TYPE">%1$s</xliff:g> to <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> to <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> to <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"No thanks"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"address"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"credit card"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"username"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"email address"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Stay calm and seek shelter nearby."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evacuate immediately from coastal regions and riverside areas to a safer place such as high ground."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Stay calm and seek shelter nearby."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 500754d..0a6a7d5 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Switch to text input mode for the time input."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Switch to clock mode for the time input."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Auto-fill options"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Contents can’t be auto-filled"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Save to <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Save <xliff:g id="TYPE">%1$s</xliff:g> to <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> to <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> to <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"No thanks"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"address"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"credit card"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"username"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"email address"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Stay calm and seek shelter nearby."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evacuate immediately from coastal regions and riverside areas to a safer place such as high ground."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Stay calm and seek shelter nearby."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 500754d..0a6a7d5 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Switch to text input mode for the time input."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Switch to clock mode for the time input."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Auto-fill options"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Contents can’t be auto-filled"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Save to <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Save <xliff:g id="TYPE">%1$s</xliff:g> to <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> to <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> to <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"No thanks"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"address"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"credit card"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"username"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"email address"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Stay calm and seek shelter nearby."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evacuate immediately from coastal regions and riverside areas to a safer place such as high ground."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Stay calm and seek shelter nearby."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index feccac9..df55b6c 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Cambia al modo de entrada de texto para ingresar la hora."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Cambia al modo de reloj para ingresar la hora."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opciones de autocompletar"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"El contenido no puede autocompletarse"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"¿Quieres guardar el contenido en <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"¿Quieres guardar el contenido de <xliff:g id="TYPE">%1$s</xliff:g> en <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"¿Guardar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"¿Guardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g> en <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Guardar"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"No, gracias"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"contraseña"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"dirección"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"tarjeta de crédito"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"nombre de usuario"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"dirección de correo electrónico"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Mantén la calma y busca un refugio cercano."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evacúa inmediatamente las regiones costeras y ribereñas en busca de un lugar seguro, como un terreno elevado."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Mantén la calma y busca un refugio cercano."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index f5bb4a0..c46146d 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Cambia al modo de introducción de texto para escribir la hora."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Cambia al modo de reloj para escribir la hora."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opciones de Autocompletar"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"El contenido no se puede autocompletar"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"¿Guardar en <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"¿Guardar <xliff:g id="TYPE">%1$s</xliff:g> en <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"¿Guardar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"¿Guardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g> en <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Guardar"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"No, gracias"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"contraseña"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"dirección"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"tarjeta de crédito"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"nombre de usuario"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"dirección de correo electrónico"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Mantén la calma y busca refugio en algún lugar cercano."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Aléjate inmediatamente de las zonas costeras y situadas junto a un río para dirigirte hacia un lugar más seguro, por ejemplo, un terreno elevado."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Mantén la calma y busca refugio en algún lugar cercano."</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index aa73458..4bd9ef8 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Aktiveerige kellaaja sisestamiseks tekstisisestusrežiim."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Aktiveerige kellaaja sisestamiseks kellarežiim."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Automaatse täitmise valikud"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Sisu ei saa automaatselt täita"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Kas salvestada sildiga <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Kas salvestada <xliff:g id="TYPE">%1$s</xliff:g> sildiga <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Kas salvestada <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> teenusesse <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Kas salvestada <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g> teenusesse <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Salvesta"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Tänan, ei"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"parool"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"aadress"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"krediitkaart"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"kasutajanimi"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"e-posti aadress"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Jääge rahulikuks ja otsige lähedusest peavarju."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evakueeruge ranniku ja jõekallaste piirkondadest viivitamatult ohutusse kohta, näiteks kõrgematesse kohtadesse."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Jääge rahulikuks ja otsige lähedusest peavarju."</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index d151045..5c1b423ca 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -307,7 +307,7 @@
<string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"birbideratu irteerako deiak"</string>
<string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Irteerako deian markatutako zenbakia ikustea baimentzen die aplikazioei, deia beste zenbaki batera birbideratzeko edo deia bertan behera uzteko aukerarekin."</string>
<string name="permlab_answerPhoneCalls" msgid="4077162841226223337">"erantzun telefono-deiak"</string>
- <string name="permdesc_answerPhoneCalls" msgid="2901889867993572266">"Sarrerako deiak hartzea baimentzen dio aplikazioari."</string>
+ <string name="permdesc_answerPhoneCalls" msgid="2901889867993572266">"Sarrerako deiak hartzea baimentzen die aplikazioei."</string>
<string name="permlab_receiveSms" msgid="8673471768947895082">"jaso testu-mezuak (SMSak)"</string>
<string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string>
<string name="permlab_receiveMms" msgid="1821317344668257098">"jaso testu-mezuak (MMSak)"</string>
@@ -405,9 +405,9 @@
<string name="permlab_readPhoneState" msgid="9178228524507610486">"irakurri telefonoaren egoera eta identitatea"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Gailuaren telefono-eginbideak atzitzeko baimena ematen die aplikazioei. Baimen horrek aplikazioari telefono-zenbakia eta gailu IDak zein diren, deirik aktibo dagoen eta deia zer zenbakirekin konektatuta dagoen zehazteko baimena ematen die aplikazioei."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"bideratu deiak sistemaren bidez"</string>
- <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Deiak sistemaren bidez bideratzea baimentzen dio aplikazioari, deien zerbitzua ahal bezain ona izan dadin."</string>
+ <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Deiak sistemaren bidez bideratzea baimentzen die aplikazioei, deien zerbitzua ahal bezain ona izan dadin."</string>
<string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"irakurri telefono-zenbakiak"</string>
- <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Gailuaren telefono-zenbakiak atzitzea baimentzen dio aplikazioari."</string>
+ <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Gailuaren telefono-zenbakiak atzitzea baimentzen die aplikazioei."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"eragotzi tableta inaktibo ezartzea"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"eragotzi telebista inaktibo geratzea"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"eragotzi telefonoa inaktibo ezartzea"</string>
@@ -1733,19 +1733,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Aldatu testu modura ordua zehazteko."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Aldatu erloju modura ordua zehazteko."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Betetze automatikoaren aukerak"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Ezin dira bete automatikoki eremuak"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> zerbitzuan gorde?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="LABEL">%2$s</xliff:g> zerbitzuan gorde nahi duzu <xliff:g id="TYPE">%1$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g> eta <xliff:g id="TYPE_1">%2$s</xliff:g> gorde nahi dituzu <xliff:g id="LABEL">%3$s</xliff:g> behar denean erabiltzeko?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> eta <xliff:g id="TYPE_2">%3$s</xliff:g> gorde nahi dituzu <xliff:g id="LABEL">%4$s</xliff:g> behar denean erabiltzeko?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Gorde"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Ez, eskerrik asko"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"pasahitza"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"helbidea"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditu-txartela"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"erabiltzaile-izena"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"helbide elektronikoa"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Ez larritu eta bilatu babesleku bat inguruan."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Ebakuatu kostaldeak eta ibaialdeak berehala eta joan toki seguru batera, adibidez, toki garai batera."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Ez larritu eta bilatu babesleku bat inguruan."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index edf9bf8..7312fa6 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"برای وارد کردن زمان، به حالت وارد کردن نوشتار تغییر وضعیت دهید."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"برای وارد کردن زمان، به حالت ساعت تغییر وضعیت دهید."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"گزینههای تکمیل خودکار"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"تکمیل خودکار محتوا ممکن نیست"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"در <xliff:g id="LABEL">%1$s</xliff:g> ذخیره شود؟"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> در <xliff:g id="LABEL">%2$s</xliff:g> ذخیره شود؟"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g> در <xliff:g id="LABEL">%3$s</xliff:g> ذخیره شود؟"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g>، <xliff:g id="TYPE_2">%3$s</xliff:g> در <xliff:g id="LABEL">%4$s</xliff:g> ذخیره شود؟"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"ذخیره"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"نه سپاسگزارم"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"گذرواژه"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"نشانی"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"کارت اعتباری"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"نام کاربری"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"نشانی رایانامه"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"آرام باشید و پناهگاهی در این اطراف پیدا کنید."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"فوراً مناطق ساحلی و محدوده رودخانه را ترک کنید و به جایی امن، مثل ارتفاعات بروید."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"آرام باشید و پناهگاهی در این اطراف پیدا کنید."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index af73c15..5d12753 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Vaihda ajan syöttämiseen tekstitilassa."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Vaihda ajan syöttämiseen kellotilassa."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Automaattisen täytön asetukset"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Sisältöä ei voi täyttää automaattisesti."</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Tallennetaanko kohteeseen <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Tallennetaanko <xliff:g id="TYPE">%1$s</xliff:g> kohteeseen <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Tallennetaanko <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> palveluun <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Tallennetaanko <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g> palveluun <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Tallenna"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Ei kiitos"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"salasana"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"osoite"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"luottokortti"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"käyttäjänimi"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"sähköpostiosoite"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Pysy rauhallisena ja hakeudu lähimpään suojapaikkaan."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Siirry heti rannikkoalueilta ja jokien varsilta korkeampiin tai muuten turvallisempiin paikkoihin."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Pysy rauhallisena ja hakeudu lähimpään suojapaikkaan."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 1e25181..6bcc8ae 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Passer au mode Entrée de texte pour entrer l\'heure."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Passer au mode Horloge pour entrer l\'heure."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Options de remplissage automatique"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Le contenu ne peut pas être entré automatiquement"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Enregistrer sous <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Enregistrer <xliff:g id="TYPE">%1$s</xliff:g> sous <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> sous <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> sous <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Enregistrer"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Non, merci"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"mot de passe"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adresse"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"carte de crédit"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"nom d\'utilisateur"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"adresse de courriel"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Restez calme et cherchez un abri à proximité."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Évacuez immédiatement les zones côtières et les rives des fleuves, et réfugiez-vous dans un endroit plus sécuritaire, comme un terrain surélevé."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Restez calme et cherchez un abri à proximité."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 25bd58a1f..fdea62a 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Passer en mode saisie de texte pour la saisie de l\'heure."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Passer en mode horloge pour la saisie de l\'heure."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Options de saisie automatique"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Le contenu ne peut pas être saisi automatiquement"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Enregistrer dans \"<xliff:g id="LABEL">%1$s</xliff:g>\" ?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Enregistrer \"<xliff:g id="TYPE">%1$s</xliff:g>\" dans \"<xliff:g id="LABEL">%2$s</xliff:g>\" ?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> sur <xliff:g id="LABEL">%3$s</xliff:g> ?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> sur <xliff:g id="LABEL">%4$s</xliff:g> ?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Enregistrer"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Non, merci"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"mot de passe"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adresse"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"carte de paiement"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"nom d\'utilisateur"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"adresse e-mail"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Restez calme et cherchez un abri à proximité."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Évacuez immédiatement les zones côtières et les berges des fleuves, et réfugiez-vous dans un endroit plus sûr, comme un terrain surélevé."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Restez calme et cherchez un abri à proximité."</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index a726854..eb220f4 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1186,7 +1186,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Mostrando <xliff:g id="NAME">%s</xliff:g> sobre outras aplicacións"</string>
- <string name="alert_windows_notification_title" msgid="3697657294867638947">"Sobre aplicacións móstrase: <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> móstrase sobre outras aplicacións"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Se non queres que <xliff:g id="NAME">%s</xliff:g> utilice esta función, toca para abrir a configuración e desactívaa."</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESACTIVAR"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparando a <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1733,19 +1733,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Cambia ao modo de entrada de texto para introducir a hora."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Cambiar ao modo de reloxo para introducir a hora."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opcións de autocompletar"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Os contidos non se poden autocompletar"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Queres gardar o contido en: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Queres gardar o contido (<xliff:g id="TYPE">%1$s</xliff:g>) en: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Queres gardar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> en: <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Queres gardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> en: <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Gardar"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Non, grazas"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"contrasinal"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"enderezo"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"tarxeta de crédito"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"nome de usuario"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"enderezo de correo electrónico"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Mantén a calma e busca refuxio cerca."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Abandona de inmediato rexións costeiras e situadas na beira de ríos para dirixirte a un lugar máis seguro, como un terreo elevado."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Mantén a calma e busca refuxio cerca."</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index f3e52e1..82481d5 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -406,10 +406,8 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"એપ્લિકેશનને ફોન સુવિધાઓને ઍક્સેસ કરવાની મંજૂરી આપે છે. આ પરવાનગી એપ્લિકેશનને ફોન નંબર અને ઉપકરણ ID, કૉલ સક્રિય છે અને કોઈ કૉલ દ્વારા કનેક્ટ થયેલ રિમોટ નંબર નિર્ધારિત કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"સિસ્ટમ મારફતે કૉલ બીજે વાળો"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"કૉલિંગ અનુભવ સુધારવા માટે ઍપ્લિકેશનને સિસ્ટમ મારફતે કૉલ બીજે વાળવાની મંજૂરી આપે છે."</string>
- <!-- no translation found for permlab_readPhoneNumbers (6108163940932852440) -->
- <skip />
- <!-- no translation found for permdesc_readPhoneNumbers (8559488833662272354) -->
- <skip />
+ <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"ફોન નંબર વાંચો"</string>
+ <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"ઍપ્લિકેશનને ઉપકરણનાં ફોન નંબરને ઍક્સેસ કરવાની મંજૂરી આપે છે."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ટેબ્લેટને નિષ્ક્રિય થતું અટકાવો"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"ટીવીને નિષ્ક્રિય થતો અટકાવો"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ફોનને નિષ્ક્રિય થતો અટકાવો"</string>
@@ -1188,8 +1186,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> અન્ય ઍપ્લિકેશનોની ઉપર પ્રદર્શિત થઈ રહ્યું છે"</string>
- <!-- no translation found for alert_windows_notification_title (3697657294867638947) -->
- <skip />
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> અન્ય ઍપ્લિકેશનો પર દેખાઈ છે"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"જો તમે નથી ઇચ્છતા કે <xliff:g id="NAME">%s</xliff:g> આ સુવિધાનો ઉપયોગ કરે, તો સેટિંગ્સ ખોલવા માટે ટૅપ કરો અને તેને બંધ કરો."</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"બંધ કરો"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> ને તૈયાર કરી રહ્યું છે"</string>
@@ -1736,19 +1733,20 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"સમય દાખલ કરવા માટે ટેક્સ્ટ ઇનપુટ મોડમાં સ્વિચ કરો."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"સમય દાખલ કરવા માટે ઘડિયાળ મોડમાં સ્વિચ કરો."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"સ્વતઃભરણના વિકલ્પો"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"કન્ટેન્ટ સ્વતઃ ભરી શકાતું નથી"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> માં સાચવીએ?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> ને <xliff:g id="LABEL">%2$s</xliff:g> માં સાચવીએ?"</string>
+ <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
+ <skip />
<string name="autofill_save_yes" msgid="6398026094049005921">"સાચવો"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"નહીં આભાર"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"પાસવર્ડ"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"સરનામું"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ક્રેડિટ કાર્ડ"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"વપરાશકર્તાનામ"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"ઇમેઇલ સરનામું"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"શાંત રહો અને નજીકમાં આશ્રય લો."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"દરિયાકિનારાના પ્રદેશો તથા નદીકાંઠાના વિસ્તારો ખાલી કરીને તાત્કાલિક સુરક્ષિત ઊંચા સ્થાન પર જાઓ."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"શાંત રહો અને નજીકમાં આશ્રય લો."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 0e94ce3..5e7edfa 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"समय इनपुट के लिए लेख इनपुट मोड पर जाएं."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"समय इनपुट के लिए घड़ी मोड पर जाएं."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"ऑटोमैटिक भरने के विकल्प"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"सामग्रियां ऑटोमैटिक रूप से भरी जा सकती हैं"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> में सहेजें?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> को <xliff:g id="LABEL">%2$s</xliff:g> में सहेजें?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> को <xliff:g id="LABEL">%3$s</xliff:g> में सहेजें?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> को <xliff:g id="LABEL">%4$s</xliff:g> में सहेजें?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"सहेजें"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"नहीं, धन्यवाद"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"पासवर्ड"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"पता"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"क्रेडिट कार्ड"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"उपयोगकर्ता नाम"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"ईमेल पता"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"शांत रहें और आस-पास शरण स्थल खोजें."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"तटीय क्षेत्रों और नदी के किनारे वाले क्षेत्रों को जल्द से जल्द खाली करके किसी सुरक्षित ऊंची जगह पर चले जाएं."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"शांत रहें और आस-पास आश्रय खोजें."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 7ed7794..d95f8c8 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1763,19 +1763,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Prijeđite na način unosa teksta da biste unijeli vrijeme."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Prijeđite na način rada sata da biste unijeli vrijeme."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opcije automatskog popunjavanja"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Sadržaj se ne može automatski popuniti"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Želi te li to spremiti u aplikaciju <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Želite li spremiti <xliff:g id="TYPE">%1$s</xliff:g> u aplikaciju <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Želite li spremiti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> u <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Želite li spremiti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> u <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Spremi"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"zaporku"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adresu"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditnu karticu"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"korisničko ime"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"e-adresa"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Ostanite mirni i potražite sklonište u blizini."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Odmah se evakuirajte s obalnih područja i područja uz rijeku na sigurnije mjesto, primjerice povišeno područje."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Ostanite mirni i potražite sklonište u blizini."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 8ca82d3..9e5c53e 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Időbevitelhez váltson szövegbeviteli módba."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Időbevitelhez váltson óramódba."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Az automatikus kitöltés beállítási lehetőségei"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"A tartalmakat nem lehet automatikusan kitölteni"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Menti ide: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> mentése ide: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Menti a(z) <xliff:g id="LABEL">%3$s</xliff:g> szolgáltatásba a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g> és <xliff:g id="TYPE_1">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Menti a(z) <xliff:g id="LABEL">%4$s</xliff:g> szolgáltatásba a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> és <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Mentés"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Nem, köszönöm"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"jelszó"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"cím"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"hitelkártya"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"felhasználónév"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"e-mail-cím"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Őrizze meg nyugalmát, és keressen menedéket a közelben."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Azonnal meneküljön biztonságosabb helyre a tengerparti, illetve folyóparti területekről, például valamilyen magaslatra."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Őrizze meg nyugalmát, és keressen menedéket a közelben."</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index b97bb1b..d6a75d5 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Ժամը մուտքագրելու համար միացրեք տեքստի մուտքագրման ռեժիմը:"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Ժամը մուտքագրելու համար միացրեք ժամացույցի ռեժիմը:"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Ինքնալրացման ընտրանքները"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Բովանդակության ինքնալրացումը հնարավոր չէ"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Պահե՞լ <xliff:g id="LABEL">%1$s</xliff:g>-ում։"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Պահե՞լ <xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g>-ում։"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Պահե՞լ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> տվյալները <xliff:g id="LABEL">%3$s</xliff:g>-ում։"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Պահե՞լ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> տվյալները <xliff:g id="LABEL">%4$s</xliff:g>-ում։"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Պահել"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Ոչ"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"գաղտնաբառ"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"հասցե"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"վարկային քարտ"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"օգտանուն"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"էլփոստի հասցե"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Պահպանեք հանգստությունը և մոտակայքում ապաստարան փնտրեք:"</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Ափամերձ և գետափնյա տարածքներից անմիջապես էվակուացվեք դեպի ավելի ապահով վայրեր (օրինակ՝ բարձրադիր գոտիներ):"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Պահպանեք հանգստությունը և մոտակայքում ապաստարան փնտրեք:"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 62c1703..cd4e63e 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Beralih ke mode masukan teks untuk masukan waktu."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Beralih ke mode jam untuk masukan waktu."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opsi Isiotomatis"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Konten tidak dapat diisi otomatis"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Simpan ke <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Simpan <xliff:g id="TYPE">%1$s</xliff:g> ke <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ke <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ke <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Simpan"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Lain kali"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"sandi"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"alamat"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kartu kredit"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"nama pengguna"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"alamat email"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Tetap tenang dan cari tempat berlindung terdekat."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evakuasi segera dari daerah pesisir dan area tepi sungai ke tempat yang lebih aman seperti dataran tinggi."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Tetap tenang dan cari tempat berlindung terdekat."</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index b5acbec..d87725e 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1733,19 +1733,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Skipta yfir í textastillingu til að færa inn tíma."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Skipta yfir í klukkustillingu til að færa inn tíma."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Valkostir sjálfvirkrar útfyllingar"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Ekki er hægt að fylla innihald út sjálfkrafa"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Vista í <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Vista <xliff:g id="TYPE">%1$s</xliff:g> í <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Vista <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> á <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Vista <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> á <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Vista"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Nei, takk"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"aðgangsorð"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"heimilisfang"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditkort"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"notandanafn"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"netfang"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Sýndu stillingu og leitaðu skjóls."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Fólk sem statt er á strandsvæðum eða við ár á tafarlaust að leita öryggis á svæðum sem eru í meiri hæð yfir sjávarmáli."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Sýndu stillingu og leitaðu skjóls."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index ffd363c..06850c8 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1185,7 +1185,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"App <xliff:g id="NAME">%s</xliff:g> visualizzata sopra altre app"</string>
- <string name="alert_windows_notification_title" msgid="3697657294867638947">"App <xliff:g id="NAME">%s</xliff:g> visualiz. sopra altre app"</string>
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"App <xliff:g id="NAME">%s</xliff:g> mostrata sopra altre app"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Se non desideri che l\'app <xliff:g id="NAME">%s</xliff:g> utilizzi questa funzione, tocca per aprire le impostazioni e disattivarla."</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DISATTIVA"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparazione della <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Passa alla modalità di immissione testo per inserire l\'ora."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Passa alla modalità orologio per inserire l\'ora."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opzioni di compilazione automatica"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Impossibile compilare automaticamente i contenuti"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Salvare in <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Salvare <xliff:g id="TYPE">%1$s</xliff:g> in <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Salvare <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> su <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Salvare <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> su <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Salva"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"No, grazie"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"indirizzo"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"carta di credito"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"nome utente"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"indirizzo email"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Mantieni la calma e cerca riparo nelle vicinanze."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evacuare immediatamente le zone costiere e in riva ai fiumi e recarsi in un luogo più sicuro, ad esempio un\'altura."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Mantieni la calma e cerca riparo nelle vicinanze."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index de88b08..846ce56 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -412,10 +412,8 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"מאפשר לאפליקציה לגשת לתכונות הטלפון של המכשיר. אישור זה מתיר לאפליקציה לגלות את מספר הטלפון ואת זיהויי המכשיר, האם שיחה פעילה ואת המספר המרוחק המחובר באמצעות שיחה."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"ניתוב שיחות דרך המערכת"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"מאפשרת לאפליקציה לנתב את השיחות דרך המערכת כדי לשפר את חוויית השיחה."</string>
- <!-- no translation found for permlab_readPhoneNumbers (6108163940932852440) -->
- <skip />
- <!-- no translation found for permdesc_readPhoneNumbers (8559488833662272354) -->
- <skip />
+ <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"גישה למספרי הטלפון"</string>
+ <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"מתירה לאפליקציה גישה למספרי הטלפון במכשיר."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"מנע מהטאבלט לעבור למצב שינה"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"מניעת מעבר למצב שינה בטלוויזיה"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"מניעת מעבר הטלפון למצב שינה"</string>
@@ -1227,8 +1225,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"תצוגה של <xliff:g id="NAME">%s</xliff:g> מעל אפליקציות אחרות"</string>
- <!-- no translation found for alert_windows_notification_title (3697657294867638947) -->
- <skip />
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> מוצגת מעל אפליקציות אחרות"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"אם אינך רוצה ש-<xliff:g id="NAME">%s</xliff:g> תשתמש בתכונה הזו, הקש כדי לפתוח את ההגדרות ולכבות אותה."</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"כבה"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"הכנת <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1797,19 +1794,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"העבר למצב קלט טקסט לצורך הזנת השעה"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"העבר למצב שעון לצורך הזנת השעה"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"אפשרויות מילוי אוטומטי"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"לא ניתן למלא את התוכן באופן אוטומטי"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"לשמור ב-<xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"לשמור <xliff:g id="TYPE">%1$s</xliff:g> ב-<xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"לשמור את <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ב-<xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"לשמור את <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ב-<xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"שמור"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"לא, תודה"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"סיסמה"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"כתובת"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"כרטיס אשראי"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"שם משתמש"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"כתובת אימייל"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"הישאר רגוע וחפש מחסה בקרבת מקום."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"יש להתפנות מיידית מאזורים הסמוכים לחופים ולנהרות למקום בטוח יותר, כגון שטח גבוה יותר."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"הישאר רגוע וחפש מחסה בקרבת מקום."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index a600652..f627b22 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"時刻をテキストで入力するモードに切り替えます。"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"時刻を時計で入力するモードに切り替えます。"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"自動入力のオプション"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"コンテンツを自動入力できません"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> に保存しますか?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>を <xliff:g id="LABEL">%2$s</xliff:g> に保存しますか?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>を <xliff:g id="LABEL">%3$s</xliff:g> に保存しますか?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>、<xliff:g id="TYPE_2">%3$s</xliff:g>を <xliff:g id="LABEL">%4$s</xliff:g> に保存しますか?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"はい"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"いいえ"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"パスワード"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"住所"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"クレジット カード"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"ユーザー名"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"メールアドレス"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"強い揺れに備えてください"</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"沿岸部の方はただちに高台へ避難してください"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"強い揺れと津波に注意してください"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index b9d496b..6157f6b 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"დროის შეყვანისთვის ტექსტის შეყვანის რეჟიმზე გადართვა."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"დროის შეყვანისთვის საათის რეჟიმზე გადართვა."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"ავტომატური შევსების ვარიანტები"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"კონტენტის ავტომატური შევსება ვერ მოხერხდება"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"გსურთ „<xliff:g id="LABEL">%1$s</xliff:g>“-ში შენახვა?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"გსურთ, შეინახოთ <xliff:g id="TYPE">%1$s</xliff:g> „<xliff:g id="LABEL">%2$s</xliff:g>“-ში?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"გსურთ, <xliff:g id="LABEL">%3$s</xliff:g>-ში შეინახოთ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"გსურთ, <xliff:g id="LABEL">%4$s</xliff:g>-ში შეინახოთ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"შენახვა"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"არა, გმადლობთ"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"პაროლი"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"მისამართი"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"საკრედიტო ბარათი"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"მომხმარებლის სახელი"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"ელფოსტის მისამართი"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"შეინარჩუნეთ სიმშვიდე და იპოვეთ ახლომდებარე თავშესაფარი."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"დაუყოვნებლივ გადაინაცვლეთ სანაპირო რეგიონებიდან და მდინარისპირა ტერიტორიებიდან უსაფრთხო ადგილზე (მაგალითად, შემაღლებულ ადგილზე)."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"შეინარჩუნეთ სიმშვიდე და იპოვეთ ახლომდებარე თავშესაფარი."</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 01088aa..bf7fdf6 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1733,19 +1733,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Уақытты енгізу үшін мәтін енгізу режиміне өтіңіз."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Уақытты енгізу үшін сағат режиміне өтіңіз."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Автотолтыру опциялары"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Мазмұндар автотолтырылмайды"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> жүйесінде сақталсын ба?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> деректері <xliff:g id="LABEL">%2$s</xliff:g> жүйесінде сақталсын ба?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> <xliff:g id="LABEL">%3$s</xliff:g> ішіне сақтау керек пе?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> <xliff:g id="LABEL">%4$s</xliff:g> ішіне сақтау керек пе?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Сақтау"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Жоқ, рақмет"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"құпия сөз"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"мекенжай"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"несие картасы"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"пайдаланушы аты"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"электрондық пошта мекенжайы"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Сабыр сақтап, жақын жерден баспана іздеңіз."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Жағалау аймақтан биіктеу қауіпсіз жерге дереу көшіңіз."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Сабыр сақтап, жақын жерден баспана іздеңіз."</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 5e56ed0..7e97f95 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1734,19 +1734,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ប្តូរទៅមុខងារបញ្ចូលអក្សរសម្រាប់ការបញ្ចូលម៉ោង។"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ប្តូរទៅមុខងារនាឡិកាសម្រាប់ការបញ្ចូលម៉ោង។"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"ជម្រើសបំពេញដោយស្វ័យប្រវត្តិ"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"មិនអាចបំពេញមាតិកាដោយស្វ័យប្រវត្តិបានទេ"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"រក្សាទុកទៅក្នុង <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"រក្សាទុក <xliff:g id="TYPE">%1$s</xliff:g> ទៅក្នុង <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"រក្សាទុក <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ទៅក្នុង <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"រក្សាទុក <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ទៅក្នុង <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"រក្សាទុក"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"ទេ អរគុណ"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"ពាក្យសម្ងាត់"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"អាសយដ្ឋាន"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"បណ្ណឥណទាន"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"ឈ្មោះអ្នកប្រើប្រាស់"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"អាសយដ្ឋានអ៊ីមែល"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"សូមរក្សាភាពស្ងប់ស្ងាត់ ហើយស្វែងរកជម្រកសុវត្ថិភាពដែលនៅជិត។"</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"ភៀសខ្លួនជាបន្ទាន់ពីតំបន់ឆ្នេរ និងតំបន់តាមមាត់ទន្លេទៅកាន់កន្លែងដែលមានសុវត្ថិភាពជាងនេះ ដូចជាទីទួលណាមួយ។"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"សូមរក្សាភាពស្ងប់ស្ងាត់ ហើយស្វែងរកជម្រកសុវត្ថិភាពដែលនៅជិត។"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 27b629a..94f4df8 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1733,19 +1733,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ಸಮಯವನ್ನು ನಮೂದಿಸಲು ಪಠ್ಯದ ನಮೂನೆಗೆ ಬದಲಿಸಿ."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ಸಮಯವನ್ನು ನಮೂದಿಸಲು ಗಡಿಯಾರದ ನಮೂನೆಗೆ ಬದಲಿಸಿ."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"ಸ್ವಯಂತುಂಬುವಿಕೆ ಆಯ್ಕೆಗಳು"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"ವಿಷಯಗಳು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಭರ್ತಿಯಾಗಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> ನಲ್ಲಿ ಉಳಿಸಬೇಕೆ?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> ಅನ್ನು <xliff:g id="LABEL">%2$s</xliff:g> ನಲ್ಲಿ ಉಳಿಸಬೇಕೆ?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ಅನ್ನು <xliff:g id="LABEL">%3$s</xliff:g>ಗೆ ಉಳಿಸಬೇಕೆ?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ಅನ್ನು <xliff:g id="LABEL">%4$s</xliff:g> ಗೆ ಉಳಿಸಬೇಕೆ?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"ಉಳಿಸಿ"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"ಬೇಡ"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"ಪಾಸ್ವರ್ಡ್"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"ವಿಳಾಸ"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ಕ್ರೆಡಿಟ್ ಕಾರ್ಡ್"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"ಬಳಕೆದಾರರ ಹೆಸರು"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"ಇಮೇಲ್ ವಿಳಾಸ"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"ಶಾಂತರಾಗಿರಿ ಮತ್ತು ಸಮೀಪದಲ್ಲೆಲ್ಲಾದರೂ ಆಶ್ರಯ ಪಡೆದುಕೊಳ್ಳಿ."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"ಕರಾವಳಿ ಪ್ರದೇಶಗಳು ಮತ್ತು ನದಿ ತೀರಗಳಿಂದ ತಕ್ಷಣವೇ ಎತ್ತರದ ಪ್ರದೇಶಗಳಂತಹ ಸುರಕ್ಷಿತ ಸ್ಥಳಕ್ಕೆ ಹೋಗಿ."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"ಶಾಂತರಾಗಿರಿ ಮತ್ತು ಸಮೀಪದಲ್ಲೆಲ್ಲಾದರೂ ಆಶ್ರಯ ಪಡೆದುಕೊಳ್ಳಿ."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 24e4676..a24eb06 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"시간 입력을 위해 텍스트 입력 모드로 전환합니다."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"시간 입력을 위해 시계 모드로 전환합니다."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"자동완성 옵션"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"콘텐츠를 자동완성할 수 없습니다."</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g>에 저장하시겠습니까?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>을(를) <xliff:g id="LABEL">%2$s</xliff:g>에 저장하시겠습니까?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="LABEL">%3$s</xliff:g>에 <xliff:g id="TYPE_0">%1$s</xliff:g> 및 <xliff:g id="TYPE_1">%2$s</xliff:g>을(를) 저장하시겠습니까?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="LABEL">%4$s</xliff:g>에 <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> 및 <xliff:g id="TYPE_2">%3$s</xliff:g>을(를) 저장하시겠습니까?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"저장"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"사용 안함"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"비밀번호"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"주소"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"신용카드"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"사용자 이름"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"이메일 주소"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"침착하게 가까운 대피소를 찾으세요."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"즉시 해안 지대나 강가에서 떨어져 고지대 등 안전한 장소로 대피하세요."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"침착하게 가까운 대피소를 찾으세요."</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 7e417f1..f4d15aa 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1186,7 +1186,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> колдонмосун башка терезелердин үстүнөн көрсөтүү"</string>
- <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> колд. башк-дын үст. көрсөт-дө"</string>
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>: башка колдонмолордун үстүнөн"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Эгер <xliff:g id="NAME">%s</xliff:g> колдонмосу бул функцияны пайдаланбасын десеңиз, жөндөөлөрдү ачып туруп, аны өчүрүп коюңуз."</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ӨЧҮРҮҮ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> даярдалууда"</string>
@@ -1733,19 +1733,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Убакытты текст киргизүү режиминде киргизиңиз."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Убакытты дубал саатынын режиминде киргизиңиз."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Автотолтуруу опциялары"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Мазмундарды автотолтуруу мүмкүн эмес"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> кызматында сакталсынбы?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g> кызматында сакталсынбы?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g> менен <xliff:g id="TYPE_1">%2$s</xliff:g> <xliff:g id="LABEL">%3$s</xliff:g> кызматында сакталсынбы?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> жана <xliff:g id="TYPE_2">%3$s</xliff:g> <xliff:g id="LABEL">%4$s</xliff:g> кызматында сакталсынбы?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Сактоо"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Жок, рахмат"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"сырсөз"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"дарек"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"насыя картасы"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"колдонуучунун аты"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"электрондук почта дареги"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Эс алып, жакын жерден калканч издеңиз."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Деңиз жана дарыя жээгинде жайгашкан аймактардан бийик тоо сыяктуу коопсуз жерге тезинен чыгып кетиңиз."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Эс алып, жакын жерден калканч издеңиз."</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 0603d1c..e57c851 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ສະຫຼັບໄປໃຊ້ໂໝດປ້ອນຂໍ້ຄວາມສຳລັບການປ້ອນເວລາ."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ສະຫຼັບໄປໃຊ້ໂໝດໂມງສຳລັບການປ້ອນເວລາ."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"ຕົວເລືອກການຕື່ມຂໍ້ມູນອັດຕະໂນມັດ"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"ບໍ່ສາມາດຕື່ມຂໍ້ມູນເນື້ອຫາອັດຕະໂນມັດໄດ້"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"ບັນທຶກໄປໃສ່ <xliff:g id="LABEL">%1$s</xliff:g> ບໍ?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"ບັນທຶກ <xliff:g id="TYPE">%1$s</xliff:g> ໄປໃສ່ <xliff:g id="LABEL">%2$s</xliff:g> ບໍ?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"ບັນທຶກ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ໄປໃສ່ <xliff:g id="LABEL">%3$s</xliff:g> ບໍ?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"ບັນທຶກ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ໄປໃສ່ <xliff:g id="LABEL">%4$s</xliff:g> ບໍ?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"ບັນທຶກ"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"ບໍ່, ຂອບໃຈ"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"ລະຫັດຜ່ານ"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"ທີ່ຢູ່"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ບັດເຄຣດິດ"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"ຊື່ຜູ້ໃຊ້"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"ທີ່ຢູ່ອີເມລ"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"ໃຈເຢັນໆ ແລະ ຊອກຫາບ່ອນພັກຢູ່ໃກ້ໆ."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"ອົບພະຍົບອອກຈາກເຂດຊາຍຝັ່ງທະເລ ແລະ ບໍລິເວນແມ່ນ້ຳໄປບ່ອນທີ່ປອດໄພກວ່າ ເຊັ່ນ: ບ່ອນສູງ ໂດຍທັນທີ."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"ໃຈເຢັນໆ ແລະ ຊອກຫາບ່ອນພັກຢູ່ໃກ້ໆ."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 2345bdf..e98c66c 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1794,19 +1794,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Laiko įvestį pateikti perjungus į teksto įvesties režimą."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Laiko įvestį pateikti perjungus į laikrodžio režimą."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Automatinio pildymo parinktys"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Turinio negalima pildyti automatiškai"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Išsaugoti skiltyje „<xliff:g id="LABEL">%1$s</xliff:g>“?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Išsaugoti <xliff:g id="TYPE">%1$s</xliff:g> skiltyje „<xliff:g id="LABEL">%2$s</xliff:g>“?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Išsaugoti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> sistemoje „<xliff:g id="LABEL">%3$s</xliff:g>“?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Išsaugoti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> sistemoje „<xliff:g id="LABEL">%4$s</xliff:g>“?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Išsaugoti"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Ne, ačiū"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"slaptažodį"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adresą"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredito kortelę"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"naudotojo vardas"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"el. pašto adresas"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Nesijaudinkite ir ieškokite prieglobsčio netoliese."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Nedelsdami pasitraukite nuo pakrančių ir paupių. Eikite į saugią vietą, pvz., vietą, kuri yra aukštai."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Nesijaudinkite ir ieškokite prieglobsčio netoliese."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 9e8a34e..4251a52 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1763,19 +1763,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Lai ievadītu laiku, ieslēdziet teksta ievades režīmu."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Lai ievadītu laiku, ieslēdziet pulksteņa režīmu."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Automātiskās aizpildes opcijas"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Saturu nevar automātiski aizpildīt."</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Vai saglabāt pakalpojumā <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Vai saglabāt <xliff:g id="TYPE">%1$s</xliff:g> pakalpojumā <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Vai saglabāt informāciju (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>) iezīmē <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Vai saglabāt informāciju (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>) iezīmē <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Saglabāt"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Nē, paldies"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"paroli"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adresi"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredītkartes informāciju"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"lietotājvārds"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"e-pasta adrese"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Saglabājiet mieru un meklējiet tuvumā patvērumu."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Nekavējoties pametiet piekrastes un upju zonas un dodieties uz drošākām (piemēram, augstākām) vietām."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Saglabājiet mieru un meklējiet tuvumā patvērumu."</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index b073652..2fb9553 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1735,19 +1735,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Префрлете се на режимот за внесување текст за да внесете време."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Префрлете се на режимот за часовник за да внесете време."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Опции за автоматско пополнување"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Содржините не може автоматски да се пополнат"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Да се зачува во <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Да се зачува <xliff:g id="TYPE">%1$s</xliff:g> во <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Да се зачуваат <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> во <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Да се зачуваат <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> во <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Зачувај"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Не, благодарам"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"лозинка"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"адреса"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"кредитна картичка"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"корисничко име"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"адреса на е-пошта"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Бидете смирени и побарајте засолниште во близина."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Итна евакуација од крајбрежните региони и областите покрај реки на побезбедно место, како на пр., терени на повисока надморска височина."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Бидете смирени и побарајте засолниште во близина."</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 84aa13c..8f80f1ad 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1733,19 +1733,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"സമയം നൽകുന്നതിന് ടെക്സ്റ്റ് ഇൻപുട്ട് മോഡിലേക്ക് മാറുക."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"സമയം നൽകുന്നതിന് ക്ലോക്ക് മോഡിലേക്ക് മാറുക."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"സ്വയമേവ പൂരിപ്പിക്കൽ ഓപ്ഷനുകൾ"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"ഉള്ളടക്കങ്ങൾ സ്വയമേവ പൂരിപ്പിക്കാൻ കഴിയില്ല"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> എന്നതിലേക്ക് സംരക്ഷിക്കണോ?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g> എന്നതിലേക്ക് സംരക്ഷിക്കണോ?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> എന്നിവ <xliff:g id="LABEL">%3$s</xliff:g> എന്നതിൽ സംരക്ഷിക്കട്ടെ?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> എന്നിവ <xliff:g id="LABEL">%4$s</xliff:g> എന്നതിൽ സംരക്ഷിക്കട്ടെ?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"സംരക്ഷിക്കുക"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"വേണ്ട, നന്ദി"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"പാസ്വേഡ്"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"വിലാസം"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ക്രെഡിറ്റ് കാർഡ്"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"ഉപയോക്തൃനാമം"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"വിലാസം നൽകുക"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"പരിഭ്രമിക്കാതിരിക്കുക, അടുത്തുള്ള അഭയകേന്ദ്രം തേടുക."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"തീരപ്രദേശങ്ങളിൽ നിന്നും നദിക്കരകളിൽ നിന്നും ആളുകളെ ഉടനടി ഒഴിപ്പിച്ച് ഉയർന്ന ഭൂമിയിൽ എത്തിക്കുക."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"പരിഭ്രമിക്കാതിരിക്കുക, അടുത്തുള്ള അഭയകേന്ദ്രം തേടുക."</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 4cd99a3..88aacda 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1730,19 +1730,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Цагийг оруулахын тулд текст оруулах горимд шилжүүлнэ үү."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Цагийг оруулахын тулд цагийн горимд шилжүүлнэ үү."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Автоматаар бөглөх хэсгийн сонголт"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Агуулгыг автоматаар бөглөх боломжгүй"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g>-д хадгалах уу?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>-г <xliff:g id="LABEL">%2$s</xliff:g>-д хадгалах уу?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>-г <xliff:g id="LABEL">%3$s</xliff:g>-д хадгалах уу?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>-г <xliff:g id="LABEL">%4$s</xliff:g>-д хадгалах уу?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Хадгалах"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Үгүй, баярлалаа"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"нууц үг"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"хаяг"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"кредит карт"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"хэрэглэгчийн нэр"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"имэйл хаяг"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Тайван байж, ойролцоох нуугдах газар хайна уу."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Эргийн бүс, голын эргийн бүсээс өндөрлөг газар зэрэг аюулгүй газар руу нэн даруй шилжинэ үү."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Тайван байж, ойролцоох нуугдах газар хайна уу."</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 2f77ffc..4769676 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -406,10 +406,8 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"डिव्हाइसच्या फोन वैशिष्ट्यांवर प्रवेश करण्यास अॅप ला अनुमती देते. ही परवानगी कॉल सक्रिय असला किंवा नसला तरीही, फोन नंबर आणि डिव्हाइस आयडी आणि कॉलद्वारे कनेक्ट केलेला रीमोट नंबर निर्धारित करण्यासाठी अॅप ला अनुमती देते."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"प्रणालीच्या माध्यमातून कॉल रूट करा"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"कॉल करण्याचा अनुभव सुधारण्यासाठी अॅपला त्याचे कॉल प्रणालीच्या माध्यमातून रूट करू देते."</string>
- <!-- no translation found for permlab_readPhoneNumbers (6108163940932852440) -->
- <skip />
- <!-- no translation found for permdesc_readPhoneNumbers (8559488833662272354) -->
- <skip />
+ <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"फोन नंबर वाचा"</string>
+ <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"अॅपला डिव्हाइसच्या फोन नंबरमध्ये प्रवेश करण्याची अनुमती देते."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"टॅबलेट निष्क्रिय होण्यापासून प्रतिबंधित करा"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"निष्क्रिय होण्यापासून प्रतिबंध करा"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"फोन निष्क्रिय होण्यापासून प्रतिबंधित करा"</string>
@@ -1188,8 +1186,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> इतर अॅप्सवर प्रदर्शित करीत आहे"</string>
- <!-- no translation found for alert_windows_notification_title (3697657294867638947) -->
- <skip />
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> अन्य अॅप्सवर प्रदर्शित करीत आहे"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ने हे वैशिष्ट्य वापरू नये असे आपण इच्छित असल्यास, सेटिंग्ज उघडण्यासाठी टॅप करा आणि ते बंद करा."</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"बंद करा"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> तयार करीत आहे"</string>
@@ -1736,19 +1733,20 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"वेळ इनपुटसाठी मजकूर इनपुट मोडवर स्विच करा."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"वेळ इनपुटसाठी घड्याळ मोडवर स्विच करा."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"स्वयं-भरण पर्याय"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"सामग्रींची स्वयं-भरणा करता येणार नाही"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> वर जतन करायचे?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="LABEL">%2$s</xliff:g> वर <xliff:g id="TYPE">%1$s</xliff:g> जतन करायचे?"</string>
+ <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
+ <skip />
+ <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
+ <skip />
<string name="autofill_save_yes" msgid="6398026094049005921">"जतन करा"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"नाही धन्यवाद"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"संकेतशब्द"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"पत्ता"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"क्रेडिट कार्ड"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"वापरकर्तानाव"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"ईमेल पत्ता"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"शांत रहा आणि जवळपास निवारा शोधा."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"किनारपट्टीचे प्रदेश आणि नदीकाठची क्षेत्रे त्वरित रिकामी करून उंच मैदानासारख्या अधिक सुरक्षित ठिकाणी जा."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"शांत रहा आणि जवळपास निवारा शोधा."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 9211121..e414985 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Beralih ke mod input teks untuk input masa."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Beralih ke mod jam untuk input masa."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Pilihan autolengkap"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Kandungan tidak boleh dilengkapkan secara automatik"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Simpan ke <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Simpan <xliff:g id="TYPE">%1$s</xliff:g> ke <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ke <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ke <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Simpan"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Tidak, terima kasih"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"kata laluan"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"alamat"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kad kredit"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"nama pengguna"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"alamat e-mel"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Bertenang dan cari perlindungan di kawasan yang berdekatan."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Segera beredar dari kawasan pinggir laut dan tepi sungai dan berpindah ke tempat yang lebih selamat seperti kawasan tinggi."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Bertenang dan cari perlindungan di kawasan yang berdekatan."</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index e8e0da3..5252422 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1186,7 +1186,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> သည် အခြားအက်ပ်များအပေါ်တွင် ပြပါသည်"</string>
- <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ကအခြားအက်ပ်ပေါ်တွင် ပြသနေသည်။"</string>
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ကို အခြားအက်ပ်များပေါ်တွင် မြင်နေရပါသည်။"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ကို ဤဝန်ဆောင်မှုအား အသုံးမပြုစေလိုလျှင် ဆက်တင်ကို တို့၍ ဖွင့်ပြီး ၎င်းကို ပိတ်လိုက်ပါ။"</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ပိတ်ပါ"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> ပြင်ဆင်နေသည်"</string>
@@ -1733,19 +1733,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"အချိန်ထည့်သွင်းရန် စာသားထည့်သွင်းမှုမုဒ်သို့ ပြောင်းပါ။"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"အချိန်ထည့်သွင်းမှုအတွက် နာရီမုဒ်သို့ ပြောင်းပါ။"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"အော်တိုဖြည့် ရွေးချယ်စရာများ"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"အကြောင်းအရာများကို အော်တိုဖြည့်၍မရပါ"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> သို့ သိမ်းဆည်းလိုပါသလား။"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> ကို <xliff:g id="LABEL">%2$s</xliff:g> သို့ သိမ်းဆည်းလိုပါသလား။"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>၊ <xliff:g id="TYPE_1">%2$s</xliff:g> ကို <xliff:g id="LABEL">%3$s</xliff:g> သို့ သိမ်းဆည်းလိုပါသလား။"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>၊ <xliff:g id="TYPE_1">%2$s</xliff:g>၊ <xliff:g id="TYPE_2">%3$s</xliff:g> ကို <xliff:g id="LABEL">%4$s</xliff:g>သို့ သိမ်းဆည်းလိုပါသလား။"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"သိမ်းရန်"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"မလိုပါ"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"စကားဝှက်"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"လိပ်စာ"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ခရက်တစ်ကတ်"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"အသုံးပြုသူအမည်"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"အီးမေးလ်လိပ်စာ"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"စိတ်ငြိမ်ငြိမ်ထားပြီး အနီးအနားတဝိုက်တွင် ခိုနားစရာ နေရာရှာပါ။"</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"ကမ်းရိုးတန်းနှင့် မြစ်ကမ်းရိုးတစ်လျှောက်ရှိ နေရာဒေသတို့မှ ချက်ချင်းထွက်ခွာပြီး ဘေးကင်းရာကုန်းမြင့်ဒေသသို့ ပြောင်းရွှေ့ပါ။"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"စိတ်ငြိမ်ငြိမ်ထားပြီး အနီးအနားတဝိုက်တွင် ခိုနားစရာ နေရာရှာပါ။"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 4db1c7e..9c638ec 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -406,10 +406,8 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Lar appen bruke enhetens telefonfunksjoner. Med denne tillatelsen kan appen finne telefonnummer og enhets-ID-er, registrere om en samtale pågår, og se det eksterne nummeret det opprettes en forbindelse med via oppringing."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"send anrop gjennom systemet"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Lar appen sende anrop gjennom systemet for å forbedre anropsopplevelsen."</string>
- <!-- no translation found for permlab_readPhoneNumbers (6108163940932852440) -->
- <skip />
- <!-- no translation found for permdesc_readPhoneNumbers (8559488833662272354) -->
- <skip />
+ <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"les telefonnumre"</string>
+ <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Gir appen tilgang til telefonnumrene til enheten."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"hindre nettbrettet fra å gå over til sovemodus"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"hindre TV-en i å gå i hvilemodus"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"forhindre telefonen fra å sove"</string>
@@ -1187,8 +1185,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> vises over andre apper"</string>
- <!-- no translation found for alert_windows_notification_title (3697657294867638947) -->
- <skip />
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> vises over andre apper"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"Hvis du ikke vil at <xliff:g id="NAME">%s</xliff:g> skal bruke denne funksjonen, kan du trykke for å åpne innstillingene og slå den av."</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"SLÅ AV"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Forbereder <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1735,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Bytt til tekstinndatamodus for tidsinndata."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Bytt til klokkemodus for tidsinndata."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Alternativer for autofyll"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Innhold kan ikke fylles ut automatisk"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Vil du lagre i <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Vil du lagre <xliff:g id="TYPE">%1$s</xliff:g> i <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Vil du lagre <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> til <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Vil du lagre <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> til <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Lagre"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Nei takk"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"passord"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adresse"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredittkort"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"brukernavn"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"e-postadresse"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Hold deg rolig og søk ly i nærheten."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evakuer umiddelbart fra kyst- og elveområder til et tryggere sted, for eksempel høyt terreng."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Hold deg rolig og søk ly i nærheten."</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index fe910ae..86c18d6 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -406,10 +406,8 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"उपकरणको फोन विशेषताहरूको पहुँच गर्न अनुप्रयोगलाई अनुमति दिन्छ। यस अनुमतिले फोन नम्बर र उपकरणको IDs, कल सक्षम छ कि छैन र कलद्वारा जोडिएको टाढाको नम्बर निर्धारण गर्न अनुमति दिन्छ।"</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"प्रणाली मार्फत कल गर्न दिनुहोस्"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"कल गर्दाको अनुभवलाई सुधार्न यस अनुप्रयोगलाई प्रणाली मार्फत कलहरू गर्न अनुमति दिन्छ।"</string>
- <!-- no translation found for permlab_readPhoneNumbers (6108163940932852440) -->
- <skip />
- <!-- no translation found for permdesc_readPhoneNumbers (8559488833662272354) -->
- <skip />
+ <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"फोन नम्बरहरू पढ्ने"</string>
+ <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"उक्त अनुप्रयोगलाई यस यन्त्रको फोन नम्बरहरूमाथि पहुँच राख्न दिनुहोस्।"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ट्याब्लेटलाई निन्द्रामा जानबाट रोक्नुहोस्"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"TV निभ्नबाट जोगाउनुहोस्"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"फोनलाई निदाउनबाट रोक्नुहोस्"</string>
@@ -1193,8 +1191,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> अन्य अनुप्रयोगहरूमा देखिँदैछ"</string>
- <!-- no translation found for alert_windows_notification_title (3697657294867638947) -->
- <skip />
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> अन्य अनुप्रयोगहरूमा देखिँदैछ"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"तपाईं <xliff:g id="NAME">%s</xliff:g> ले यो विशेषता प्रयोग नगरेको चाहनुहुन्न भने सेटिङहरू खोली यसलाई निष्क्रिय पार्न ट्याप गर्नुहोस्।"</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"निष्क्रिय पार्नुहोस्"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"तयारी गर्दै <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1741,19 +1738,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"समय इनपुट गर्न पाठ इनपुट मोडमा स्विच गर्नुहोस्।"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"समय इनपुट गर्न घडी मोडमा स्विच गर्नुहोस्।"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"स्वतः भरणका विकल्पहरू"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"सामग्रीहरूलाई स्वत: भरण गर्न मिल्दैन"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> मा सुरक्षित गर्ने हो?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> लाई <xliff:g id="LABEL">%2$s</xliff:g> मा सुरक्षित गर्ने हो?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> लाई <xliff:g id="LABEL">%3$s</xliff:g> मा सुरक्षित गर्ने हो?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> लाई <xliff:g id="LABEL">%4$s</xliff:g> मा सुरक्षित गर्ने हो?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"सुरक्षित गर्नुहोस्"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"पर्दैन, धन्यवाद"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"पासवर्ड"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"ठेगाना"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"क्रेडिट कार्ड"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"प्रयोगकर्ताको नाम"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"इमेल ठेगाना"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"शान्त रहनुहोस् र नजिकै आश्रयस्थल खोज्नुहोस्।"</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"तटीय क्षेत्र र नदीछेउका ठाउँहरू छाडी उच्च सतहमा अवस्थित कुनै अझ सुरक्षित ठाउँमा जानुहोस्।"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"शान्त रहनुहोस् र नजिकै आश्रयस्थल खोज्नुहोस्।"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 1bfc77a..af8c0a2 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Schakel naar de tekstinvoermodus om de tijd in te voeren."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Schakel naar de klokmodus om de tijd in te voeren."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opties voor automatisch aanvullen"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Content kan niet automatisch worden aangevuld"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Opslaan in <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> opslaan in <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> opslaan in <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g> opslaan in <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Opslaan"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Nee, bedankt"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"Wachtwoord"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"Adres"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"Creditcard"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"gebruikersnaam"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"e-mailadres"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Blijf kalm en zoek onderdak in de buurt."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Verlaat kustgebieden en rivieroevers onmiddellijk en zoek een hoger gelegen gebied op."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Blijf kalm en zoek onderdak in de buurt."</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 3fe7fb0..71fd285 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -91,12 +91,12 @@
<string name="CLIRPermanent" msgid="3377371145926835671">"ਤੁਸੀਂ ਕਾਲਰ ID ਸੈਟਿੰਗ ਨਹੀਂ ਬਦਲ ਸਕਦੇ।"</string>
<string name="RestrictedOnDataTitle" msgid="1322504692764166532">"ਕੋਈ ਡੈਟਾ ਸੇਵਾ ਨਹੀਂ"</string>
<string name="RestrictedOnEmergencyTitle" msgid="1236071219598685236">"ਕੋਈ ਸੰਕਟਕਾਲੀਨ ਸੇਵਾ ਨਹੀਂ"</string>
- <string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"ਕੋਈ ਅਵਾਜ਼ੀ ਸੇਵਾ ਨਹੀਂ"</string>
- <string name="RestrictedOnAllVoiceTitle" msgid="158800171499150681">"ਕੋਈ ਅਵਾਜ਼ੀ/ਸੰਕਟਕਾਲੀਨ ਸੇਵਾ ਨਹੀਂ"</string>
+ <string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"ਕੋਈ ਆਵਾਜ਼ੀ ਸੇਵਾ ਨਹੀਂ"</string>
+ <string name="RestrictedOnAllVoiceTitle" msgid="158800171499150681">"ਕੋਈ ਆਵਾਜ਼ੀ/ਸੰਕਟਕਾਲੀਨ ਸੇਵਾ ਨਹੀਂ"</string>
<string name="RestrictedOnDataContent" msgid="8997474569390996587">"ਤੁਹਾਡੇ ਕੈਰੀਅਰ ਵੱਲੋਂ ਇਸ ਟਿਕਾਣੇ \'ਤੇ ਡੈਟਾ ਸੇਵਾ ਨੂੰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਮੁਅੱਤਲ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
<string name="RestrictedOnEmergencyContent" msgid="4573217945494650061">"ਤੁਹਾਡੇ ਕੈਰੀਅਰ ਵੱਲੋਂ ਇਸ ਟਿਕਾਣੇ \'ਤੇ ਸੰਕਟਕਾਲੀਨ ਕਾਲਾਂ ਨੂੰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਮੁਅੱਤਲ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
- <string name="RestrictedOnNormalContent" msgid="1579434198284512182">"ਤੁਹਾਡੇ ਕੈਰੀਅਰ ਵੱਲੋਂ ਇਸ ਟਿਕਾਣੇ \'ਤੇ ਅਵਾਜ਼ੀ ਕਾਲਾਂ ਨੂੰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਮੁਅੱਤਲ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
- <string name="RestrictedOnAllVoiceContent" msgid="5243580774142557047">"ਤੁਹਾਡੇ ਕੈਰੀਅਰ ਵੱਲੋਂ ਇਸ ਟਿਕਾਣੇ \'ਤੇ ਅਵਾਜ਼ੀ ਅਤੇ ਸੰਕਟਕਾਲੀਨ ਕਾਲਾਂ ਨੂੰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਮੁਅੱਤਲ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
+ <string name="RestrictedOnNormalContent" msgid="1579434198284512182">"ਤੁਹਾਡੇ ਕੈਰੀਅਰ ਵੱਲੋਂ ਇਸ ਟਿਕਾਣੇ \'ਤੇ ਆਵਾਜ਼ੀ ਕਾਲਾਂ ਨੂੰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਮੁਅੱਤਲ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
+ <string name="RestrictedOnAllVoiceContent" msgid="5243580774142557047">"ਤੁਹਾਡੇ ਕੈਰੀਅਰ ਵੱਲੋਂ ਇਸ ਟਿਕਾਣੇ \'ਤੇ ਆਵਾਜ਼ੀ ਅਤੇ ਸੰਕਟਕਾਲੀਨ ਕਾਲਾਂ ਨੂੰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਮੁਅੱਤਲ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
<string name="NetworkPreferenceSwitchTitle" msgid="4008877505368566980">"ਨੈੱਟਵਰਕ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"</string>
<string name="NetworkPreferenceSwitchSummary" msgid="4164230263214915351">"ਸਿਗਨਲ ਪ੍ਰਾਪਤੀ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਲਈ, ਸਿਸਟਮ > ਨੈੱਟਵਰਕ ਅਤੇ ਇੰਟਰਨੈੱਟ > ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ > ਤਰਜੀਹੀ ਨੈੱਟਵਰਕ ਦੀ ਕਿਸਮ \'ਤੇ ਚੁਣੀ ਗਈ ਕਿਸਮ ਨੂੰ ਬਦਲਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"ਪੀਅਰ ਨੇ TTY Mode FULL ਦੀ ਬੇਨਤੀ ਕੀਤੀ"</string>
@@ -179,8 +179,8 @@
<string name="ssl_ca_cert_noti_by_administrator" msgid="3541729986326153557">"ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ"</string>
<string name="ssl_ca_cert_noti_managed" msgid="4030263497686867141">"<xliff:g id="MANAGING_DOMAIN">%s</xliff:g> ਮੁਤਾਬਕ"</string>
<string name="work_profile_deleted" msgid="5005572078641980632">"ਕੰਮ ਪ੍ਰੋਫਾਈਲ ਮਿਟਾਈ ਗਈ"</string>
- <string name="work_profile_deleted_description" msgid="1100529432509639864">"ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਗੁੰਮ ਹੋਣ ਕਾਰਨ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਮਿਟਾਇਆ ਗਿਆ"</string>
- <string name="work_profile_deleted_details" msgid="6307630639269092360">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਜਾਂ ਤਾਂ ਗੁੰਮ ਹੈ ਜਾਂ ਖਰਾਬ ਹੈ। ਨਤੀਜੇ ਵਜੋਂ, ਤੁਹਾਡਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਸਬੰਧਿਤ ਡੈਟਾ ਮਿਟਾਇਆ ਗਿਆ ਹੈ। ਸਹਾਇਤਾ ਲਈ ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
+ <string name="work_profile_deleted_description" msgid="1100529432509639864">"ਗੁੰਮਸ਼ੁਦਾ ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਦੇ ਕਾਰਨ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਮਿਟਾਇਆ ਗਿਆ"</string>
+ <string name="work_profile_deleted_details" msgid="6307630639269092360">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਜਾਂ ਤਾਂ ਗੁੰਮਸ਼ੁਦਾ ਹੈ ਜਾਂ ਖਰਾਬ ਹੈ। ਨਤੀਜੇ ਵਜੋਂ, ਤੁਹਾਡਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਸਬੰਧਿਤ ਡੈਟਾ ਮਿਟਾਇਆ ਗਿਆ ਹੈ। ਸਹਾਇਤਾ ਲਈ ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
<string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"ਤੁਹਾਡਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹੁਣ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
<string name="network_logging_notification_title" msgid="6399790108123704477">"ਡੀਵਾਈਸ ਪ੍ਰਬੰਧਨ ਅਧੀਨ ਹੈ"</string>
<string name="network_logging_notification_text" msgid="7930089249949354026">"ਤੁਹਾਡਾ ਸੰਗਠਨ ਇਸ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਦਾ ਹੈ ਅਤੇ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦਾ ਹੈ। ਵੇਰਵਿਆਂ ਲਈ ਟੈਪ ਕਰੋ।"</string>
@@ -1466,7 +1466,7 @@
<string name="leave_accessibility_shortcut_on" msgid="7653111894438512680">"ਸ਼ਾਰਟਕੱਟ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
<string name="accessibility_shortcut_enabling_service" msgid="7771852911861522636">"ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਨੇ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਚਾਲੂ ਕੀਤਾ"</string>
<string name="accessibility_shortcut_disabling_service" msgid="2747243438223109821">"ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਨੇ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਬੰਦ ਕੀਤਾ"</string>
- <string name="accessibility_button_prompt_text" msgid="4234556536456854251">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ \'ਤੇ ਟੈਪ ਕੀਤੇ ਜਾਣ \'ਤੇ ਵਰਤਣ ਲਈ ਕੋਈ ਵਿਸ਼ੇਸ਼ਤਾ ਚੁਣੋ:"</string>
+ <string name="accessibility_button_prompt_text" msgid="4234556536456854251">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ ਨੂੰ ਟੈਪ ਕੀਤੇ ਜਾਣ \'ਤੇ ਵਰਤਣ ਲਈ ਕੋਈ ਵਿਸ਼ੇਸ਼ਤਾ ਚੁਣੋ:"</string>
<string name="accessibility_button_instructional_text" msgid="6942300463612999993">"ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਬਦਲਣ ਲਈ, ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ ਨੂੰ ਸਪੱਰਸ਼ ਕਰੋ ਅਤੇ ਦਬਾਈ ਰੱਖੋ।"</string>
<string name="accessibility_magnification_chooser_text" msgid="1227146738764986237">"ਵੱਡਦਰਸ਼ੀਕਰਨ"</string>
<string name="user_switched" msgid="3768006783166984410">"ਮੌਜੂਦਾ ਉਪਭੋਗਤਾ <xliff:g id="NAME">%1$s</xliff:g>।"</string>
@@ -1733,26 +1733,25 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ਸਮਾਂ ਇਨਪੁੱਟ ਕਰਨ ਲਈ ਲਿਖਤ ਇਨਪੁੱਟ ਮੋਡ \'ਤੇ ਬਦਲੀ ਕਰੋ।"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ਸਮਾਂ ਇਨਪੁੱਟ ਕਰਨ ਲਈ ਘੜੀ ਮੋਡ \'ਤੇ ਬਦਲੀ ਕਰੋ।"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"ਆਟੋਫਿਲ ਵਿਕਲਪ"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"ਸਮੱਗਰੀਆਂ ਆਟੋਫਿਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੀਏ?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> ਨੂੰ <xliff:g id="LABEL">%2$s</xliff:g> ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੀਏ?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ਨੂੰ <xliff:g id="LABEL">%3$s</xliff:g> ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੀਏ?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ਨੂੰ <xliff:g id="LABEL">%4$s</xliff:g> ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੀਏ?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"ਰੱਖਿਅਤ ਕਰੋ"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"ਪਾਸਵਰਡ"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"ਪਤਾ"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ਕ੍ਰੈਡਿਟ ਕਾਰਡ"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"ਵਰਤੋਂਕਾਰ ਨਾਮ"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"ਈਮੇਲ ਪਤਾ"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"ਸ਼ਾਂਤ ਰਹੋ ਅਤੇ ਆਸ-ਪਾਸ ਪਨਾਹ ਮੰਗੋ।"</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"ਤੁਰੰਤ ਤੱਟੀ ਖੇਤਰਾਂ ਅਤੇ ਨਦੀ ਦੇ ਕਿਨਾਰੇ ਵਾਲੇ ਖੇਤਰਾਂ ਨੂੰ ਖਾਲੀ ਕਰ ਕੇ ਕਿਸੇ ਸੁਰੱਖਿਅਤ ਸਥਾਨ \'ਤੇ ਚਲੇ ਜਾਓ ਜਿਵੇਂ ਕਿ ਉੱਚੀ ਜ਼ਮੀਨ।"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"ਸ਼ਾਂਤ ਰਹੋ ਅਤੇ ਆਸ-ਪਾਸ ਪਨਾਹ ਮੰਗੋ।"</string>
<string name="etws_primary_default_message_test" msgid="2709597093560037455">"ਸੰਕਟਕਾਲੀਨ ਸੰਦੇਸ਼ ਟੈਸਟ"</string>
<string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
<string name="mmcc_authentication_reject" msgid="7729819349669603406">"SIM ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
- <string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM ਅਨੁਕੂਲਿਤ ਨਹੀਂ ਹੈ"</string>
+ <string name="mmcc_imsi_unknown_in_hlr" msgid="6321202257374418726">"SIM ਦੀ ਵਿਵਸਥਾ ਨਹੀਂ ਹੈ"</string>
<string name="mmcc_illegal_ms" msgid="2769452751852211112">"SIM ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
<string name="mmcc_illegal_me" msgid="4438696681169345015">"ਫ਼ੋਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 5f61e89..dee76d5 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1794,19 +1794,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Aby wprowadzić czas, włącz tryb wprowadzania tekstu."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Aby wprowadzić czas, włącz tryb zegara."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opcje autouzupełniania"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Nie można automatycznie uzupełnić treści"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Zapisać w: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Zapisać element <xliff:g id="TYPE">%1$s</xliff:g> w: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Zapisać: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> w: <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Zapisać: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> w: <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Zapisz"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Nie, dziękuję"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"hasło"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adres"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"karta kredytowa"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"nazwa użytkownika"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"adres e-mail"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Zachowaj spokój i poszukaj schronienia w pobliżu."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Niezwłocznie ewakuuj się z regionów nabrzeżnych i położonych przy rzekach w bezpieczniejsze miejsce, np. na wzniesienie."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Zachowaj spokój i poszukaj schronienia w pobliżu."</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 9c059f9..2212c06 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Alterne para o modo de entrada de texto para informar o horário."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Alterne para o modo de relógio para informar o horário."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opções de preenchimento automático"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Não é possível preencher os conteúdos automaticamente"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Salvar em <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Salvar <xliff:g id="TYPE">%1$s</xliff:g> em <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> em <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Salvar"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Não, obrigado"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"senha"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"endereço"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"cartão de crédito"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"nome de usuário"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"endereço de e-mail"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Fique calmo e procure um abrigo por perto."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Saia imediatamente de regiões costeiras e áreas ribeirinhas e vá para um lugar mais seguro, como terrenos elevados."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Fique calmo e procure um abrigo por perto."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 8d89c17..241b2fe 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Mude para o modo de introdução de texto para a introdução da hora."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Mude para o modo de relógio para a introdução da hora."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opções de preenchimento automático"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Não é possível preencher automaticamente o conteúdo"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Pretende guardar no <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Pretende guardar o(a) <xliff:g id="TYPE">%1$s</xliff:g> no <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Pretende guardar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> no <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Pretende guardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> no <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Guardar"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Não, obrigado"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"palavra-passe"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"endereço"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"cartão de crédito"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"nome de utilizador"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"endereço de email"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Mantenha a calma e procure abrigo nas proximidades."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Abandone imediatamente regiões costeiras e zonas ribeirinhas em direção a um local mais seguro, como um terreno elevado."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Mantenha a calma e procure abrigo nas proximidades."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 9c059f9..2212c06 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Alterne para o modo de entrada de texto para informar o horário."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Alterne para o modo de relógio para informar o horário."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opções de preenchimento automático"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Não é possível preencher os conteúdos automaticamente"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Salvar em <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Salvar <xliff:g id="TYPE">%1$s</xliff:g> em <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> em <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Salvar"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Não, obrigado"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"senha"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"endereço"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"cartão de crédito"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"nome de usuário"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"endereço de e-mail"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Fique calmo e procure um abrigo por perto."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Saia imediatamente de regiões costeiras e áreas ribeirinhas e vá para um lugar mais seguro, como terrenos elevados."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Fique calmo e procure um abrigo por perto."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 007ac8c..f347a8e 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1763,19 +1763,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Pentru a introduce ora, comutați la modul de introducere a textului."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Pentru a introduce ora, comutați la modul ceas."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opțiuni de completare automată"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Conținutul nu poate fi completat automat"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Salvați în <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Salvați <xliff:g id="TYPE">%1$s</xliff:g> în <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Salvați <xliff:g id="TYPE_0">%1$s</xliff:g> și <xliff:g id="TYPE_1">%2$s</xliff:g> în <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Salvați <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> și <xliff:g id="TYPE_2">%3$s</xliff:g> în <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Salvați"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Nu, mulțumesc"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"parolă"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adresă"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"card de credit"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"nume de utilizator"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"adresă de e-mail"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Păstrați-vă calmul și căutați un adăpost în apropiere."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Părăsiți imediat zonele de coastă și din apropierea râurilor și îndreptați-vă spre un loc mai sigur, cum ar fi o zonă aflată la înălțime."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Păstrați-vă calmul și căutați un adăpost în apropiere."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index c64f929..3ac621a 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1794,19 +1794,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Чтобы ввести время, перейдите в режим ввода текста."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Чтобы ввести время, перейдите в режим часов."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Параметры автозаполнения"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Ошибка автозаполнения"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Сохранить в <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>: сохранить в <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Сохранить данные (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>) в \"<xliff:g id="LABEL">%3$s</xliff:g>\"?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Сохранить данные (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>) в \"<xliff:g id="LABEL">%4$s</xliff:g>\"?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Сохранить"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Нет, спасибо"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"Пароль"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"Адрес"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"Банковская карта"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"имя пользователя"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"адрес электронной почты"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Сохраняйте спокойствие и поищите укрытие поблизости."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Немедленно эвакуируйтесь из прибрежной зоны в более высокое место."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Сохраняйте спокойствие и поищите укрытие поблизости."</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 2a76c97..6c595fb 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -406,10 +406,8 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"උපාංගයේ දුරකථන විශේෂාංග වෙත ප්රවේශයට යෙදුමට ඉඩ දෙයි. ඇමතුම සක්රිය වුවත්, සහ ඇමතුමකින් දුරස්ථ අංකය සම්බන්ධ වුවත් දුරකථන අංකය සහ උපාංග ID හඳුනා ගැනීමට මෙම අවසරය යෙදුමට ඉඩ දෙයි."</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"පද්ධතිය හරහා ඇමතුම් මාර්ගගත කරන්න"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"ඇමතුම් අත්දැකීම වැඩිදියුණු කිරීම සඳහා යෙදුමට පද්ධතිය හරහා එහි ඇමතුම් මාර්ගගත කිරීමට ඉඩ දෙයි."</string>
- <!-- no translation found for permlab_readPhoneNumbers (6108163940932852440) -->
- <skip />
- <!-- no translation found for permdesc_readPhoneNumbers (8559488833662272354) -->
- <skip />
+ <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"දුරකථන අංක කියවන්න"</string>
+ <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"උපාංගයේ දුරකථන අංක වෙත ප්රවේශයට යෙදුමට ඉඩ දෙයි."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ටැබ්ලටය නින්දෙන් වැළක්වීම"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"රූපවාහිනිය නින්දට යාමෙන් නවත්වන්න"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"දුරකථනය නින්දට යාමෙන් වළකන්න"</string>
@@ -1189,8 +1187,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"අනෙක් යෙදුම්වලට උඩින් <xliff:g id="NAME">%s</xliff:g> සංදර්ශනය කරමින්"</string>
- <!-- no translation found for alert_windows_notification_title (3697657294867638947) -->
- <skip />
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"අනෙක් යෙදුම්වලට උඩින් <xliff:g id="NAME">%s</xliff:g> දිස් වේ"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"ඔබට <xliff:g id="NAME">%s</xliff:g> මෙම විශේෂාංගය භාවිත කිරීමට අවශ්ය නැති නම්, සැකසීම් විවෘත කිරීමට තට්ටු කර එය ක්රියාවිරහිත කරන්න."</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ක්රියා විරහිත කරන්න"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> සූදානම් කරමින්"</string>
@@ -1737,19 +1734,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"වේලා ආදානය සඳහා ආදාන ප්රකාරය වෙත මාරු වෙන්න."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"වේලා ආදානය සඳහා ඔරලෝසු ප්රකාරය වෙත මාරු වෙන්න."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"ස්වයංක්රිය පිරවුම් විකල්ප"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"අන්තර්ගතය ස්වයං පිරවුම් කළ නොහැකිය"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> වෙත සුරකින්නද?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g> වෙත සුරකින්නද?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="LABEL">%3$s</xliff:g> වෙත <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> සුරකින්නද?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="LABEL">%4$s</xliff:g> වෙත <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> සුරකින්නද?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"සුරකින්න"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"එපා ස්තූතියි"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"මුරපදය"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"ලිපිනය"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ණය කාඩ්පත"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"පරිශීලක නාමය"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"ඊ-තැපැල් ලිපිනය"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"සන්සුන්ව ඉන්න සහ අවට ඇති නවාතැන් පහසුකම් බලන්න."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"මුහුදු බඩ ප්රදේශ සහ ගංඉවුරු ප්රදේශ සිට ඉහළ ප්රදේශයක් වැනි ආරක්ෂිත තැනකට දැන්ම යන්න."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"සන්සුන්ව ඉන්න සහ අවට ඇති නවාතැන් පහසුකම් බලන්න."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index a1b3ad4..af5268e 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1794,19 +1794,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Ak chcete zadať čas, prepnite na textový režim vstupu"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Ak chcete zadať čas, prepnite na režim hodín."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Možnosti automatického dopĺňania"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Obsah nie je možné automaticky vyplniť"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Uložiť do zariadenia <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Uložiť <xliff:g id="TYPE">%1$s</xliff:g> do zariadenia <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Uložiť <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> do služby <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Uložiť <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g> do služby <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Uložiť"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Nie, vďaka"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"heslo"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adresa"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditná karta"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"používateľské meno"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"e-mailová adresa"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Zachovajte pokoj a vyhľadajte úkryt v okolí."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Okamžite začnite evakuáciu z prímorských a nábrežných oblastí na bezpečnejšie miesto, napríklad do vyššie položených regiónov."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Zachovajte pokoj a vyhľadajte úkryt v okolí."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index f003c0b..877add7 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1794,19 +1794,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Preklopite na način za vnašanje besedila, da vnesete čas."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Preklopite na način ure, da vnesete čas."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Možnosti samodejnega izpolnjevanja"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Vsebine ni mogoče samodejno izpolniti"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Shrani v <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Shrani <xliff:g id="TYPE">%1$s</xliff:g> v <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Želite shraniti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> v <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Želite shraniti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> v <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Shrani"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"geslo"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"naslov"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditno kartico"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"uporabniško ime"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"e-poštni naslov"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Ostanite mirni in poiščite zavetje v bližini."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Takoj se umaknite z obalnih območij in bregov rek na varnejše mesto, na primer na višje ležeča mesta."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Ostanite mirni in poiščite zavetje v bližini."</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 05feb1a..b645553 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1733,19 +1733,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Kalo te modaliteti i hyrjes së tekstit për hyrjen e kohës."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Kalo te modaliteti i orës për hyrjen e kohës."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opsionet e plotësimit automatik"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Përmbajtjet nuk mund të plotësohen automatikisht"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Të ruhet te <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Të ruhet <xliff:g id="TYPE">%1$s</xliff:g> te <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Të ruhen <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> te <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Të ruhen <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> te <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Ruaj"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Jo, faleminderit"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"fjalëkalimi"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adresa"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"karta e kreditit"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"emri i përdoruesit"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"adresa e mail-it"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Qëndro i qetë dhe kërko strehim në afërsi."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Evakuohu menjëherë nga rajonet bregdetare dhe zonat pranë lumenjve drejt një vendi më të sigurt, si për shembull në një terren të ngritur."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Qëndro i qetë dhe kërko strehim në afërsi."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 8c7ad93..6e13582 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1763,19 +1763,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Пређите у режим уноса текста ради уноса времена."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Пређите у режим сата ради уноса времена."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Опције аутоматског попуњавања"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Садржај не може аутоматски да се попуни"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Желите ли да сачувате у: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Желите ли да сачувате ставку <xliff:g id="TYPE">%1$s</xliff:g> у: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Желите ли да сачувате ставке <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> у <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Желите ли да сачувате ставке <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> у <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Сачувај"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Не, хвала"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"лозинка"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"адреса"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"кредитна картица"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"корисничко име"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"имејл адреса"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Останите мирни и потражите склониште у околини."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Одмах се склоните из приобалних региона и области поред река на неко безбедније место, на пример, на неко узвишење."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Останите мирни и потражите склониште у околини."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index cbb84af..90dfd681a 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -282,7 +282,7 @@
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"få åtkomst till sensordata om dina vitalparametrar"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Hämta fönsterinnehåll"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Granska innehållet i ett fönster som du interagerar med."</string>
- <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Aktivera Explore by Touch"</string>
+ <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Aktivera Explore by touch"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Objekt som användaren trycker på läses upp högt och skärmen kan utforskas med hjälp av rörelser."</string>
<string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Aktivera förbättrad webbtillgänglighet"</string>
<string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"Skript kan installeras för att göra appens innehåll tillgängligare."</string>
@@ -853,9 +853,9 @@
<string name="searchview_description_clear" msgid="1330281990951833033">"Ta bort frågan"</string>
<string name="searchview_description_submit" msgid="2688450133297983542">"Skicka fråga"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"Röstsökning"</string>
- <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"Aktivera Explore by Touch?"</string>
- <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vill aktivera Explore by Touch. När funktionen är aktiv kan du höra eller se beskrivningar av vad du har under fingret eller utföra gester för att göra saker med surfplattan."</string>
- <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vill aktivera Explore by Touch. När funktionen är aktiv kan du höra eller se beskrivningar av vad du har under fingret eller utföra gester för att göra saker med telefonen."</string>
+ <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"Aktivera Explore by touch?"</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vill aktivera Explore by touch. När funktionen är aktiv kan du höra eller se beskrivningar av vad du har under fingret eller utföra gester för att göra saker med surfplattan."</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vill aktivera Explore by touch. När funktionen är aktiv kan du höra eller se beskrivningar av vad du har under fingret eller utföra gester för att göra saker med telefonen."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"för 1 månad sedan"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"För mer än en månad sedan"</string>
<plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Byt till textinmatningsläget och ange tid."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Byt till klockläget och ange tid."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Alternativ för autofyll"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Det gick inte att fylla i innehållet automatiskt"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Vill du spara detta i <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Vill du spara <xliff:g id="TYPE">%1$s</xliff:g> i <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Spara <xliff:g id="TYPE_0">%1$s</xliff:g> och <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Spara <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> och <xliff:g id="TYPE_2">%3$s</xliff:g> i <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Spara"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Nej tack"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"lösenordet"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adressen"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kreditkortet"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"användarnamn"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"e-postadress"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Håll dig lugn och sök skydd i närheten."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Utrym kust- och flodområden omedelbart och förflytta er till en säkrare plats, till exempel ett högt beläget område."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Håll dig lugn och sök skydd i närheten."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 7cd8c3a..664a038 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1730,19 +1730,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Badilisha iwe katika hali ya maandishi wakati wa kuweka muda."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Badilisha umbo liwe la saa ya mishale wakati wa kuweka muda."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Chaguo za kujaza otomatiki"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Maudhui hayawezi kujazwa kiotomatiki"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Ungependa kuhifadhi kwenye <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Ungependa kuhifadhi <xliff:g id="TYPE">%1$s</xliff:g> kwenye <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Ungependa kuhifadhi <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> kwenye <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Ungependa kuhifadhi <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> kwenye <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Hifadhi"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Hapana, asante"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"nenosiri"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"anwani"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kadi ya mikopo"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"jina la mtumiaji"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"anwani ya barua pepe"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Tulia na utafute hifadhi ya karibu."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Ondoka mara moja kwenye maeneo ya ufuo na mito ili uende kwenye sehemu salama kama vile milimani."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Tulia na utafute hifadhi ya karibu."</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 16ced0a..1f81757 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1733,19 +1733,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"உரை உள்ளீட்டிற்காக, கடிகாரப் பயன்முறைக்கு மாற்றும்."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"நேர உள்ளீட்டிற்காக, கடிகாரப் பயன்முறைக்கு மாற்றும்."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"தன்னிரப்பி விருப்பங்கள்"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"உள்ளடக்கத்தைத் தானாக நிரப்ப முடியவில்லை"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> இல் சேமிக்கவா?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>ஐ <xliff:g id="LABEL">%2$s</xliff:g> இல் சேமிக்கவா?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ஆகியவற்றை <xliff:g id="LABEL">%3$s</xliff:g> இல் சேமிக்கவா?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ஆகியவற்றை <xliff:g id="LABEL">%4$s</xliff:g> இல் சேமிக்கவா?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"சேமி"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"வேண்டாம்"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"கடவுச்சொல்"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"முகவரி"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"கிரெடிட் கார்டு"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"பயனர்பெயர்"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"மின்னஞ்சல் முகவரி"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"பதட்டப்படாதீர்கள், அருகில் ஏதேனும் பாதுகாப்பான இடம் உள்ளதா எனப் பாருங்கள்."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"கடலோரப் பகுதிகளிலும் ஆற்றங்கரைகளிலும் வசிப்பவர்கள் உடனடியாகப் பாதுகாப்பான இடத்திற்குச் (மேட்டுப்பகுதி) செல்லவும்."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"பதட்டப்படாதீர்கள், அருகில் ஏதேனும் பாதுகாப்பான இடம் உள்ளதா எனப் பாருங்கள்."</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index c143d4f..0fb49d5 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1733,19 +1733,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"సమయాన్ని నమోదు చేయడం కోసం వచన నమోదు మోడ్కి మారండి."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"సమయాన్ని నమోదు చేయడం కోసం గడియారం మోడ్కు మారండి."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"స్వీయ పూరింపు ఎంపికలు"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"కంటెంట్లను స్వీయ పూరింపు చేయడం సాధ్యపడదు"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g>కు సేవ్ చేయాలా?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>ని <xliff:g id="LABEL">%2$s</xliff:g>కు సేవ్ చేయాలా?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>లను <xliff:g id="LABEL">%3$s</xliff:g>కు సేవ్ చేయాలా?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>లను <xliff:g id="LABEL">%4$s</xliff:g>కు సేవ్ చేయాలా?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"సేవ్ చేయి"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"వద్దు, ధన్యవాదాలు"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"పాస్వర్డ్"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"చిరునామా"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"క్రెడిట్ కార్డ్"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"వినియోగదారు పేరు"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"ఇమెయిల్ చిరునామా"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"ప్రశాంతంగా ఉండండి మరియు దగ్గర్లో తలదాచుకోండి."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"వెంటనే తీర ప్రాంతాలు మరియు నదీ పరీవాహక ప్రాంతాలను ఖాళీ చేసి మెట్ట ప్రాంతాలకు తరలి వెళ్లండి."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"ప్రశాంతంగా ఉండండి మరియు దగ్గర్లో తలదాచుకోండి."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index f308bcf..ed22eef 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"สลับไปโหมดป้อนข้อความเพื่อป้อนเวลา"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"สลับไปโหมดนาฬิกาเพื่อป้อนเวลา"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"ตัวเลือกในการป้อนอัตโนมัติ"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"ไม่สามารถป้อนเนื้อหาอัตโนมัติ"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"บันทึกไปยัง <xliff:g id="LABEL">%1$s</xliff:g> ใช่ไหม"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"บันทึก <xliff:g id="TYPE">%1$s</xliff:g> ไปยัง <xliff:g id="LABEL">%2$s</xliff:g> ใช่ไหม"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"บันทึก <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ไปยัง <xliff:g id="LABEL">%3$s</xliff:g> ไหม"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"บันทึก <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ไปยัง <xliff:g id="LABEL">%4$s</xliff:g> ไหม"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"บันทึก"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"ไม่เป็นไร"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"รหัสผ่าน"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"ที่อยู่"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"บัตรเครดิต"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"ชื่อผู้ใช้"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"ที่อยู่อีเมล"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"ทำใจให้สงบและหาที่กำบังในบริเวณใกล้เคียง"</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"อพยพออกจากจากเขตชายฝั่งทะเลและบริเวณริมแม่น้ำไปยังสถานที่ที่ปลอดภัยกว่า เช่น ที่สูง โดยทันที"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"ทำใจให้สงบและหาที่กำบังในบริเวณใกล้เคียง"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index fa02f8f..8b5962f 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Lumipat sa pamamaraan ng pag-input ng text para sa input na oras."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Lumipat sa mode ng orasan para sa input na oras."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Mga opsyon sa autofill"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Hindi maaaring ma-autofill ang mga content"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"I-save sa <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"I-save ang <xliff:g id="TYPE">%1$s</xliff:g> sa <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"I-save ang <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> sa <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"I-save ang <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> sa <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"I-save"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Hindi, salamat na lang"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"address"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"credit card"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"username"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"email address"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Manatiling kalmado at maghanap ng matutuluyan sa malapit."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Umalis kaagad sa mga baybayin at pampang, at pumunta sa isang mas ligtas na lokasyon tulad ng isang mataas na lugar."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Manatiling kalmado at maghanap ng matutuluyan sa malapit."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 4275e5c..7be1384 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Zaman girişi için metin girişi moduna geçin."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Zaman girişi için saat moduna geçin."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Otomatik doldurma seçenekleri"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"İçerikler otomatik doldurulamıyor"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> hizmetine kaydedilsin mi?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>, <xliff:g id="LABEL">%2$s</xliff:g> etkinliğine kaydedilsin mi?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g> ve <xliff:g id="TYPE_1">%2$s</xliff:g> bilgileri <xliff:g id="LABEL">%3$s</xliff:g> hizmetine kaydedilsin mi?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ve <xliff:g id="TYPE_2">%3$s</xliff:g> bilgileri <xliff:g id="LABEL">%4$s</xliff:g> hizmetine kaydedilsin mi?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Kaydet"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Hayır, teşekkürler"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"şifre"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"adres"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredi kartı"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"kullanıcı adı"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"e-posta adresi"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Sakin olun ve yakınlarda sığınabileceğiniz bir yer bulun."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Kıyı kesimlerini ve nehir kenarlarını hemen boşaltarak yüksek yerler gibi daha güvenli bölgelere gidin."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Sakin olun ve yakınlarda sığınabileceğiniz bir yer bulun."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 187904d..6c5846d 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1794,19 +1794,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Перейти в текстовий режим, щоб ввести час."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Перейти в режим годинника, щоб ввести час."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Параметри автозаповнення"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Вміст не можна заповнити автоматично"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Зберегти в службі <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Зберегти дані (<xliff:g id="TYPE">%1$s</xliff:g>) у службі <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Зберегти дані (<xliff:g id="TYPE_0">%1$s</xliff:g> і <xliff:g id="TYPE_1">%2$s</xliff:g>) у службі <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Зберегти дані (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> і <xliff:g id="TYPE_2">%3$s</xliff:g>) у службі <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Зберегти"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Ні, дякую"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"пароль"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"адреса"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"кредитна картка"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"ім’я користувача"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"електронна адреса"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Не хвилюйтеся та знайдіть прихисток поблизу."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Негайно евакуюйтеся з прибережних районів і територій поблизу річок у безпечніше місце, як-от на територію на підвищенні."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Не хвилюйтеся та знайдіть прихисток поблизу."</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index f87cf54..ccaa412 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -406,10 +406,8 @@
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"ایپ کو آلے کی فون والی خصوصیات تک رسائی حاصل کرنے کی اجازت دیتا ہے۔ یہ اجازت ایپ کو فون نمبر اور آلے کے IDs کا تعین کرنے، آیا کوئی کال فعال ہے، اور کال کے ذریعہ مربوط ریموٹ نمبر کا تعین کرنے دیتی ہے۔"</string>
<string name="permlab_manageOwnCalls" msgid="1503034913274622244">"سسٹم کے ذریعہ کالز روٹ کریں"</string>
<string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"کالںگ کا تجربہ بہتر بنانے کے لیے سسٹم کے ذریعہ ایپ کو کالز روٹ کرنے کی اجازت دیتا ہے۔"</string>
- <!-- no translation found for permlab_readPhoneNumbers (6108163940932852440) -->
- <skip />
- <!-- no translation found for permdesc_readPhoneNumbers (8559488833662272354) -->
- <skip />
+ <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"فون نمبرز پڑھیں"</string>
+ <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"ایپ کو آلہ کے فون نمبرز تک رسائی کرنے دیتا ہے۔"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ٹیبلیٹ کو سلیپ وضع میں جانے سے روکیں"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"TV کو سلیپ وضع میں جانے سے روکیں"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"فون کو سلیپ وضع میں جانے سے روکیں"</string>
@@ -1188,8 +1186,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> کو دیگر ایپس پر دکھایا کیا جا رہا ہے"</string>
- <!-- no translation found for alert_windows_notification_title (3697657294867638947) -->
- <skip />
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> دیگر ایپس پر ڈسپلے ہو رہی ہے"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"اگر آپ نہیں چاہتے ہیں کہ <xliff:g id="NAME">%s</xliff:g> اس خصوصیت کا استعمال کرے تو ترتیبات کھولنے کیلئے تھپتھپائیں اور اسے بند کریں۔"</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"آف کریں"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> تیار کیا جا رہا ہے"</string>
@@ -1736,19 +1733,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"وقت ان پٹ کے لیے ٹیکسٹ ان پٹ وضع پر سوئچ کریں۔"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"وقت ان پٹ کے لیے گھڑی وضع پر سوئچ کریں۔"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"آٹو فل کے اختیارات"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"موادوں کو آٹو فل نہیں کیا جا سکتا"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> میں محفوظ کریں؟"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> کو <xliff:g id="LABEL">%2$s</xliff:g> میں محفوظ کریں؟"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g> کو <xliff:g id="LABEL">%3$s</xliff:g> میں محفوظ کریں؟"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g>، <xliff:g id="TYPE_2">%3$s</xliff:g> کو <xliff:g id="LABEL">%4$s</xliff:g> میں محفوظ کریں؟"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"محفوظ کریں"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"نہیں، شکریہ"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"پاس ورڈ"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"پتہ"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"کریڈٹ کارڈ"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"صارف نام"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"ای میل پتہ"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"پُرسکون رہیں اور قریبی پناہ حاصل کریں۔"</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"ساحلی خطوں اور دریائی کناروں کے علاقوں کو فوری طور پر خالی کر کے اونچے ٹیلے جیسے کسی زیادہ محفوظ مقام پر چلے جائیں۔"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"پُرسکون رہیں اور قریبی پناہ حاصل کریں۔"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index f841f1c..ee2438f 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -796,7 +796,7 @@
<string name="factorytest_failed" msgid="5410270329114212041">"Ishlab chiqarish sinovi amalga oshmadi"</string>
<string name="factorytest_not_system" msgid="4435201656767276723">"The FACTORY_TEST amali faqatgina /system/app ichiga o‘rnatilgan paketlar bilan ishlay oladi."</string>
<string name="factorytest_no_action" msgid="872991874799998561">"FACTORY_TEST amalini bajarish uchun birorta ham paket topilmadi."</string>
- <string name="factorytest_reboot" msgid="6320168203050791643">"O‘chirib-yoqish"</string>
+ <string name="factorytest_reboot" msgid="6320168203050791643">"O‘chirib yoqish"</string>
<string name="js_dialog_title" msgid="1987483977834603872">"\"<xliff:g id="TITLE">%s</xliff:g>\"dagi sahifa buni xabar qilmoqda:"</string>
<string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
<string name="js_dialog_before_unload_title" msgid="2619376555525116593">"Tasdiqlash"</string>
@@ -1146,7 +1146,7 @@
<string name="sim_done_button" msgid="827949989369963775">"Tayyor"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM karta qo‘shildi"</string>
<string name="sim_added_message" msgid="6599945301141050216">"Uyali tarmoqqa ulanish uchun qurilmangizni o‘chirib-yoqing."</string>
- <string name="sim_restart_button" msgid="4722407842815232347">"O‘chirib-yoqish"</string>
+ <string name="sim_restart_button" msgid="4722407842815232347">"O‘chirib yoqish"</string>
<string name="carrier_app_dialog_message" msgid="7066156088266319533">"Yangi SIM karta to‘g‘ri ishlashi uchun operator ilovasini o‘rnatib, ochish kerak bo‘ladi."</string>
<string name="carrier_app_dialog_button" msgid="7900235513678617329">"ILOVANI YUKLAB OLING"</string>
<string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"HOZIR EMAS"</string>
@@ -1733,19 +1733,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Vaqtni kiritish uchun matn kiritish rejimiga o‘ting."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Vaqtni kiritish uchun soat rejimiga o‘ting."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Avtomatik to‘ldirish parametrlari"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Kontentlarni avtomatik to‘ldirib bo‘lmaydi"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> xizmatiga saqlansinmi?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g> xizmatiga saqlansinmi?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ma’lumotlari <xliff:g id="LABEL">%3$s</xliff:g> yorlig‘iga saqlansinmi?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ma’lumotlari <xliff:g id="LABEL">%4$s</xliff:g> yorlig‘iga saqlansinmi?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Saqlash"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Yo‘q, kerak emas"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"parol"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"manzil"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"kredit karta"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"foydalanuvchi nomi"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"e-pochta manzili"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Tinchlaning va yaqin-atrofdan boshpana qidiring."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Qirg‘oq va daryo bo‘ylaridan yuqori tepalik kabi xavfsiz joylarga darhol evakuatsiya qiling."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Tinchlaning va yaqin-atrofdan boshpana qidiring."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index ba72144..c85f413 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Chuyển sang chế độ nhập văn bản để nhập thời gian."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Chuyển sang chế độ đồng hồ để nhập thời gian."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Tùy chọn tự động điền"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Không thể tự động điền nội dung"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Lưu vào <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Lưu <xliff:g id="TYPE">%1$s</xliff:g> vào <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Lưu <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> vào <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Lưu <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> vào <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Lưu"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Không, cảm ơn"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"mật khẩu"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"địa chỉ"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"thẻ tín dụng"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"tên người dùng"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"địa chỉ email"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Hãy bình tĩnh và tìm kiếm nơi trú ẩn gần đó."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Ngay lập tức sơ tán khỏi các vùng ven biển và khu vực ven sông để tới một nơi an toàn hơn như vùng đất cao."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Hãy bình tĩnh và tìm kiếm nơi trú ẩn gần đó."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 8f110d1..1daecdd 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"切换到文字输入模式来输入时间。"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"切换到时钟模式来输入时间。"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"自动填充选项"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"无法自动填充内容"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"要保存到<xliff:g id="LABEL">%1$s</xliff:g>吗?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"要将<xliff:g id="TYPE">%1$s</xliff:g>保存到<xliff:g id="LABEL">%2$s</xliff:g>吗?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"要将<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>保存到<xliff:g id="LABEL">%3$s</xliff:g>吗?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"要将<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>、<xliff:g id="TYPE_2">%3$s</xliff:g>保存到<xliff:g id="LABEL">%4$s</xliff:g>吗?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"保存"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"不用了"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"密码"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"地址"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"信用卡"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"用户名"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"电子邮件地址"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"请保持冷静,并寻找附近的避难地点。"</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"请立即从沿海和河滨区域撤离到高地等较安全的地方。"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"请保持冷静,并寻找附近的避难地点。"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 556a5c7..902cfea 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1185,7 +1185,7 @@
<string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"「<xliff:g id="NAME">%s</xliff:g>」目前在其他應用程式上顯示內容"</string>
- <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>目前在其他應用程式上層顯示內容"</string>
+ <string name="alert_windows_notification_title" msgid="3697657294867638947">"「<xliff:g id="NAME">%s</xliff:g>」正在其他應用程式上顯示內容"</string>
<string name="alert_windows_notification_message" msgid="8917232109522912560">"如果您不想「<xliff:g id="NAME">%s</xliff:g>」使用此功能,請輕按以開啟設定,然後停用此功能。"</string>
<string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"關閉"</string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"正在準備<xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"切換至文字輸入模式即可輸入時間。"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"切換至時鐘模式即可輸入時間。"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"自動填入選項"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"無法自動填入內容"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"要儲存至 <xliff:g id="LABEL">%1$s</xliff:g> 嗎?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"要將<xliff:g id="TYPE">%1$s</xliff:g>儲存至 <xliff:g id="LABEL">%2$s</xliff:g> 嗎?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>儲存至「<xliff:g id="LABEL">%3$s</xliff:g>」嗎?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>儲存至「<xliff:g id="LABEL">%4$s</xliff:g>」嗎?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"儲存"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"不用了,謝謝"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"密碼"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"地址"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"信用卡"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"使用者名稱"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"電郵地址"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"請保持冷靜,並尋找附近的避難所。"</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"請立即從沿海和河岸地區撤離,前往高地等較安全的地點。"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"請保持冷靜,並尋找附近的避難所。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index c16d59a..91c5df3 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"切換至文字輸入模式來輸入時間。"</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"切換至時鐘模式來輸入時間。"</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"自動填入選項"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"無法自動填入內容"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"要儲存到「<xliff:g id="LABEL">%1$s</xliff:g>」嗎?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"要將<xliff:g id="TYPE">%1$s</xliff:g>儲存到「<xliff:g id="LABEL">%2$s</xliff:g>」嗎?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>儲存到「<xliff:g id="LABEL">%3$s</xliff:g>」嗎?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>、<xliff:g id="TYPE_2">%3$s</xliff:g>儲存到「<xliff:g id="LABEL">%4$s</xliff:g>」嗎?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"儲存"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"不用了,謝謝"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"密碼"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"地址"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"信用卡"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"使用者名稱"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"電子郵件地址"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"請保持冷靜並尋找附近的避難地點。"</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"請立即從沿海與河岸地區撤離,前往高地這類較安全的地點。"</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"請保持冷靜並尋找附近的避難地點。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index e05aebf..5289834 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1732,19 +1732,18 @@
<string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"Shintshela kumodi yokufaka umbhalo ngokufaka isikhathi."</string>
<string name="time_picker_radial_mode_description" msgid="4953403779779557198">"Shintshela kumodi yewashi ngokufakwa kwesikhathi."</string>
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Izinketho zokugcwalisa ngokuzenzakalela"</string>
- <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
- <skip />
+ <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Okuqukethwe akukwazi ukugcwalisa ngokuzenzakalela"</string>
<string name="autofill_save_title" msgid="7081244500504163245">"Londoloza ku-<xliff:g id="LABEL">%1$s</xliff:g>?"</string>
<string name="autofill_save_title_with_type" msgid="4977385733042555659">"Londoloza i-<xliff:g id="TYPE">%1$s</xliff:g> ku-<xliff:g id="LABEL">%2$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Londoloza i-<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ku-<xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+ <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Londoloza i-<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ku-<xliff:g id="LABEL">%4$s</xliff:g>?"</string>
<string name="autofill_save_yes" msgid="6398026094049005921">"Londoloza"</string>
<string name="autofill_save_no" msgid="2625132258725581787">"Cha ngiyabonga"</string>
<string name="autofill_save_type_password" msgid="5288448918465971568">"iphasiwedi"</string>
<string name="autofill_save_type_address" msgid="4936707762193009542">"ikheli"</string>
<string name="autofill_save_type_credit_card" msgid="7127694776265563071">"ikhadi lesikweletu"</string>
- <!-- no translation found for autofill_save_type_username (239040540379769562) -->
- <skip />
- <!-- no translation found for autofill_save_type_email_address (5752949432129262174) -->
- <skip />
+ <string name="autofill_save_type_username" msgid="239040540379769562">"igama lomsebenzisi"</string>
+ <string name="autofill_save_type_email_address" msgid="5752949432129262174">"ikheli le-imeyili"</string>
<string name="etws_primary_default_message_earthquake" msgid="5541962250262769193">"Hlala ubeke umoya phansi uphinde ufune ukukhuselwa eduze."</string>
<string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"Phuma ngokushesha kusukela kuzifunda ezingasolwandle nasezindaweni zemifula uye endaweni ephephile efana nendawo ephakeme."</string>
<string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"Hlala ubeke umoya phansi uphinde ufune ukukhuselwa eduze."</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 69c6fa4..67f6d19 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -430,10 +430,9 @@
<flag name="adjustNothing" value="0x30" />
</attr>
- <!-- Flag allowing you to disable the preview animation for a window.
- The default value is false; if set to true, the system can never
- use the window's theme to show a preview of it before your
- actual instance is shown to the user. -->
+ <!-- Flag allowing you to disable the splash screen for a window. The default value is
+ false; if set to true, the system can never use the window's theme to show a splash
+ screen before your actual instance is shown to the user. -->
<attr name="windowDisablePreview" format="boolean" />
<!-- Flag indicating that this window should not be displayed at all.
@@ -2049,6 +2048,17 @@
Corresponds to setting {@link android.view.View#SYSTEM_UI_FLAG_LIGHT_STATUS_BAR} on
the decor view. -->
<attr name="windowLightStatusBar" format="boolean" />
+
+ <!-- Reference to a drawable to be used as the splash screen content of the window. This
+ drawable will be placed on top of the {@link android.R.attr#windowBackground} with its
+ bounds inset by the system bars. If the drawable should not be inset by the system
+ bars, use a fullscreen theme.
+ <p>
+ Note that even if no splashscreen content is set on the theme, the system may still
+ show a splash screen using the other attributes on the theme, like the
+ {@link android.R.attr#windowBackground}.
+ -->
+ <attr name="windowSplashscreenContent" format="reference" />
</declare-styleable>
<!-- The set of attributes that describe a AlertDialog's theme. -->
@@ -2953,6 +2963,9 @@
See {@link android.view.View#setFocusedByDefault(boolean)}. -->
<attr name="focusedByDefault" format="boolean" />
+ <!-- Whether this View should use a default focus highlight when it gets focused but
+ doesn't have {@link android.R.attr#state_focused} defined in its background. -->
+ <attr name="defaultFocusHighlightEnabled" format="boolean" />
</declare-styleable>
<!-- Attributes that can be assigned to a tag for a particular View. -->
@@ -3214,18 +3227,7 @@
and subtype in order to provide the consistent user experience in switching
between IMEs and subtypes. -->
<attr name="supportsSwitchingToNextInputMethod" format="boolean" />
- <!-- Set to true if this input method supports ways to dismiss the windows assigned to
- the input method (for example, a dismiss button rendered by the input method itself). The
- System UI may optimize the UI by not showing system-level dismiss button if this
- value is true.
- <p> Must be a boolean value, either "true" or "false". The default value is "false".
- <p> This may also be a reference to a resource (in the form "@[package:]type:name")
- or theme attribute (in the form "?[package:]type:name") containing a value of this
- type.
- <p> A UI element that dismisses the input method window should report
- {@link android.view.accessibility.AccessibilityNodeInfo#ACTION_DISMISS} action, so
- that accessibility services can handle it accordingly. -->
- <attr name="supportsDismissingWindow" format="boolean" />
+ <attr name="__removed2" format="boolean" />
</declare-styleable>
<!-- This is the subtype of InputMethod. Subtype can describe locales (for example, en_US and
@@ -8559,6 +8561,11 @@
<!-- @hide From Theme.colorBackground, used for the TaskDescription background
color. -->
<attr name="colorBackground" />
+ <!-- @hide From Theme.statusBarColor, used for the TaskDescription status bar color. -->
+ <attr name="statusBarColor"/>
+ <!-- @hide From Theme.navigationBarColor, used for the TaskDescription navigation bar
+ color. -->
+ <attr name="navigationBarColor"/>
</declare-styleable>
<declare-styleable name="Shortcut">
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 3e4b66d7..5696468 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -322,6 +322,10 @@
your application running at all times. -->
<attr name="persistent" format="boolean" />
+ <!-- If set, the "persistent" attribute will only be honored if the feature
+ specified here is present on the device. -->
+ <attr name="persistentFeature" format="string" />
+
<!-- Flag to specify if this application needs to be present for all users. Only pre-installed
applications can request this feature. Default value is false. -->
<attr name="requiredForAllUsers" format="boolean" />
@@ -1358,6 +1362,7 @@
for normal behavior. -->
<attr name="hasCode" format="boolean" />
<attr name="persistent" />
+ <attr name="persistentFeature" />
<attr name="requiredForAllUsers" />
<!-- Specify whether the components in this application are enabled or not (that is, can be
instantiated by the system).
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 3dd7ad4..45dccb6 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1881,10 +1881,6 @@
<!-- Amount of time in ms the user needs to press the relevant key to bring up the global actions dialog -->
<integer name="config_globalActionsKeyTimeout">500</integer>
- <!-- Default width of a vertical scrollbar and height of a horizontal scrollbar.
- Takes effect only if the scrollbar drawables have no intrinsic size. -->
- <dimen name="config_scrollbarSize">4dp</dimen>
-
<!-- Distance that should be scrolled, per axis value, in response to a horizontal
{@link MotionEvent#ACTION_SCROLL} event. -->
<dimen name="config_horizontalScrollFactor">64dp</dimen>
@@ -2798,7 +2794,7 @@
<string name="config_defaultCellBroadcastReceiverPkg" translatable="false">com.android.cellbroadcastreceiver</string>
<!-- Specifies the path that is used by AdaptiveIconDrawable class to crop launcher icons. -->
- <string name="config_icon_mask" translatable="false">"M50,0L100,0 100,100 0,100 0,0z"</string>
+ <string name="config_icon_mask" translatable="false">"M50,0L92,0 A8,8,0,0 1 100,8 L100,92 A8,8,0,0 1 92,100 L8,100 A8,8,0,0 1 0,92 L 0,8 A8,8,0,0 1 8,0z"</string>
<!-- The component name, flattened to a string, for the default accessibility service to be
enabled by the accessibility shortcut. This service must be trusted, as it can be activated
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 1d1fd5e..d6ed178 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2785,7 +2785,7 @@
<public name="focusedByDefault" />
<public name="appCategory" />
<public name="autoSizeMaxTextSize" />
- <public name="supportsDismissingWindow" />
+ <public name="__removed2" />
<public name="restartOnConfigChanges" />
<public name="certDigest" />
<public name="splitName" />
@@ -2814,6 +2814,9 @@
<public name="iconTintMode" />
<public name="maxAspectRatio"/>
<public name="iconSpaceReserved"/>
+ <public name="defaultFocusHighlightEnabled" />
+ <public name="persistentFeature"/>
+ <public name="windowSplashscreenContent" />
</public-group>
<public-group type="style" first-id="0x010302e0">
@@ -2829,6 +2832,9 @@
<public name="autofilled_highlight" />
</public-group>
+ <public-group type="string" first-id="0x01040019">
+ <public name="paste_as_plain_text" />
+ </public-group>
<!-- ===============================================================
DO NOT ADD UN-GROUPED ITEMS HERE
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 75de4da..0821674 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3628,7 +3628,7 @@
<string name="data_usage_3g_limit_title">2G-3G data limit reached</string>
<!-- Notification title when 4G data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
<string name="data_usage_4g_limit_title">4G data limit reached</string>
- <!-- Notification title when mobile data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
+ <!-- Notification title when mobile data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=50] -->
<string name="data_usage_mobile_limit_title">Mobile data limit reached</string>
<!-- Notification title when Wi-Fi data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
<string name="data_usage_wifi_limit_title">Wi-Fi data limit reached</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 7dac18d..2ae2ca0 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -322,6 +322,7 @@
<item name="scrollbars">vertical</item>
<item name="fadingEdge">vertical</item>
<item name="fastScrollStyle">?attr/fastScrollStyle</item>
+ <item name="defaultFocusHighlightEnabled">false</item>
</style>
<style name="Widget.GestureOverlayView">
@@ -538,6 +539,7 @@
<item name="gravity">center_vertical</item>
<item name="breakStrategy">simple</item>
<item name="hyphenationFrequency">normal</item>
+ <item name="defaultFocusHighlightEnabled">false</item>
</style>
<style name="Widget.ExpandableListView" parent="Widget.ListView">
@@ -1482,4 +1484,10 @@
<item name="successColor">@color/lock_pattern_view_success_color</item>
</style>
+ <!-- @hide -->
+ <style name="AutofillDatasetPicker">
+ <item name="elevation">4dp</item>
+ <item name="background">@drawable/autofill_dataset_picker_background</item>
+ </style>
+
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7cb9ba8..603e376 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -434,7 +434,6 @@
<java-symbol type="dimen" name="config_viewConfigurationTouchSlop" />
<java-symbol type="dimen" name="config_viewMinFlingVelocity" />
<java-symbol type="dimen" name="config_viewMaxFlingVelocity" />
- <java-symbol type="dimen" name="config_scrollbarSize" />
<java-symbol type="dimen" name="config_horizontalScrollFactor" />
<java-symbol type="dimen" name="config_verticalScrollFactor" />
<java-symbol type="dimen" name="config_scrollFactor" />
@@ -2858,6 +2857,7 @@
<java-symbol type="id" name="accessibility_button_target_icon" />
<java-symbol type="id" name="accessibility_button_target_label" />
<java-symbol type="string" name="accessibility_magnification_chooser_text" />
+ <java-symbol type="drawable" name="ic_accessibility_magnification" />
<!-- com.android.internal.widget.RecyclerView -->
<java-symbol type="id" name="item_touch_helper_previous_elevation"/>
@@ -2866,10 +2866,10 @@
<java-symbol type="dimen" name="item_touch_helper_swipe_escape_max_velocity"/>
<!-- com.android.server.autofill -->
- <!-- TODO: floating_window_z temporary exposed until Autofill UI uses a ContextThemeWrapper -->
- <java-symbol type="dimen" name="floating_window_z" />
<java-symbol type="layout" name="autofill_save"/>
<java-symbol type="layout" name="autofill_dataset_picker"/>
+ <java-symbol type="id" name="autofill_dataset_picker"/>
+ <java-symbol type="id" name="autofill_dataset_list"/>
<java-symbol type="id" name="autofill" />
<java-symbol type="id" name="autofill_save_title" />
<java-symbol type="id" name="autofill_save_subtitle" />
@@ -2890,6 +2890,8 @@
<java-symbol type="string" name="autofill_save_type_credit_card" />
<java-symbol type="string" name="autofill_save_type_username" />
<java-symbol type="string" name="autofill_save_type_email_address" />
+ <java-symbol type="drawable" name="autofill_dataset_picker_background" />
+ <java-symbol type="style" name="AutofillDatasetPicker" />
<!-- Accessibility fingerprint gestures -->
<java-symbol type="string" name="capability_title_canCaptureFingerprintGestures" />
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 9911d9d..e0b4ec5 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -748,12 +748,12 @@
<!-- @hide DeviceDefault theme for a window that should use Settings theme colors
but has a full dark palette. ONLY USED FOR QUICK SETTINGS THEME -->
- <style name="Theme.DeviceDefault.QuickSettings" parent="Theme.Material">
+ <style name="Theme.DeviceDefault.QuickSettings" parent="Theme.DeviceDefault.Light">
<!-- Color palette -->
- <item name="colorPrimary">@color/primary_device_default_settings</item>
- <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
- <item name="colorSecondary">@color/secondary_device_default_settings</item>
- <item name="colorAccent">@color/accent_device_default_dark</item>
+ <item name="colorPrimary">@color/primary_device_default_settings_light</item>
+ <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
+ <item name="colorSecondary">@color/secondary_device_default_settings_light</item>
+ <item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorControlNormal">?attr/textColorPrimary</item>
</style>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 9dafa7a..86abe97 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -214,7 +214,7 @@
<!-- Scrollbar attributes -->
<item name="scrollbarFadeDuration">250</item>
<item name="scrollbarDefaultDelayBeforeFade">400</item>
- <item name="scrollbarSize">@dimen/config_scrollbarSize</item>
+ <item name="scrollbarSize">10dp</item>
<item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_material</item>
<item name="scrollbarThumbVertical">@drawable/config_scrollbarThumbVertical</item>
<item name="scrollbarTrackHorizontal">@null</item>
@@ -582,7 +582,7 @@
<!-- Scrollbar attributes -->
<item name="scrollbarFadeDuration">250</item>
<item name="scrollbarDefaultDelayBeforeFade">400</item>
- <item name="scrollbarSize">@dimen/config_scrollbarSize</item>
+ <item name="scrollbarSize">10dp</item>
<item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_material</item>
<item name="scrollbarThumbVertical">@drawable/config_scrollbarThumbVertical</item>
<item name="scrollbarTrackHorizontal">@null</item>
diff --git a/core/tests/coretests/res/xml/ime_meta_dismiss.xml b/core/tests/coretests/res/xml/ime_meta_dismiss.xml
deleted file mode 100644
index 59f8ecc..0000000
--- a/core/tests/coretests/res/xml/ime_meta_dismiss.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<input-method
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:settingsActivity="com.android.inputmethod.latin.settings.SettingsActivity"
- android:supportsDismissingWindow="true"
->
- <subtype
- android:label="subtype1"
- android:imeSubtypeLocale="en_US"
- android:imeSubtypeMode="keyboard" />
-</input-method>
diff --git a/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java b/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
index 6bcf8fc..0e1e6ac 100644
--- a/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
+++ b/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
@@ -27,6 +27,6 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.animator_basic);
- mAnimatingButton = (Button) findViewById(R.id.animatingButton);
+ mAnimatingButton = findViewById(R.id.animatingButton);
}
}
diff --git a/core/tests/coretests/src/android/database/PageViewCursorTest.java b/core/tests/coretests/src/android/database/PageViewCursorTest.java
deleted file mode 100644
index fba6aaf..0000000
--- a/core/tests/coretests/src/android/database/PageViewCursorTest.java
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.database;
-
-import static com.android.internal.util.ArrayUtils.contains;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.annotation.Nullable;
-import android.content.ContentResolver;
-import android.os.Build;
-import android.os.Bundle;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
-import android.util.MathUtils;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.Arrays;
-import java.util.Random;
-
-@RunWith(AndroidJUnit4.class)
-public class PageViewCursorTest {
-
- private static final int ITEM_COUNT = 20;
-
- private static final String NAME_COLUMN = "name";
- private static final String NUM_COLUMN = "num";
-
- private static final String[] COLUMNS = new String[] {
- NAME_COLUMN,
- NUM_COLUMN
- };
-
- private static final String[] NAMES = new String[] {
- "000",
- "111",
- "222",
- "333",
- "444",
- "555",
- "666",
- "777",
- "888",
- "999",
- "aaa",
- "bbb",
- "ccc",
- "ddd",
- "eee",
- "fff",
- "ggg",
- "hhh",
- "iii",
- "jjj"
- };
-
- private MatrixCursor mDelegate;
- private PageViewCursor mCursor;
-
- @Before
- public void setUp() {
- Random rand = new Random();
-
- mDelegate = new MatrixCursor(COLUMNS);
- for (int i = 0; i < ITEM_COUNT; i++) {
- MatrixCursor.RowBuilder row = mDelegate.newRow();
- row.add(NAME_COLUMN, NAMES[i]);
- row.add(NUM_COLUMN, rand.nextInt());
- }
-
- mCursor = new PageViewCursor(mDelegate, createArgs(10, 5));
- }
-
- @Test
- public void testPage_Size() {
- assertEquals(5, mCursor.getCount());
- }
-
- @Test
- public void testPage_TotalSize() {
- assertEquals(ITEM_COUNT, mCursor.getExtras().getInt(ContentResolver.EXTRA_TOTAL_SIZE));
- }
-
- @Test
- public void testPage_OffsetExceedsCursorCount_EffectivelyEmptyCursor() {
- mCursor = new PageViewCursor(mDelegate, createArgs(ITEM_COUNT * 2, 5));
- assertEquals(0, mCursor.getCount());
- }
-
- @Test
- public void testMoveToPosition() {
- assertTrue(mCursor.moveToPosition(0));
- assertEquals(NAMES[10], mCursor.getString(0));
- assertTrue(mCursor.moveToPosition(1));
- assertEquals(NAMES[11], mCursor.getString(0));
- assertTrue(mCursor.moveToPosition(4));
- assertEquals(NAMES[14], mCursor.getString(0));
-
- // and then back down again for good measure.
- assertTrue(mCursor.moveToPosition(1));
- assertEquals(NAMES[11], mCursor.getString(0));
- assertTrue(mCursor.moveToPosition(0));
- assertEquals(NAMES[10], mCursor.getString(0));
- }
-
- @Test
- public void testMoveToPosition_MoveToSamePosition_NoOp() {
- assertTrue(mCursor.moveToPosition(1));
- assertEquals(NAMES[11], mCursor.getString(0));
- assertTrue(mCursor.moveToPosition(1));
- assertEquals(NAMES[11], mCursor.getString(0));
- }
-
- @Test
- public void testMoveToPosition_PositionOutOfBounds_MovesToBeforeFirst() {
- assertTrue(mCursor.moveToPosition(0));
- assertEquals(NAMES[10], mCursor.getString(0));
-
- // move before
- assertFalse(mCursor.moveToPosition(-12));
- assertTrue(mCursor.isBeforeFirst());
- }
-
- @Test
- public void testMoveToPosition_PositionOutOfBounds_MovesToAfterLast() {
- assertTrue(mCursor.moveToPosition(0));
- assertEquals(NAMES[10], mCursor.getString(0));
-
- assertFalse(mCursor.moveToPosition(222));
- assertTrue(mCursor.isAfterLast());
- }
-
- @Test
- public void testPosition() {
- assertEquals(-1, mCursor.getPosition());
- }
-
- @Test
- public void testIsBeforeFirst() {
- assertTrue(mCursor.isBeforeFirst());
- mCursor.moveToFirst();
- assertFalse(mCursor.isBeforeFirst());
- }
-
- @Test
- public void testCount_ZeroForEmptyCursor() {
- mCursor = new PageViewCursor(mDelegate, createArgs(0, 0));
- assertEquals(0, mCursor.getCount());
- }
-
- @Test
- public void testIsBeforeFirst_TrueForEmptyCursor() {
- mCursor = new PageViewCursor(mDelegate, createArgs(0, 0));
- assertTrue(mCursor.isBeforeFirst());
- }
-
- @Test
- public void testIsAfterLast() {
- assertFalse(mCursor.isAfterLast());
- mCursor.moveToLast();
- mCursor.moveToNext();
- assertTrue(mCursor.isAfterLast());
- }
-
- @Test
- public void testIsAfterLast_TrueForEmptyCursor() {
- mCursor = new PageViewCursor(mDelegate, createArgs(0, 0));
- assertTrue(mCursor.isAfterLast());
- }
-
- @Test
- public void testIsFirst() {
- assertFalse(mCursor.isFirst());
- mCursor.moveToFirst();
- assertTrue(mCursor.isFirst());
- }
-
- @Test
- public void testIsLast() {
- assertFalse(mCursor.isLast());
- mCursor.moveToLast();
- assertTrue(mCursor.isLast());
- }
-
- @Test
- public void testMove() {
- // note that initial position is -1, so moving
- // 2 will only put as at 1.
- mCursor.move(2);
- assertEquals(NAMES[11], mCursor.getString(0));
- mCursor.move(-1);
- assertEquals(NAMES[10], mCursor.getString(0));
- }
-
- @Test
- public void testMoveToFist() {
- mCursor.moveToPosition(3);
- mCursor.moveToFirst();
- assertEquals(NAMES[10], mCursor.getString(0));
- }
-
- @Test
- public void testMoveToLast() {
- mCursor.moveToLast();
- assertEquals(NAMES[14], mCursor.getString(0));
- }
-
- @Test
- public void testMoveToNext() {
- // default position is -1, so next is 0.
- mCursor.moveToNext();
- assertEquals(NAMES[10], mCursor.getString(0));
- }
-
- @Test
- public void testMoveToNext_AfterLastReturnsFalse() {
- mCursor.moveToLast();
- assertFalse(mCursor.moveToNext());
- }
-
- @Test
- public void testMoveToPrevious() {
- mCursor.moveToPosition(3);
- mCursor.moveToPrevious();
- assertEquals(NAMES[12], mCursor.getString(0));
- }
-
- @Test
- public void testMoveToPrevious_BeforeFirstReturnsFalse() {
- assertFalse(mCursor.moveToPrevious());
- }
-
- @Test
- public void testWindow_ReadPastEnd() {
- assertFalse(mCursor.moveToPosition(10));
- }
-
- @Test
- public void testLimitOutOfBounds() {
- mCursor = new PageViewCursor(mDelegate, createArgs(5, 100));
- assertEquals(15, mCursor.getCount());
- }
-
- @Test
- public void testOffsetOutOfBounds_EmptyResult() {
- mCursor = new PageViewCursor(mDelegate, createArgs(100000, 100));
- assertEquals(0, mCursor.getCount());
- }
-
- @Test
- public void testAddsExtras() {
- mCursor = new PageViewCursor(mDelegate, createArgs(5, 100));
- assertTrue(mCursor.getExtras().getBoolean(PageViewCursor.EXTRA_AUTO_PAGED));
- String[] honoredArgs = mCursor.getExtras()
- .getStringArray(ContentResolver.EXTRA_HONORED_ARGS);
- assertTrue(contains(honoredArgs, ContentResolver.QUERY_ARG_OFFSET));
- assertTrue(contains(honoredArgs, ContentResolver.QUERY_ARG_LIMIT));
- }
-
- @Test
- public void testAddsExtras_OnlyOffset() {
- Bundle args = new Bundle();
- args.putInt(ContentResolver.QUERY_ARG_OFFSET, 5);
- mCursor = new PageViewCursor(mDelegate, args);
- String[] honoredArgs = mCursor.getExtras()
- .getStringArray(ContentResolver.EXTRA_HONORED_ARGS);
- assertTrue(contains(honoredArgs, ContentResolver.QUERY_ARG_OFFSET));
- assertFalse(contains(honoredArgs, ContentResolver.QUERY_ARG_LIMIT));
- }
-
- @Test
- public void testAddsExtras_OnlyLimit() {
- Bundle args = new Bundle();
- args.putInt(ContentResolver.QUERY_ARG_LIMIT, 5);
- mCursor = new PageViewCursor(mDelegate, args);
- String[] honoredArgs = mCursor.getExtras()
- .getStringArray(ContentResolver.EXTRA_HONORED_ARGS);
- assertFalse(contains(honoredArgs, ContentResolver.QUERY_ARG_OFFSET));
- assertTrue(contains(honoredArgs, ContentResolver.QUERY_ARG_LIMIT));
- }
-
- @Test
- public void testGetWindow() {
- mCursor = new PageViewCursor(mDelegate, createArgs(5, 5));
- CursorWindow window = mCursor.getWindow();
- assertEquals(5, window.getNumRows());
- }
-
- @Test
- public void testWraps() {
- Bundle args = createArgs(5, 5);
- Cursor wrapped = PageViewCursor.wrap(mDelegate, args);
- assertTrue(wrapped instanceof PageViewCursor);
- assertEquals(5, wrapped.getCount());
- }
-
- @Test
- public void testWraps_NullExtras() {
- Bundle args = createArgs(5, 5);
- mDelegate.setExtras(null);
- Cursor wrapped = PageViewCursor.wrap(mDelegate, args);
- assertTrue(wrapped instanceof PageViewCursor);
- assertEquals(5, wrapped.getCount());
- }
-
- @Test
- public void testWraps_WithJustOffset() {
- Bundle args = new Bundle();
- args.putInt(ContentResolver.QUERY_ARG_OFFSET, 5);
- Cursor wrapped = PageViewCursor.wrap(mDelegate, args);
- assertTrue(wrapped instanceof PageViewCursor);
- assertEquals(15, wrapped.getCount());
- }
-
- @Test
- public void testWraps_WithJustLimit() {
- Bundle args = new Bundle();
- args.putInt(ContentResolver.QUERY_ARG_LIMIT, 5);
- Cursor wrapped = PageViewCursor.wrap(mDelegate, args);
- assertTrue(wrapped instanceof PageViewCursor);
- assertEquals(5, wrapped.getCount());
- }
-
- @Test
- public void testNoWrap_WithoutPagingArgs() {
- Cursor wrapped = PageViewCursor.wrap(mDelegate, Bundle.EMPTY);
- assertTrue(mDelegate == wrapped);
- }
-
- @Test
- public void testNoWrap_CursorsHasExistingPaging_ByTotalSize() {
- Bundle extras = new Bundle();
- extras.putInt(ContentResolver.EXTRA_TOTAL_SIZE, 5);
- mDelegate.setExtras(extras);
-
- Bundle args = createArgs(5, 5);
- Cursor wrapped = PageViewCursor.wrap(mDelegate, args);
- assertTrue(mDelegate == wrapped);
- }
-
- @Test
- public void testNoWrap_CursorsHasExistingPaging_ByHonoredArgs() {
- Bundle extras = new Bundle();
- extras.putStringArray(
- ContentResolver.EXTRA_HONORED_ARGS,
- new String[] {
- ContentResolver.QUERY_ARG_OFFSET,
- ContentResolver.QUERY_ARG_LIMIT
- });
- mDelegate.setExtras(extras);
-
- Bundle args = createArgs(5, 5);
- Cursor wrapped = PageViewCursor.wrap(mDelegate, args);
- assertTrue(mDelegate == wrapped);
- }
-
- private static Bundle createArgs(int offset, int limit) {
- Bundle args = new Bundle();
- args.putInt(ContentResolver.QUERY_ARG_OFFSET, offset);
- args.putInt(ContentResolver.QUERY_ARG_LIMIT, limit);
- return args;
- }
-
- private void assertStringAt(int row, int column, String expected) {
- mCursor.moveToPosition(row);
- assertEquals(expected, mCursor.getString(column));
- }
-}
diff --git a/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java b/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java
index 5ade66e..7550cb5 100644
--- a/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java
+++ b/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java
@@ -2,18 +2,22 @@
import static org.junit.Assert.assertTrue;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.Region;
import android.test.AndroidTestCase;
import android.util.Log;
+import android.util.PathParser;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Arrays;
@@ -35,7 +39,7 @@
* Nothing is drawn.
*/
@Test
- public void testDrawWithoutSetBounds() throws Exception {
+ public void testDraw_withoutBounds() throws Exception {
mBackgroundDrawable = new ColorDrawable(Color.BLUE);
mForegroundDrawable = new ColorDrawable(Color.RED);
mIconDrawable = new AdaptiveIconDrawable(mBackgroundDrawable, mForegroundDrawable);
@@ -59,7 +63,7 @@
* When setBound is called, translate accordingly.
*/
@Test
- public void testDrawSetBounds() throws Exception {
+ public void testDraw_withBounds() throws Exception {
int dpi = 4 ;
int top = 18 * dpi;
int left = 18 * dpi;
@@ -102,6 +106,71 @@
}
}
+ /**
+ * When setBound isn't called before getIconMask method is called.
+ * default device config mask is returned.
+ */
+ @Test
+ public void testGetIconMask_withoutBounds() throws Exception {
+ mIconDrawable = new AdaptiveIconDrawable(mBackgroundDrawable, mForegroundDrawable);
+ Path pathFromDrawable = mIconDrawable.getIconMask();
+ Path pathFromDeviceConfig = PathParser.createPathFromPathData(
+ Resources.getSystem().getString(com.android.internal.R.string.config_icon_mask));
+
+ RectF boundFromDrawable = new RectF();
+ pathFromDrawable.computeBounds(boundFromDrawable, true);
+
+ RectF boundFromDeviceConfig = new RectF();
+ pathFromDeviceConfig.computeBounds(boundFromDeviceConfig, true);
+
+ double delta = 0.01;
+ assertEquals("left", boundFromDrawable.left, boundFromDeviceConfig.left, delta);
+ assertEquals("top", boundFromDrawable.top, boundFromDeviceConfig.top, delta);
+ assertEquals("right", boundFromDrawable.right, boundFromDeviceConfig.right, delta);
+ assertEquals("bottom", boundFromDrawable.bottom, boundFromDeviceConfig.bottom, delta);
+
+ assertTrue("path from device config is convex.", pathFromDeviceConfig.isConvex());
+ assertTrue("path from drawable is convex.", pathFromDrawable.isConvex());
+ }
+
+ @Test
+ public void testGetIconMaskAfterSetBounds() throws Exception {
+ int dpi = 4;
+ int top = 18 * dpi;
+ int left = 18 * dpi;
+ int right = 90 * dpi;
+ int bottom = 90 * dpi;
+
+ mIconDrawable = new AdaptiveIconDrawable(mBackgroundDrawable, mForegroundDrawable);
+ mIconDrawable.setBounds(left, top, right, bottom);
+ RectF maskBounds = new RectF();
+
+ mIconDrawable.getIconMask().computeBounds(maskBounds, true);
+
+ double delta = 0.01;
+ assertEquals("left", left, maskBounds.left, delta);
+ assertEquals("top", top, maskBounds.top, delta);
+ assertEquals("right", right, maskBounds.right, delta);
+ assertEquals("bottom", bottom, maskBounds.bottom, delta);
+
+ assertTrue(mIconDrawable.getIconMask().isConvex());
+ }
+
+ @Test
+ public void testGetOutline_withBounds() throws Exception {
+ int dpi = 4;
+ int top = 18 * dpi;
+ int left = 18 * dpi;
+ int right = 90 * dpi;
+ int bottom = 90 * dpi;
+
+ mIconDrawable = new AdaptiveIconDrawable(mBackgroundDrawable, mForegroundDrawable);
+ mIconDrawable.setBounds(left, top, right, bottom);
+ Outline outline = new Outline();
+ mIconDrawable.getOutline(outline);
+ assertTrue("outline path should be convex", outline.mPath.isConvex());
+ }
+
//
// Utils
//
diff --git a/core/tests/coretests/src/android/graphics/drawable/IconTest.java b/core/tests/coretests/src/android/graphics/drawable/IconTest.java
index b50955b..b7a48c7 100644
--- a/core/tests/coretests/src/android/graphics/drawable/IconTest.java
+++ b/core/tests/coretests/src/android/graphics/drawable/IconTest.java
@@ -119,13 +119,13 @@
final AdaptiveIconDrawable draw1 = (AdaptiveIconDrawable) im1.loadDrawable(mContext);
final Bitmap test1 = Bitmap.createBitmap(
- (int)(draw1.getIntrinsicWidth() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetPercentage())),
- (int)(draw1.getIntrinsicHeight() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetPercentage())),
+ (int)(draw1.getIntrinsicWidth() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction())),
+ (int)(draw1.getIntrinsicHeight() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction())),
Bitmap.Config.ARGB_8888);
draw1.setBounds(0, 0,
- (int) (draw1.getIntrinsicWidth() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetPercentage())),
- (int) (draw1.getIntrinsicHeight() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetPercentage())));
+ (int) (draw1.getIntrinsicWidth() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction())),
+ (int) (draw1.getIntrinsicHeight() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction())));
draw1.draw(new Canvas(test1));
final File dir = getContext().getExternalFilesDir(null);
diff --git a/core/tests/coretests/src/android/os/BrightnessLimit.java b/core/tests/coretests/src/android/os/BrightnessLimit.java
index f4a5e09..43cd373 100644
--- a/core/tests/coretests/src/android/os/BrightnessLimit.java
+++ b/core/tests/coretests/src/android/os/BrightnessLimit.java
@@ -40,7 +40,7 @@
setContentView(R.layout.brightness_limit);
- Button b = (Button) findViewById(R.id.go);
+ Button b = findViewById(R.id.go);
b.setOnClickListener(this);
}
diff --git a/core/tests/coretests/src/android/os/VintfObjectTest.java b/core/tests/coretests/src/android/os/VintfObjectTest.java
new file mode 100644
index 0000000..aaaf55c
--- /dev/null
+++ b/core/tests/coretests/src/android/os/VintfObjectTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+public class VintfObjectTest extends TestCase {
+ public void testReport() {
+ String[] xmls = VintfObject.report();
+ assertTrue(xmls.length > 0);
+ // From /system/manifest.xml
+ assertTrue(String.join("", xmls).contains(
+ "<manifest version=\"1.0\" type=\"framework\">"));
+ }
+}
diff --git a/core/tests/coretests/src/android/provider/FontsContractTest.java b/core/tests/coretests/src/android/provider/FontsContractTest.java
index 1dd3ef6..ccc8c18 100644
--- a/core/tests/coretests/src/android/provider/FontsContractTest.java
+++ b/core/tests/coretests/src/android/provider/FontsContractTest.java
@@ -17,29 +17,29 @@
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
+import static android.provider.FontsContract.Columns.RESULT_CODE_OK;
+import static android.provider.FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND;
+import static android.provider.FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE;
+import static android.provider.FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY;
+
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.Signature;
import android.database.MatrixCursor;
-import android.graphics.Typeface;
import android.graphics.fonts.FontRequest;
-import android.graphics.fonts.FontResult;
-import android.os.Bundle;
-import android.os.ResultReceiver;
+import android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+import android.graphics.fonts.FontVariationAxis;
+import android.provider.FontsContract.FontInfo;
import android.support.test.filters.SmallTest;
import android.test.ProviderTestCase2;
import android.util.Base64;
-import org.mockito.ArgumentCaptor;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -61,8 +61,6 @@
private final FontRequest request = new FontRequest(
TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query");
private TestFontsProvider mProvider;
- private FontsContract mContract;
- private ResultReceiver mResultReceiver;
private PackageManager mPackageManager;
public FontsContractTest() {
@@ -74,126 +72,178 @@
mProvider = getProvider();
mPackageManager = mock(PackageManager.class);
- mContract = new FontsContract(getMockContext(), mPackageManager);
- mResultReceiver = mock(ResultReceiver.class);
}
- public void testGetFontFromProvider_resultOK() {
- mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
-
- final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
- verify(mResultReceiver).send(
- eq(FontsContract.Columns.RESULT_CODE_OK), bundleCaptor.capture());
-
- Bundle bundle = bundleCaptor.getValue();
- assertNotNull(bundle);
- List<FontResult> resultList =
- bundle.getParcelableArrayList(FontsContract.PARCEL_FONT_RESULTS);
- assertNotNull(resultList);
- assertEquals(1, resultList.size());
- FontResult fontResult = resultList.get(0);
- assertEquals(TestFontsProvider.TTC_INDEX, fontResult.getTtcIndex());
- assertEquals(TestFontsProvider.VARIATION_SETTINGS, fontResult.getFontVariationSettings());
- assertEquals(TestFontsProvider.NORMAL_WEIGHT, fontResult.getWeight());
- assertEquals(TestFontsProvider.ITALIC, fontResult.getItalic());
- assertNotNull(fontResult.getFileDescriptor());
+ public void testGetFontFromProvider_resultOK() throws InvalidFormatException {
+ FontInfo[] fonts = FontsContract.getFontFromProvider(
+ getMockContext(), request, TestFontsProvider.AUTHORITY, null);
+ assertNotNull(fonts);
+ assertEquals(1, fonts.length);
+ FontInfo font = fonts[0];
+ assertEquals(TestFontsProvider.TTC_INDEX, font.getTtcIndex());
+ FontVariationAxis[] actual = font.getAxes();
+ assertEquals(1, actual.length);
+ assertEquals("wdth", actual[0].getTag());
+ assertEquals(1.0f, actual[0].getStyleValue(), 0);
+ assertEquals(TestFontsProvider.NORMAL_WEIGHT, font.getWeight());
+ assertEquals(TestFontsProvider.ITALIC, font.isItalic());
+ assertNotNull(font.getUri());
+ assertEquals(RESULT_CODE_OK, font.getResultCode());
}
- public void testGetFontFromProvider_providerDoesntReturnAllFields() {
+ public void testGetFontFromProvider_providerDoesntReturnAllFields()
+ throws InvalidFormatException {
mProvider.setReturnAllFields(false);
- final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
- mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
- verify(mResultReceiver).send(
- eq(FontsContract.Columns.RESULT_CODE_OK), bundleCaptor.capture());
-
- Bundle bundle = bundleCaptor.getValue();
- assertNotNull(bundle);
- List<FontResult> resultList =
- bundle.getParcelableArrayList(FontsContract.PARCEL_FONT_RESULTS);
- assertNotNull(resultList);
- assertEquals(1, resultList.size());
- FontResult fontResult = resultList.get(0);
- assertEquals(0, fontResult.getTtcIndex());
- assertNull(fontResult.getFontVariationSettings());
- assertEquals(400, fontResult.getWeight());
- assertFalse(fontResult.getItalic());
- assertNotNull(fontResult.getFileDescriptor());
+ FontInfo[] fonts = FontsContract.getFontFromProvider(
+ getMockContext(), request, TestFontsProvider.AUTHORITY, null);
+ assertNotNull(fonts);
+ assertEquals(1, fonts.length);
+ FontInfo font = fonts[0];
+ assertEquals(0, font.getTtcIndex());
+ assertNull(font.getAxes());
+ assertEquals(400, font.getWeight());
+ assertFalse(font.isItalic());
+ assertNotNull(font.getUri());
+ assertEquals(RESULT_CODE_OK, font.getResultCode());
}
- public void testGetFontFromProvider_resultFontNotFound() {
+ public void testGetFontFromProvider_resultFontNotFound() throws InvalidFormatException {
// Make the provider return unknown
- mProvider.setResultCode(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND);
- mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
-
- verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND,null);
+ mProvider.setResultCode(RESULT_CODE_FONT_NOT_FOUND);
+ FontInfo[] fonts = FontsContract.getFontFromProvider(
+ getMockContext(), request, TestFontsProvider.AUTHORITY, null);
+ assertNotNull(fonts);
+ assertEquals(1, fonts.length);
+ FontInfo font = fonts[0];
+ assertEquals(TestFontsProvider.TTC_INDEX, font.getTtcIndex());
+ assertNotNull(font.getUri());
+ assertEquals(RESULT_CODE_FONT_NOT_FOUND, font.getResultCode());
}
- public void testGetFontFromProvider_resultFontUnavailable() {
+ public void testGetFontFromProvider_resultFontUnavailable() throws InvalidFormatException {
// Make the provider return font unavailable
- mProvider.setResultCode(FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE);
- mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+ mProvider.setResultCode(RESULT_CODE_FONT_UNAVAILABLE);
+ FontInfo[] fonts = FontsContract.getFontFromProvider(
+ getMockContext(), request, TestFontsProvider.AUTHORITY, null);
- verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE,null);
+ assertNotNull(fonts);
+ assertEquals(1, fonts.length);
+ FontInfo font = fonts[0];
+ assertEquals(TestFontsProvider.TTC_INDEX, font.getTtcIndex());
+ FontVariationAxis[] actual = font.getAxes();
+ assertEquals(1, actual.length);
+ assertEquals("wdth", actual[0].getTag());
+ assertEquals(1.0f, actual[0].getStyleValue(), 0);
+ assertEquals(TestFontsProvider.NORMAL_WEIGHT, font.getWeight());
+ assertEquals(TestFontsProvider.ITALIC, font.isItalic());
+ assertNotNull(font.getUri());
+ assertEquals(RESULT_CODE_FONT_UNAVAILABLE, font.getResultCode());
}
- public void testGetFontFromProvider_resultMalformedQuery() {
+ public void testGetFontFromProvider_resultMalformedQuery() throws InvalidFormatException {
// Make the provider return font unavailable
- mProvider.setResultCode(FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY);
- mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+ mProvider.setResultCode(RESULT_CODE_MALFORMED_QUERY);
+ FontInfo[] fonts = FontsContract.getFontFromProvider(
+ getMockContext(), request, TestFontsProvider.AUTHORITY, null);
- verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY,null);
+ assertNotNull(fonts);
+ assertEquals(1, fonts.length);
+ FontInfo font = fonts[0];
+ assertEquals(TestFontsProvider.TTC_INDEX, font.getTtcIndex());
+ FontVariationAxis[] actual = font.getAxes();
+ assertEquals(1, actual.length);
+ assertEquals("wdth", actual[0].getTag());
+ assertEquals(1.0f, actual[0].getStyleValue(), 0);
+ assertEquals(TestFontsProvider.NORMAL_WEIGHT, font.getWeight());
+ assertEquals(TestFontsProvider.ITALIC, font.isItalic());
+ assertNotNull(font.getUri());
+ assertEquals(RESULT_CODE_MALFORMED_QUERY, font.getResultCode());
}
- public void testGetFontFromProvider_resultFontNotFoundSecondRow() {
+ public void testGetFontFromProvider_resultFontNotFoundSecondRow()
+ throws InvalidFormatException {
MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
FontsContract.Columns.RESULT_CODE });
- cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0, RESULT_CODE_OK});
cursor.addRow(new Object[] { 1, 0, null, 400, 0,
- FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND});
+ RESULT_CODE_FONT_NOT_FOUND});
mProvider.setCustomCursor(cursor);
- mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+ FontInfo[] fonts = FontsContract.getFontFromProvider(
+ getMockContext(), request, TestFontsProvider.AUTHORITY, null);
- verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND, null);
+ assertNotNull(fonts);
+ assertEquals(2, fonts.length);
+
+ FontInfo font = fonts[0];
+ assertEquals(0, font.getTtcIndex());
+ assertNull(font.getAxes());
+ assertEquals(400, font.getWeight());
+ assertFalse(font.isItalic());
+ assertNotNull(font.getUri());
+ assertEquals(RESULT_CODE_OK, font.getResultCode());
+
+ font = fonts[1];
+ assertEquals(0, font.getTtcIndex());
+ assertNull(font.getAxes());
+ assertEquals(400, font.getWeight());
+ assertFalse(font.isItalic());
+ assertNotNull(font.getUri());
+ assertEquals(RESULT_CODE_FONT_NOT_FOUND, font.getResultCode());
}
- public void testGetFontFromProvider_resultFontNotFoundOtherRow() {
+ public void testGetFontFromProvider_resultFontNotFoundOtherRow() throws InvalidFormatException {
MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
FontsContract.Columns.RESULT_CODE });
- cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0, RESULT_CODE_OK});
cursor.addRow(new Object[] { 1, 0, null, 400, 0,
- FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND});
- cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
+ RESULT_CODE_FONT_NOT_FOUND});
+ cursor.addRow(new Object[] { 1, 0, null, 400, 0, RESULT_CODE_OK});
mProvider.setCustomCursor(cursor);
- mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+ FontInfo[] fonts = FontsContract.getFontFromProvider(
+ getMockContext(), request, TestFontsProvider.AUTHORITY, null);
- verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND, null);
- }
+ assertNotNull(fonts);
+ assertEquals(3, fonts.length);
- public void testGetFontFromProvider_resultCodeIsNegativeNumber() {
- MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
- FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
- FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
- FontsContract.Columns.RESULT_CODE });
- cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
- cursor.addRow(new Object[] { 1, 0, null, 400, 0, -5});
- mProvider.setCustomCursor(cursor);
- mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+ FontInfo font = fonts[0];
+ assertEquals(0, font.getTtcIndex());
+ assertNull(font.getAxes());
+ assertEquals(400, font.getWeight());
+ assertFalse(font.isItalic());
+ assertNotNull(font.getUri());
+ assertEquals(RESULT_CODE_OK, font.getResultCode());
- verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND, null);
+ font = fonts[1];
+ assertEquals(0, font.getTtcIndex());
+ assertNull(font.getAxes());
+ assertEquals(400, font.getWeight());
+ assertFalse(font.isItalic());
+ assertNotNull(font.getUri());
+ assertEquals(RESULT_CODE_FONT_NOT_FOUND, font.getResultCode());
+
+ font = fonts[2];
+ assertEquals(0, font.getTtcIndex());
+ assertNull(font.getAxes());
+ assertEquals(400, font.getWeight());
+ assertFalse(font.isItalic());
+ assertNotNull(font.getUri());
+ assertEquals(RESULT_CODE_OK, font.getResultCode());
}
public void testGetProvider_providerNotFound() {
when(mPackageManager.resolveContentProvider(anyString(), anyInt())).thenReturn(null);
- ProviderInfo result = mContract.getProvider(request, mResultReceiver);
-
- verify(mResultReceiver).send(FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND, null);
- assertNull(result);
+ try {
+ FontsContract.getProvider(mPackageManager, request);
+ fail();
+ } catch (NameNotFoundException e) {
+ // pass
+ }
}
public void testGetProvider_providerIsSystemApp() throws PackageManager.NameNotFoundException {
@@ -201,9 +251,7 @@
info.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
when(mPackageManager.resolveContentProvider(anyString(), anyInt())).thenReturn(info);
- ProviderInfo result = mContract.getProvider(request, mResultReceiver);
-
- verifyZeroInteractions(mResultReceiver);
+ ProviderInfo result = FontsContract.getProvider(mPackageManager, request);
assertEquals(info, result);
}
@@ -213,23 +261,22 @@
info.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
when(mPackageManager.resolveContentProvider(anyString(), anyInt())).thenReturn(info);
- ProviderInfo result = mContract.getProvider(
- new FontRequest(TestFontsProvider.AUTHORITY, "com.wrong.package", "query"),
- mResultReceiver);
+ try {
+ FontsContract.getProvider(
+ mPackageManager,
+ new FontRequest(TestFontsProvider.AUTHORITY, "com.wrong.package", "query"));
+ fail();
+ } catch (NameNotFoundException e) {
+ // pass
+ }
- verify(mResultReceiver).send(FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND, null);
- assertNull(result);
}
public void testGetProvider_providerIsNonSystemAppNoCerts()
throws PackageManager.NameNotFoundException {
setupPackageManager();
- // The default request is missing the certificates info.
- ProviderInfo result = mContract.getProvider(request, mResultReceiver);
-
- verify(mResultReceiver).send(FontsContract.RESULT_CODE_WRONG_CERTIFICATES, null);
- assertNull(result);
+ assertNull(FontsContract.getProvider(mPackageManager, request));
}
public void testGetProvider_providerIsNonSystemAppWrongCerts()
@@ -240,10 +287,8 @@
List<byte[]> certList = Arrays.asList(wrongCert);
FontRequest requestWrongCerts = new FontRequest(
TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
- ProviderInfo result = mContract.getProvider(requestWrongCerts, mResultReceiver);
- verify(mResultReceiver).send(FontsContract.RESULT_CODE_WRONG_CERTIFICATES, null);
- assertNull(result);
+ assertNull(FontsContract.getProvider(mPackageManager, requestWrongCerts));
}
public void testGetProvider_providerIsNonSystemAppCorrectCerts()
@@ -253,9 +298,9 @@
List<byte[]> certList = Arrays.asList(BYTE_ARRAY);
FontRequest requestRightCerts = new FontRequest(
TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
- ProviderInfo result = mContract.getProvider(requestRightCerts, mResultReceiver);
+ ProviderInfo result = FontsContract.getProvider(
+ mPackageManager, requestRightCerts);
- verifyZeroInteractions(mResultReceiver);
assertEquals(info, result);
}
@@ -267,11 +312,7 @@
List<byte[]> certList = Arrays.asList(wrongCert, BYTE_ARRAY);
FontRequest requestRightCerts = new FontRequest(
TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
- ProviderInfo result = mContract.getProvider(requestRightCerts, mResultReceiver);
-
- // There is one too many certs, should fail as the set doesn't match.
- verify(mResultReceiver).send(FontsContract.RESULT_CODE_WRONG_CERTIFICATES, null);
- assertNull(result);
+ assertNull(FontsContract.getProvider(mPackageManager, requestRightCerts));
}
public void testGetProvider_providerIsNonSystemAppDuplicateCerts()
@@ -294,12 +335,7 @@
List<byte[]> certList = Arrays.asList(BYTE_ARRAY_2, BYTE_ARRAY_COPY);
FontRequest requestRightCerts = new FontRequest(
TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
- ProviderInfo result = mContract.getProvider(requestRightCerts, mResultReceiver);
-
- // The given list includes an extra cert and doesn't have a second copy of the cert like
- // the provider does, so it should have failed.
- verify(mResultReceiver).send(FontsContract.RESULT_CODE_WRONG_CERTIFICATES, null);
- assertNull(result);
+ assertNull(FontsContract.getProvider(mPackageManager, requestRightCerts));
}
public void testGetProvider_providerIsNonSystemAppCorrectCertsSeveralSets()
@@ -312,9 +348,8 @@
certList.add(Arrays.asList(BYTE_ARRAY));
FontRequest requestRightCerts = new FontRequest(
TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", certList);
- ProviderInfo result = mContract.getProvider(requestRightCerts, mResultReceiver);
+ ProviderInfo result = FontsContract.getProvider(mPackageManager, requestRightCerts);
- verifyZeroInteractions(mResultReceiver);
assertEquals(info, result);
}
@@ -326,10 +361,12 @@
certList.add(Arrays.asList(BYTE_ARRAY));
FontRequest requestRightCerts = new FontRequest(
TestFontsProvider.AUTHORITY, "com.wrong.package.name", "query", certList);
- ProviderInfo result = mContract.getProvider(requestRightCerts, mResultReceiver);
-
- verify(mResultReceiver).send(FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND, null);
- assertNull(result);
+ try {
+ FontsContract.getProvider(mPackageManager, requestRightCerts);
+ fail();
+ } catch (NameNotFoundException e) {
+ // pass
+ }
}
private ProviderInfo setupPackageManager()
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 782a50f..d7887d3 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -473,7 +473,7 @@
Settings.Secure.USER_SETUP_COMPLETE,
Settings.Secure.VOICE_INTERACTION_SERVICE,
Settings.Secure.VOICE_RECOGNITION_SERVICE,
- Settings.Secure.WEB_ACTION_ENABLED);
+ Settings.Secure.INSTANT_APPS_ENABLED);
@Test
public void systemSettingsBackedUpOrBlacklisted() {
diff --git a/core/tests/coretests/src/android/view/Disabled.java b/core/tests/coretests/src/android/view/Disabled.java
index fa92107..d3c7470 100644
--- a/core/tests/coretests/src/android/view/Disabled.java
+++ b/core/tests/coretests/src/android/view/Disabled.java
@@ -34,16 +34,16 @@
setContentView(R.layout.disabled);
// Find our buttons
- Button disabledButton = (Button) findViewById(R.id.disabledButton);
+ Button disabledButton = findViewById(R.id.disabledButton);
disabledButton.setEnabled(false);
// Find our buttons
- Button disabledButtonA = (Button) findViewById(R.id.disabledButtonA);
+ Button disabledButtonA = findViewById(R.id.disabledButtonA);
disabledButtonA.setOnClickListener(this);
}
public void onClick(View v) {
- Button disabledButtonB = (Button) findViewById(R.id.disabledButtonB);
+ Button disabledButtonB = findViewById(R.id.disabledButtonB);
disabledButtonB.setEnabled(!disabledButtonB.isEnabled());
}
}
diff --git a/core/tests/coretests/src/android/view/DrawableBgMinSize.java b/core/tests/coretests/src/android/view/DrawableBgMinSize.java
index a75b23a..58bfb8a 100644
--- a/core/tests/coretests/src/android/view/DrawableBgMinSize.java
+++ b/core/tests/coretests/src/android/view/DrawableBgMinSize.java
@@ -58,14 +58,14 @@
mBackgroundDrawable = getResources().getDrawable(R.drawable.drawable_background);
mBigBackgroundDrawable = getResources().getDrawable(R.drawable.big_drawable_background);
- mChangeBackgroundsButton = (Button) findViewById(R.id.change_backgrounds);
+ mChangeBackgroundsButton = findViewById(R.id.change_backgrounds);
mChangeBackgroundsButton.setOnClickListener(this);
- mTextView = (TextView) findViewById(R.id.text_view);
- mLinearLayout = (LinearLayout) findViewById(R.id.linear_layout);
- mRelativeLayout = (RelativeLayout) findViewById(R.id.relative_layout);
- mFrameLayout = (FrameLayout) findViewById(R.id.frame_layout);
- mAbsoluteLayout = (AbsoluteLayout) findViewById(R.id.absolute_layout);
+ mTextView = findViewById(R.id.text_view);
+ mLinearLayout = findViewById(R.id.linear_layout);
+ mRelativeLayout = findViewById(R.id.relative_layout);
+ mFrameLayout = findViewById(R.id.frame_layout);
+ mAbsoluteLayout = findViewById(R.id.absolute_layout);
changeBackgrounds(mBackgroundDrawable);
}
diff --git a/core/tests/coretests/src/android/view/PopupWindowVisibility.java b/core/tests/coretests/src/android/view/PopupWindowVisibility.java
index 6e11ede..85ce04f 100644
--- a/core/tests/coretests/src/android/view/PopupWindowVisibility.java
+++ b/core/tests/coretests/src/android/view/PopupWindowVisibility.java
@@ -45,13 +45,13 @@
mFrame = findViewById(R.id.frame);
- mHide = (Button) findViewById(R.id.hide);
+ mHide = findViewById(R.id.hide);
mHide.setOnClickListener(this);
- mShow = (Button) findViewById(R.id.show);
+ mShow = findViewById(R.id.show);
mShow.setOnClickListener(this);
- Spinner spinner = (Spinner) findViewById(R.id.spinner);
+ Spinner spinner = findViewById(R.id.spinner);
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, mStrings);
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
@@ -59,7 +59,7 @@
ArrayAdapter<String> autoAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line, COUNTRIES);
- AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.auto);
+ AutoCompleteTextView textView = findViewById(R.id.auto);
textView.setAdapter(autoAdapter);
}
diff --git a/core/tests/coretests/src/android/view/PreDrawListener.java b/core/tests/coretests/src/android/view/PreDrawListener.java
index 981c6c0..60bbee4 100644
--- a/core/tests/coretests/src/android/view/PreDrawListener.java
+++ b/core/tests/coretests/src/android/view/PreDrawListener.java
@@ -75,9 +75,9 @@
super.onCreate(icicle);
setContentView(R.layout.pre_draw_listener);
- mFrame = (MyLinearLayout) findViewById(R.id.frame);
+ mFrame = findViewById(R.id.frame);
- Button mGoButton = (Button) findViewById(R.id.go);
+ Button mGoButton = findViewById(R.id.go);
mGoButton.setOnClickListener(this);
}
diff --git a/core/tests/coretests/src/android/view/Visibility.java b/core/tests/coretests/src/android/view/Visibility.java
index 97ff252..031568c 100644
--- a/core/tests/coretests/src/android/view/Visibility.java
+++ b/core/tests/coretests/src/android/view/Visibility.java
@@ -37,9 +37,9 @@
mVictim = findViewById(R.id.victim);
// Find our buttons
- Button visibleButton = (Button) findViewById(R.id.vis);
- Button invisibleButton = (Button) findViewById(R.id.invis);
- Button goneButton = (Button) findViewById(R.id.gone);
+ Button visibleButton = findViewById(R.id.vis);
+ Button invisibleButton = findViewById(R.id.invis);
+ Button goneButton = findViewById(R.id.gone);
// Wire each button to a click listener
visibleButton.setOnClickListener(mVisibleListener);
diff --git a/core/tests/coretests/src/android/view/VisibilityCallback.java b/core/tests/coretests/src/android/view/VisibilityCallback.java
index 7290a62..f98a0a8 100644
--- a/core/tests/coretests/src/android/view/VisibilityCallback.java
+++ b/core/tests/coretests/src/android/view/VisibilityCallback.java
@@ -45,9 +45,9 @@
mVictim = (MonitoredTextView)findViewById(R.id.victim);
// Find our buttons
- Button visibleButton = (Button) findViewById(R.id.vis);
- Button invisibleButton = (Button) findViewById(R.id.invis);
- Button goneButton = (Button) findViewById(R.id.gone);
+ Button visibleButton = findViewById(R.id.vis);
+ Button invisibleButton = findViewById(R.id.invis);
+ Button goneButton = findViewById(R.id.gone);
// Wire each button to a click listener
visibleButton.setOnClickListener(mVisibleListener);
diff --git a/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java b/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
index 23dc80f..13cef52 100644
--- a/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
@@ -51,12 +51,10 @@
final InputMethodInfo imi = buildInputMethodForTest(R.xml.ime_meta);
assertThat(imi.supportsSwitchingToNextInputMethod(), is(false));
- assertThat(imi.supportsDismissingWindow(), is(false));
final InputMethodInfo clone = cloneViaParcel(imi);
assertThat(clone.supportsSwitchingToNextInputMethod(), is(false));
- assertThat(clone.supportsDismissingWindow(), is(false));
}
@Test
@@ -70,17 +68,6 @@
assertThat(clone.supportsSwitchingToNextInputMethod(), is(true));
}
- @Test
- public void testSupportsDismissingWindow() throws Exception {
- final InputMethodInfo imi = buildInputMethodForTest(R.xml.ime_meta_dismiss);
-
- assertThat(imi.supportsDismissingWindow(), is(true));
-
- final InputMethodInfo clone = cloneViaParcel(imi);
-
- assertThat(clone.supportsDismissingWindow(), is(true));
- }
-
private InputMethodInfo buildInputMethodForTest(final @XmlRes int metaDataRes)
throws Exception {
final Context context = InstrumentationRegistry.getContext();
diff --git a/core/tests/coretests/src/android/widget/AutoCompleteTextViewSimple.java b/core/tests/coretests/src/android/widget/AutoCompleteTextViewSimple.java
index f6cec26..b4e05aa 100644
--- a/core/tests/coretests/src/android/widget/AutoCompleteTextViewSimple.java
+++ b/core/tests/coretests/src/android/widget/AutoCompleteTextViewSimple.java
@@ -47,7 +47,7 @@
// setup layout & views
setContentView(R.layout.autocompletetextview_simple);
- mTextView = (AutoCompleteTextView) findViewById(R.id.autocompletetextview1);
+ mTextView = findViewById(R.id.autocompletetextview1);
// configure callbacks used for monitoring
mTextView.setOnItemClickListener(this);
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 7edab008..3029134 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -26,7 +26,6 @@
import static android.widget.espresso.TextViewActions.Handle;
import static android.widget.espresso.TextViewActions.longPressAndDragOnText;
import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex;
-import static android.widget.espresso.TextViewAssertions.handleIsOnLine;
import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex;
import static android.widget.espresso.TextViewAssertions.hasSelection;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsDisplayed;
@@ -448,26 +447,6 @@
onView(withId(R.id.textview)).check(hasSelection("abcd\nefg\nhijk\nlmn\nopqr"));
}
- public void testSelectionHandles_multiLine_japanese() throws Exception {
- final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
- final StringBuilder builder = new StringBuilder();
- for (int i = 0; i < 100; ++i) {
- builder.append("\u3042\u3044\u3046\u3048\u304A");
- onView(withId(R.id.textview)).perform(replaceText(builder.toString()));
- final int lineEnd = textView.getLayout().getLineEnd(0);
- if (lineEnd < builder.length()) {
- break;
- }
- }
- onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(3));
-
- final int lineEnd = textView.getLayout().getLineEnd(0);
- onHandleView(com.android.internal.R.id.selection_end_handle)
- .perform(dragHandle(textView, Handle.SELECTION_END, lineEnd, true, false));
- onHandleView(com.android.internal.R.id.selection_end_handle)
- .check(handleIsOnLine(textView, 0));
- }
-
public void testSelectionHandles_multiLine_rtl() throws Exception {
// Arabic text.
final String text = "\u062A\u062B\u062C\n" + "\u062D\u062E\u062F\n"
diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
index 1e88712..335d021 100644
--- a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
+++ b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
@@ -331,37 +331,15 @@
*/
public static ViewAction dragHandle(TextView textView, Handle handleType, int endIndex,
boolean primary) {
- return dragHandle(textView, handleType, endIndex, primary, true);
- }
-
- /**
- * Returns an action that tap then drags on the handle from the current position to endIndex on
- * the TextView.<br>
- * <br>
- * View constraints:
- * <ul>
- * <li>must be a TextView's drag-handle displayed on screen
- * <ul>
- *
- * @param textView TextView the handle is on
- * @param handleType Type of the handle
- * @param endIndex The index of the TextView's text to end the drag at
- * @param primary whether to use primary direction to get coordinate form index when endIndex is
- * at a direction boundary.
- * @param getNewLineStartPosOnLineBreak whether to use new line start coordinate on a line break
- * within a paragraph.
- */
- public static ViewAction dragHandle(TextView textView, Handle handleType, int endIndex,
- boolean primary, boolean getNewLineStartPosOnLineBreak) {
return actionWithAssertions(
new DragAction(
DragAction.Drag.TAP,
new CurrentHandleCoordinates(textView),
- new HandleCoordinates(textView, handleType, endIndex, primary,
- getNewLineStartPosOnLineBreak),
+ new HandleCoordinates(textView, handleType, endIndex, primary),
Press.FINGER,
Editor.HandleView.class));
}
+
/**
* A provider of the x, y coordinates of the handle dragging point.
*/
@@ -424,16 +402,13 @@
private final Handle mHandleType;
private final int mIndex;
private final boolean mPrimary;
- private final boolean mGetNewLineStartPosOnLineBreak;
private final String mActionDescription;
- public HandleCoordinates(TextView textView, Handle handleType, int index, boolean primary,
- boolean getNewLineStartPosOnLineBreak) {
+ public HandleCoordinates(TextView textView, Handle handleType, int index, boolean primary) {
mTextView = textView;
mHandleType = handleType;
mIndex = index;
mPrimary = primary;
- mGetNewLineStartPosOnLineBreak = getNewLineStartPosOnLineBreak;
mActionDescription = "Could not locate " + handleType.toString()
+ " handle that points text index: " + index
+ " (" + (primary ? "primary" : "secondary" ) + ")";
@@ -470,10 +445,9 @@
final float currentX = handleView.getHorizontal(layout, currentOffset);
final float currentY = layout.getLineTop(currentLine);
final float[] currentCoordinates =
- convertToScreenCoordinates(mTextView, currentX, currentY);
+ TextCoordinates.convertToScreenCoordinates(mTextView, currentX, currentY);
final float[] targetCoordinates =
- (new TextCoordinates(mIndex, mPrimary, mGetNewLineStartPosOnLineBreak))
- .calculateCoordinates(mTextView);
+ (new TextCoordinates(mIndex, mPrimary)).calculateCoordinates(mTextView);
final Rect bounds = new Rect();
view.getBoundsOnScreen(bounds);
final Rect visibleDisplayBounds = new Rect();
@@ -511,27 +485,23 @@
private final int mIndex;
private final boolean mPrimary;
- private final boolean mGetNewLineStartPosOnLineBreak;
private final String mActionDescription;
public TextCoordinates(int index) {
- this(index, true, true);
+ this(index, true);
}
- public TextCoordinates(int index, boolean primary, boolean getNewLineStartPosOnLineBreak) {
+ public TextCoordinates(int index, boolean primary) {
mIndex = index;
mPrimary = primary;
- mGetNewLineStartPosOnLineBreak = getNewLineStartPosOnLineBreak;
mActionDescription = "Could not locate text at index: " + mIndex
- + " (" + (primary ? "primary" : "secondary" )
- + ", mGetNewLineStartPosOnLineBreak: " + mGetNewLineStartPosOnLineBreak + ")";
+ + " (" + (primary ? "primary" : "secondary" ) + ")";
}
@Override
public float[] calculateCoordinates(View view) {
try {
- return locateTextAtIndex((TextView) view, mIndex, mPrimary,
- mGetNewLineStartPosOnLineBreak);
+ return locateTextAtIndex((TextView) view, mIndex, mPrimary);
} catch (ClassCastException e) {
throw new PerformException.Builder()
.withActionDescription(mActionDescription)
@@ -550,38 +520,30 @@
/**
* @throws StringIndexOutOfBoundsException
*/
- private float[] locateTextAtIndex(TextView textView, int index, boolean primary,
- boolean getNewLineStartPosOnLineBreak) {
+ private float[] locateTextAtIndex(TextView textView, int index, boolean primary) {
if (index < 0 || index > textView.getText().length()) {
throw new StringIndexOutOfBoundsException(index);
}
final Layout layout = textView.getLayout();
-
- int line = layout.getLineForOffset(index);
- if (!getNewLineStartPosOnLineBreak && line > 0 && layout.getLineStart(line) == index
- && textView.getText().charAt(index - 1) != '\n') {
- line = line - 1;
- }
+ final int line = layout.getLineForOffset(index);
return convertToScreenCoordinates(textView,
- (primary ? layout.getPrimaryHorizontal(index, false,
- getNewLineStartPosOnLineBreak)
- : layout.getSecondaryHorizontal(index, false,
- getNewLineStartPosOnLineBreak)),
+ (primary ? layout.getPrimaryHorizontal(index)
+ : layout.getSecondaryHorizontal(index)),
layout.getLineTop(line));
}
- }
- /**
- * Convert TextView's local coordinates to on screen coordinates.
- * @param textView the TextView
- * @param x local horizontal coordinate
- * @param y local vertical coordinate
- * @return
- */
- public static float[] convertToScreenCoordinates(TextView textView, float x, float y) {
- final int[] xy = new int[2];
- textView.getLocationOnScreen(xy);
- return new float[]{ x + textView.getTotalPaddingLeft() - textView.getScrollX() + xy[0],
- y + textView.getTotalPaddingTop() - textView.getScrollY() + xy[1] };
+ /**
+ * Convert TextView's local coordinates to on screen coordinates.
+ * @param textView the TextView
+ * @param x local horizontal coordinate
+ * @param y local vertical coordinate
+ * @return
+ */
+ public static float[] convertToScreenCoordinates(TextView textView, float x, float y) {
+ final int[] xy = new int[2];
+ textView.getLocationOnScreen(xy);
+ return new float[]{ x + textView.getTotalPaddingLeft() - textView.getScrollX() + xy[0],
+ y + textView.getTotalPaddingTop() - textView.getScrollY() + xy[1] };
+ }
}
}
diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java b/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java
index fef84f4..6e44cd8 100644
--- a/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java
+++ b/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java
@@ -28,14 +28,11 @@
import android.support.test.espresso.ViewAssertion;
import android.view.View;
import android.widget.EditText;
-import android.widget.Editor;
import android.widget.TextView;
import junit.framework.AssertionFailedError;
import org.hamcrest.Matcher;
-import com.android.ex.editstyledtext.EditStyledText.EditModeActions.TextViewAction;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -140,14 +137,6 @@
}
/**
- * Returns a {@link ViewAssertion} that asserts that the TextView selection handle is on the
- * specified line.
- */
- public static ViewAssertion handleIsOnLine(TextView tv, int line) {
- return new SelectionHandlePositionAssertion(tv, line);
- }
-
- /**
* A {@link ViewAssertion} to check the selected text in a {@link TextView}.
*/
private static final class TextSelectionAssertion implements ViewAssertion {
@@ -227,31 +216,4 @@
closeTo(0f, 1f));
}
}
- /**
- * {@link ViewAssertion} to check that TextView selection handle is on a given line.
- */
- static class SelectionHandlePositionAssertion implements ViewAssertion {
- private TextView mTextView;
- private int mLine;
- private SelectionHandlePositionAssertion(TextView tv, int line) {
- mTextView = tv;
- mLine = line;
- }
-
- @Override
- public void check(View view, NoMatchingViewException exception) {
- if (!(view instanceof Editor.HandleView)) {
- throw new AssertionFailedError("View should be an instance of Editor.HandleView");
- }
- final Editor.HandleView handleView = (Editor.HandleView) view;
- final Rect bounds = new Rect();
- handleView.getBoundsOnScreen(bounds);
- final float bottom = mTextView.getLayout().getLineBottom(mLine);
- final float[] pos =
- TextViewActions.convertToScreenCoordinates(mTextView, 0, bottom);
-
- assertThat("Cursor should be on the line " + mLine, Double.valueOf(bounds.top),
- closeTo(pos[1], 1f));
- }
- }
}
diff --git a/core/tests/coretests/src/android/widget/focus/DescendantFocusability.java b/core/tests/coretests/src/android/widget/focus/DescendantFocusability.java
index f7d91aa..f6b0520 100644
--- a/core/tests/coretests/src/android/widget/focus/DescendantFocusability.java
+++ b/core/tests/coretests/src/android/widget/focus/DescendantFocusability.java
@@ -40,13 +40,13 @@
setContentView(R.layout.descendant_focusability);
- beforeDescendants = (ViewGroup) findViewById(R.id.beforeDescendants);
+ beforeDescendants = findViewById(R.id.beforeDescendants);
beforeDescendantsChild = (Button) beforeDescendants.getChildAt(0);
- afterDescendants = (ViewGroup) findViewById(R.id.afterDescendants);
+ afterDescendants = findViewById(R.id.afterDescendants);
afterDescendantsChild = (Button) afterDescendants.getChildAt(0);
- blocksDescendants = (ViewGroup) findViewById(R.id.blocksDescendants);
+ blocksDescendants = findViewById(R.id.blocksDescendants);
blocksDescendantsChild = (Button) blocksDescendants.getChildAt(0);
}
diff --git a/core/tests/coretests/src/android/widget/focus/FocusAfterRemoval.java b/core/tests/coretests/src/android/widget/focus/FocusAfterRemoval.java
index 93245e7..b3d5ec5 100644
--- a/core/tests/coretests/src/android/widget/focus/FocusAfterRemoval.java
+++ b/core/tests/coretests/src/android/widget/focus/FocusAfterRemoval.java
@@ -35,10 +35,10 @@
super.onCreate(icicle);
setContentView(R.layout.focus_after_removal);
- final LinearLayout left = (LinearLayout) findViewById(R.id.leftLayout);
+ final LinearLayout left = findViewById(R.id.leftLayout);
// top left makes parent layout GONE
- Button topLeftButton = (Button) findViewById(R.id.topLeftButton);
+ Button topLeftButton = findViewById(R.id.topLeftButton);
topLeftButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
@@ -48,7 +48,7 @@
// bottom left makes parent layout INVISIBLE
// top left makes parent layout GONE
- Button bottomLeftButton = (Button) findViewById(R.id.bottomLeftButton);
+ Button bottomLeftButton = findViewById(R.id.bottomLeftButton);
bottomLeftButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
@@ -57,7 +57,7 @@
});
// top right button makes top right button GONE
- final Button topRightButton = (Button) findViewById(R.id.topRightButton);
+ final Button topRightButton = findViewById(R.id.topRightButton);
topRightButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
@@ -66,7 +66,7 @@
});
// bottom right button makes bottom right button INVISIBLE
- final Button bottomRightButton = (Button) findViewById(R.id.bottomRightButton);
+ final Button bottomRightButton = findViewById(R.id.bottomRightButton);
bottomRightButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
diff --git a/core/tests/coretests/src/android/widget/focus/LinearLayoutGrid.java b/core/tests/coretests/src/android/widget/focus/LinearLayoutGrid.java
index db082ec..acd632f 100644
--- a/core/tests/coretests/src/android/widget/focus/LinearLayoutGrid.java
+++ b/core/tests/coretests/src/android/widget/focus/LinearLayoutGrid.java
@@ -33,7 +33,7 @@
}
public ViewGroup getRootView() {
- return (ViewGroup) findViewById(R.id.layout);
+ return findViewById(R.id.layout);
}
public Button getButtonAt(int column, int row) {
@@ -51,11 +51,11 @@
private LinearLayout getColumn(int column) {
switch (column) {
case 0:
- return (LinearLayout) findViewById(R.id.column1);
+ return findViewById(R.id.column1);
case 1:
- return (LinearLayout) findViewById(R.id.column2);
+ return findViewById(R.id.column2);
case 2:
- return (LinearLayout) findViewById(R.id.column3);
+ return findViewById(R.id.column3);
default:
throw new IllegalArgumentException("column out of range");
}
diff --git a/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabels.java b/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabels.java
index ceb0e95..b908201 100644
--- a/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabels.java
+++ b/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabels.java
@@ -54,7 +54,7 @@
setListAdapter(mMyAdapter);
// not in list
- Button topButton = (Button) findViewById(R.id.button);
+ Button topButton = findViewById(R.id.button);
topButton.setText("click to add new item");
topButton.setOnClickListener(new View.OnClickListener() {
diff --git a/core/tests/coretests/src/android/widget/focus/RequestFocus.java b/core/tests/coretests/src/android/widget/focus/RequestFocus.java
index 21d762a..4daf0b4 100644
--- a/core/tests/coretests/src/android/widget/focus/RequestFocus.java
+++ b/core/tests/coretests/src/android/widget/focus/RequestFocus.java
@@ -34,7 +34,7 @@
setContentView(R.layout.focus_after_removal);
// bottom right button starts with the focus.
- final Button bottomRightButton = (Button) findViewById(R.id.bottomRightButton);
+ final Button bottomRightButton = findViewById(R.id.bottomRightButton);
bottomRightButton.requestFocus();
bottomRightButton.setText("I should have focus");
}
diff --git a/core/tests/coretests/src/android/widget/gridview/GridPadding.java b/core/tests/coretests/src/android/widget/gridview/GridPadding.java
index 0b9e4c5..c3156dc 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridPadding.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridPadding.java
@@ -40,7 +40,7 @@
values[i] = String.valueOf(i);
}
- mGridView = (GridView) findViewById(R.id.grid);
+ mGridView = findViewById(R.id.grid);
mGridView.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, values));
}
diff --git a/core/tests/coretests/src/android/widget/gridview/GridScrollListener.java b/core/tests/coretests/src/android/widget/gridview/GridScrollListener.java
index 4290941..0ce5a31 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridScrollListener.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridScrollListener.java
@@ -46,8 +46,8 @@
values[i] = ((Integer)i).toString();
}
- mText = (TextView) findViewById(R.id.text);
- mGridView = (GridView) findViewById(R.id.grid);
+ mText = findViewById(R.id.text);
+ mGridView = findViewById(R.id.grid);
mGridView.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, values));
diff --git a/core/tests/coretests/src/android/widget/gridview/GridThrasher.java b/core/tests/coretests/src/android/widget/gridview/GridThrasher.java
index 0ef5db9..ad89bb6 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridThrasher.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridThrasher.java
@@ -115,9 +115,9 @@
setContentView(R.layout.grid_thrasher);
- mText = (TextView) findViewById(R.id.text);
+ mText = findViewById(R.id.text);
mAdapter = new ThrashListAdapter(this);
- GridView g = (GridView) findViewById(R.id.grid);
+ GridView g = findViewById(R.id.grid);
g.setAdapter(mAdapter);
mHandler.postDelayed(mThrash, 5000);
diff --git a/core/tests/coretests/src/android/widget/layout/linear/LLEditTextThenButton.java b/core/tests/coretests/src/android/widget/layout/linear/LLEditTextThenButton.java
index fe2525f..83331ca 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/LLEditTextThenButton.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/LLEditTextThenButton.java
@@ -36,9 +36,9 @@
setContentView(R.layout.linear_layout_edittext_then_button);
- mLayout = (LinearLayout) findViewById(R.id.layout);
- mEditText = (EditText) findViewById(R.id.editText);
- mButton = (Button) findViewById(R.id.button);
+ mLayout = findViewById(R.id.layout);
+ mEditText = findViewById(R.id.editText);
+ mButton = findViewById(R.id.button);
}
public LinearLayout getLayout() {
diff --git a/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons1.java b/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons1.java
index 3d0144f..ab2f060 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons1.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons1.java
@@ -37,7 +37,7 @@
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.linear_layout_buttons);
- mFirstButton = (Button) findViewById(R.id.button1);
+ mFirstButton = findViewById(R.id.button1);
mFirstButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
@@ -48,7 +48,7 @@
}
public LinearLayout getLayout() {
- return (LinearLayout) findViewById(R.id.layout);
+ return findViewById(R.id.layout);
}
public Button getFirstButton() {
diff --git a/core/tests/coretests/src/android/widget/listview/ListDividers.java b/core/tests/coretests/src/android/widget/listview/ListDividers.java
index 3928c03..9b5a087 100644
--- a/core/tests/coretests/src/android/widget/listview/ListDividers.java
+++ b/core/tests/coretests/src/android/widget/listview/ListDividers.java
@@ -40,7 +40,7 @@
values[i] = ((Integer) i).toString();
}
- mListView = (ListView) findViewById(android.R.id.list);
+ mListView = findViewById(android.R.id.list);
mListView.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, values));
diff --git a/core/tests/coretests/src/android/widget/listview/ListFilter.java b/core/tests/coretests/src/android/widget/listview/ListFilter.java
index 9e9d1b0..c2ac90e 100644
--- a/core/tests/coretests/src/android/widget/listview/ListFilter.java
+++ b/core/tests/coretests/src/android/widget/listview/ListFilter.java
@@ -46,10 +46,10 @@
getListView().setTextFilterEnabled(true);
mFrame = findViewById(R.id.frame);
- mHide = (Button) findViewById(R.id.hide);
+ mHide = findViewById(R.id.hide);
mHide.setOnClickListener(this);
- mShow = (Button) findViewById(R.id.show);
+ mShow = findViewById(R.id.show);
mShow.setOnClickListener(this);
}
diff --git a/core/tests/coretests/src/android/widget/listview/ListInHorizontal.java b/core/tests/coretests/src/android/widget/listview/ListInHorizontal.java
index 5f09ff6..a373a5b 100644
--- a/core/tests/coretests/src/android/widget/listview/ListInHorizontal.java
+++ b/core/tests/coretests/src/android/widget/listview/ListInHorizontal.java
@@ -43,7 +43,7 @@
values[i] = ((Integer) i).toString();
}
- mListView = (ListView) findViewById(R.id.list);
+ mListView = findViewById(R.id.list);
mListView.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, values));
diff --git a/core/tests/coretests/src/android/widget/listview/ListRecyclerProfiling.java b/core/tests/coretests/src/android/widget/listview/ListRecyclerProfiling.java
index d5d7261..76814fb 100644
--- a/core/tests/coretests/src/android/widget/listview/ListRecyclerProfiling.java
+++ b/core/tests/coretests/src/android/widget/listview/ListRecyclerProfiling.java
@@ -38,14 +38,14 @@
values[i] = ((Integer) i).toString();
}
- ListView listView = (ListView) findViewById(R.id.list);
+ ListView listView = findViewById(R.id.list);
ViewDebug.startRecyclerTracing("SimpleList", listView);
listView.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, values));
- ImageButton stopProfiling = (ImageButton) findViewById(R.id.pause);
+ ImageButton stopProfiling = findViewById(R.id.pause);
stopProfiling.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
ViewDebug.stopRecyclerTracing();
diff --git a/core/tests/coretests/src/android/widget/listview/ListScrollListener.java b/core/tests/coretests/src/android/widget/listview/ListScrollListener.java
index 58a31dc..f349dc6 100644
--- a/core/tests/coretests/src/android/widget/listview/ListScrollListener.java
+++ b/core/tests/coretests/src/android/widget/listview/ListScrollListener.java
@@ -46,7 +46,7 @@
values[i] = ((Integer)i).toString();
}
- mText = (TextView) findViewById(R.id.text);
+ mText = findViewById(R.id.text);
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, values));
diff --git a/core/tests/coretests/src/android/widget/listview/ListThrasher.java b/core/tests/coretests/src/android/widget/listview/ListThrasher.java
index ba3d590..0237a95 100644
--- a/core/tests/coretests/src/android/widget/listview/ListThrasher.java
+++ b/core/tests/coretests/src/android/widget/listview/ListThrasher.java
@@ -112,7 +112,7 @@
setContentView(R.layout.list_thrasher);
- mText = (TextView) findViewById(R.id.text);
+ mText = findViewById(R.id.text);
mAdapter = new ThrashListAdapter(this);
setListAdapter(mAdapter);
diff --git a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisible.java b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisible.java
index 9cc8544..afc275f 100644
--- a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisible.java
+++ b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisible.java
@@ -43,8 +43,8 @@
final Rect rect = new Rect();
final View childToMakeVisible = findViewById(R.id.childToMakeVisible);
- final TextView topBlob = (TextView) findViewById(R.id.topBlob);
- final TextView bottomBlob = (TextView) findViewById(R.id.bottomBlob);
+ final TextView topBlob = findViewById(R.id.topBlob);
+ final TextView bottomBlob = findViewById(R.id.bottomBlob);
// estimate to get blobs larger than screen
int screenHeight = getWindowManager().getDefaultDisplay().getHeight();
diff --git a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScroll.java b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScroll.java
index 0e2586d..731b25a 100644
--- a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScroll.java
+++ b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScroll.java
@@ -53,11 +53,11 @@
setContentView(R.layout.scroll_to_rect_with_internal_scroll);
- mTextBlob = (TextView) findViewById(R.id.blob);
+ mTextBlob = findViewById(R.id.blob);
mTextBlob.scrollBy(0, scrollYofBlob);
- mScrollToBlob = (Button) findViewById(R.id.scrollToBlob);
+ mScrollToBlob = findViewById(R.id.scrollToBlob);
mScrollToBlob.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
diff --git a/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabels.java b/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabels.java
index 4d0892c..027ea0f 100644
--- a/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabels.java
+++ b/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabels.java
@@ -66,8 +66,8 @@
int screenHeight = getWindowManager().getDefaultDisplay().getHeight();
mNumGroups = screenHeight / 30;
- mScrollView = (ScrollView) findViewById(R.id.scrollView);
- mLinearLayout = (LinearLayout) findViewById(R.id.layout);
+ mScrollView = findViewById(R.id.scrollView);
+ mLinearLayout = findViewById(R.id.layout);
LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 1080a9f..1859378 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -154,22 +154,6 @@
}
@Test
- public void reportChooserSelection() throws InterruptedException {
- Intent sendIntent = createSendImageIntent();
- final ChooserWrapperActivity activity = mActivityRule
- .launchActivity(Intent.createChooser(sendIntent, null));
- waitForIdle();
- UsageStatsManager usm = activity.getUsageStatsManager();
- String packageName = "test_package";
- String action = "test_action";
- String annotation = "test_annotation";
- long beforeReport = getCount(usm, packageName, action, annotation);
- usm.reportChooserSelection(packageName, activity.getUserId(), annotation, null, action);
- long afterReport = getCount(usm, packageName, action, annotation);
- assertThat(afterReport, is(beforeReport + 1l));
- }
-
- @Test
public void noResultsFromPackageManager() {
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
@@ -356,19 +340,4 @@
private void waitForIdle() {
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
-
- private Integer getCount(
- UsageStatsManager usm, String packageName, String action, String annotation) {
- if (usm == null) {
- return 0;
- }
- Map<String, UsageStats> stats =
- usm.queryAndAggregateUsageStats(Long.MIN_VALUE, Long.MAX_VALUE);
- UsageStats packageStats = stats.get(packageName);
- if (packageStats == null || packageStats.mChooserCounts == null
- || packageStats.mChooserCounts.get(action) == null) {
- return 0;
- }
- return packageStats.mChooserCounts.get(action).getOrDefault(annotation, 0);
- }
}
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
new file mode 100644
index 0000000..284ab60
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
+
+import android.app.usage.IUsageStatsManager;
+import android.app.usage.UsageStats;
+import android.app.usage.UsageStatsManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.ArrayMap;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * ResolverListController Test.
+ */
+@RunWith(AndroidJUnit4.class)
+public class ResolverListControllerTest {
+
+ @Mock private Context mMockContext;
+ @Mock private PackageManager mMockPackageManager;
+ @Mock private Resources mMockResources;
+ @Mock private IUsageStatsManager mMockService;
+
+ private ResolverListController mController;
+ private UsageStatsManager mUsm;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ Configuration config = new Configuration();
+ config.locale = Locale.getDefault();
+ List<ResolveInfo> services = new ArrayList<>();
+ when(mMockPackageManager.queryIntentServices(any(), anyInt())).thenReturn(services);
+ when(mMockResources.getConfiguration()).thenReturn(config);
+ when(mMockContext.getResources()).thenReturn(mMockResources);
+ when(mMockContext.getPackageName()).thenReturn("android");
+ when(mMockContext.getUserId()).thenReturn(54321);
+ when(mMockContext.getSharedPreferences(anyString(), anyInt())).thenReturn(null);
+ when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+ }
+
+ @Test
+ public void reportChooserSelection() throws InterruptedException, RemoteException {
+ String annotation = "test_annotation";
+ Intent sendIntent = createSendImageIntent(annotation);
+ String refererPackage = "test_referer_package";
+ String packageName = "test_package";
+ String action = "test_action";
+ final int initialCount = 1234;
+ UsageStats packageStats = initStats(packageName, action, annotation, initialCount);
+ UsageStats oneClickStats = initStats(packageName, action, annotation, 1);
+ final List<UsageStats> slices = new ArrayList<>();
+ slices.add(packageStats);
+ ParceledListSlice<UsageStats> stats = new ParceledListSlice<>(slices);
+ when(mMockService.queryUsageStats(anyInt(), anyLong(), anyLong(), anyString()))
+ .thenReturn(stats);
+ Answer<Void> answer = new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ slices.add(oneClickStats);
+ return null;
+ }
+ };
+ doAnswer(answer).when(mMockService).reportChooserSelection(
+ anyString(), anyInt(), anyString(), any(), anyString());
+ when(mMockContext.getOpPackageName()).thenReturn(refererPackage);
+ mUsm = new UsageStatsManager(mMockContext, mMockService);
+ when(mMockContext.getSystemService(Context.USAGE_STATS_SERVICE)).thenReturn(mUsm);
+ mController = new ResolverListController(mMockContext, mMockPackageManager, sendIntent,
+ refererPackage, UserHandle.USER_CURRENT);
+ mController.sort(new ArrayList<ResolverActivity.ResolvedComponentInfo>());
+ long beforeReport = getCount(mUsm, packageName, action, annotation);
+ mController.updateChooserCounts(packageName, UserHandle.USER_CURRENT, action);
+ long afterReport = getCount(mUsm, packageName, action, annotation);
+ assertThat(afterReport, is(beforeReport + 1l));
+ }
+
+ private UsageStats initStats(String packageName, String action,
+ String annotation, int count) {
+ ArrayMap<String, ArrayMap<String, Integer>> chooserCounts = new ArrayMap<>();
+ ArrayMap<String, Integer> counts = new ArrayMap<>();
+ counts.put(annotation, count);
+ chooserCounts.put(action, counts);
+ UsageStats packageStats = new UsageStats();
+ packageStats.mPackageName = packageName;
+ packageStats.mChooserCounts = chooserCounts;
+ return packageStats;
+ }
+
+ private Intent createSendImageIntent(String annotation) {
+ Intent sendIntent = new Intent();
+ sendIntent.setAction(Intent.ACTION_SEND);
+ sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
+ sendIntent.setType("image/jpeg");
+ ArrayList<String> annotations = new ArrayList<>();
+ annotations.add(annotation);
+ sendIntent.putStringArrayListExtra(Intent.EXTRA_CONTENT_ANNOTATIONS, annotations);
+ return sendIntent;
+ }
+
+ private Integer getCount(
+ UsageStatsManager usm, String packageName, String action, String annotation) {
+ if (usm == null) {
+ return 0;
+ }
+ Map<String, UsageStats> stats =
+ usm.queryAndAggregateUsageStats(Long.MIN_VALUE, Long.MAX_VALUE);
+ UsageStats packageStats = stats.get(packageName);
+ if (packageStats == null || packageStats.mChooserCounts == null
+ || packageStats.mChooserCounts.get(action) == null) {
+ return 0;
+ }
+ return packageStats.mChooserCounts.get(action).getOrDefault(annotation, 0);
+ }
+}
\ No newline at end of file
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 686f75b..515e558 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
@@ -75,8 +75,7 @@
}
final InputMethodInfo imi = new InputMethodInfo(ri, DUMMY_IS_AUX_IME,
DUMMY_SETTING_ACTIVITY_NAME, subtypes, DUMMY_IS_DEFAULT_RES_ID,
- DUMMY_FORCE_DEFAULT, supportsSwitchingToNextInputMethod,
- false /* supportsDismissingWindow */);
+ DUMMY_FORCE_DEFAULT, supportsSwitchingToNextInputMethod);
if (subtypes == null) {
items.add(new ImeSubtypeListItem(imeName, null /* variableName */, imi,
NOT_A_SUBTYPE_ID, null, SYSTEM_LOCALE));
@@ -112,8 +111,7 @@
.build());
final InputMethodInfo imi = new InputMethodInfo(ri, DUMMY_IS_AUX_IME,
DUMMY_SETTING_ACTIVITY_NAME, subtypes, DUMMY_IS_DEFAULT_RES_ID,
- DUMMY_FORCE_DEFAULT, true /* supportsSwitchingToNextInputMethod */,
- false /* supportsDismissingWindow */);
+ DUMMY_FORCE_DEFAULT, true /* supportsSwitchingToNextInputMethod */);
return new ImeSubtypeListItem(imeName, subtypeName, imi, subtypeIndex, subtypeLocale,
systemLocale);
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
index 2b0ae21..d8de70c 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
@@ -249,4 +249,65 @@
assertEquals(2, bi.getUidStats().get(UID).getJobStats().size());
bi.noteJobFinishLocked(jobName2, UID);
}
+
+ @SmallTest
+ public void testSyncs() throws Exception {
+ final MockClocks clocks = new MockClocks();
+ MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
+ final String syncName = "sync_name";
+ long curr = 0; // realtime in us
+
+ // On battery
+ curr = 1000 * (clocks.realtime = clocks.uptime = 100);
+ bi.updateTimeBasesLocked(true, false, curr, curr); // on battery
+ // App in foreground
+ bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+
+ // Start timer
+ curr = 1000 * (clocks.realtime = clocks.uptime = 151);
+ bi.noteSyncStartLocked(syncName, UID);
+
+ // Stop timer
+ curr = 1000 * (clocks.realtime = clocks.uptime = 161);
+ bi.noteSyncFinishLocked(syncName, UID);
+
+ // Move to background
+ curr = 1000 * (clocks.realtime = clocks.uptime = 202);
+ bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+
+ // Start timer
+ curr = 1000 * (clocks.realtime = clocks.uptime = 254);
+ bi.noteSyncStartLocked(syncName, UID);
+
+ // Off battery
+ curr = 1000 * (clocks.realtime = clocks.uptime = 305);
+ bi.updateTimeBasesLocked(false, false, curr, curr); // off battery
+
+ // Stop timer
+ curr = 1000 * (clocks.realtime = clocks.uptime = 409);
+ bi.noteSyncFinishLocked(syncName, UID);
+
+ // Test
+ curr = 1000 * (clocks.realtime = clocks.uptime = 657);
+ final ArrayMap<String, ? extends BatteryStats.Timer> syncs =
+ bi.getUidStats().get(UID).getSyncStats();
+ assertEquals(1, syncs.size());
+ BatteryStats.Timer timer = syncs.valueAt(0);
+ BatteryStats.Timer bgTimer = timer.getSubTimer();
+ long time = timer.getTotalTimeLocked(curr, STATS_SINCE_CHARGED);
+ int count = timer.getCountLocked(STATS_SINCE_CHARGED);
+ int bgCount = bgTimer.getCountLocked(STATS_SINCE_CHARGED);
+ long bgTime = bgTimer.getTotalTimeLocked(curr, STATS_SINCE_CHARGED);
+ assertEquals((161 - 151 + 305 - 254) * 1000, time);
+ assertEquals(2, count);
+ assertEquals(1, bgCount);
+ assertEquals((305 - 254) * 1000, bgTime);
+
+ // Test that a second sync is separate.
+ curr = 1000 * (clocks.realtime = clocks.uptime = 3000);
+ final String syncName2 = "second_sync";
+ bi.noteSyncStartLocked(syncName2, UID);
+ assertEquals(2, bi.getUidStats().get(UID).getSyncStats().size());
+ bi.noteSyncFinishLocked(syncName2, UID);
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsDualTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsDualTimerTest.java
new file mode 100644
index 0000000..3a5a9f5
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsDualTimerTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.android.internal.os;
+
+import android.os.BatteryStats;
+import android.support.test.filters.SmallTest;
+
+import junit.framework.TestCase;
+
+/**
+ * Test BatteryStatsImpl.DualTimer.
+ */
+public class BatteryStatsDualTimerTest extends TestCase {
+
+ @SmallTest
+ public void testResetDetach() throws Exception {
+ final MockClocks clocks = new MockClocks();
+ clocks.realtime = clocks.uptime = 100;
+
+ final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase();
+ timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime());
+ final BatteryStatsImpl.TimeBase subTimeBase = new BatteryStatsImpl.TimeBase();
+ subTimeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime());
+
+ final BatteryStatsImpl.DualTimer timer = new BatteryStatsImpl.DualTimer(clocks,
+ null, BatteryStats.WAKE_TYPE_PARTIAL, null, timeBase, subTimeBase);
+
+ assertTrue(timeBase.hasObserver(timer));
+ assertFalse(subTimeBase.hasObserver(timer));
+ assertFalse(timeBase.hasObserver(timer.getSubTimer()));
+ assertTrue(subTimeBase.hasObserver(timer.getSubTimer()));
+
+ // Timer is running so resetting it should not remove it from timerbases.
+ clocks.realtime = clocks.uptime = 200;
+ timer.startRunningLocked(clocks.realtime);
+ timer.reset(true);
+ assertTrue(timeBase.hasObserver(timer));
+ assertTrue(subTimeBase.hasObserver(timer.getSubTimer()));
+
+ // Stop timer and ensure that resetting removes it from timebases.
+ clocks.realtime = clocks.uptime = 300;
+ timer.stopRunningLocked(clocks.realtime);
+ timer.reset(true);
+ assertFalse(timeBase.hasObserver(timer));
+ assertFalse(timeBase.hasObserver(timer.getSubTimer()));
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
index 47bc502..af4a6d9 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
@@ -371,4 +371,48 @@
// Test: UID_2 - background count
assertEquals(2, bgTimer2.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
}
+
+ @SmallTest
+ public void testSensorReset() throws Exception {
+ final MockClocks clocks = new MockClocks();
+ MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
+ bi.mForceOnBattery = true;
+ clocks.realtime = 100;
+ clocks.uptime = 100;
+ bi.getOnBatteryTimeBase().setRunning(true, 100_000, 100_000);
+ bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_RECEIVER);
+
+ clocks.realtime += 100;
+ clocks.uptime += 100;
+
+ bi.noteStartSensorLocked(UID, SENSOR_ID);
+
+ clocks.realtime += 100;
+ clocks.uptime += 100;
+
+ // The sensor is started and the timer has been created.
+ final BatteryStats.Uid uid = bi.getUidStats().get(UID);
+ assertNotNull(uid);
+
+ BatteryStats.Uid.Sensor sensor = uid.getSensorStats().get(SENSOR_ID);
+ assertNotNull(sensor);
+ assertNotNull(sensor.getSensorTime());
+ assertNotNull(sensor.getSensorBackgroundTime());
+
+ // Reset the stats. Since the sensor is still running, we should still see the timer
+ bi.getUidStatsLocked(UID).reset();
+
+ sensor = uid.getSensorStats().get(SENSOR_ID);
+ assertNotNull(sensor);
+ assertNotNull(sensor.getSensorTime());
+ assertNotNull(sensor.getSensorBackgroundTime());
+
+ bi.noteStopSensorLocked(UID, SENSOR_ID);
+
+ // Now the sensor timer has stopped so this reset should also take out the sensor.
+ bi.getUidStatsLocked(UID).reset();
+
+ sensor = uid.getSensorStats().get(SENSOR_ID);
+ assertNull(sensor);
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
index 9607a59..57d6934 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -5,6 +5,7 @@
@RunWith(Suite.class)
@Suite.SuiteClasses({
+ BatteryStatsDualTimerTest.class,
BatteryStatsDurationTimerTest.class,
BatteryStatsSamplingTimerTest.class,
BatteryStatsServTest.class,
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 6929fb9..ec653d0 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -257,6 +257,7 @@
<permission name="android.permission.CHANGE_CONFIGURATION"/>
<permission name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST" />
<permission name="android.permission.CHANGE_OVERLAY_PACKAGES"/>
+ <permission name="android.permission.CLEAR_APP_CACHE"/>
<permission name="android.permission.CONNECTIVITY_INTERNAL"/>
<permission name="android.permission.DELETE_CACHE_FILES"/>
<permission name="android.permission.DELETE_PACKAGES"/>
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 3dab1f7..39b0bc7 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -277,6 +277,9 @@
<font weight="400" style="normal">NotoSansCham-Regular.ttf</font>
<font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
</family>
+ <family lang="und-Adlm">
+ <font weight="400" style="normal">NotoSansAdlam-Regular.ttf</font>
+ </family>
<family lang="und-Avst">
<font weight="400" style="normal">NotoSansAvestan-Regular.ttf</font>
</family>
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 7289429..2a2e14b 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -157,10 +157,12 @@
/**
* Specify a bitmap for the canvas to draw into. All canvas state such as
- * layers, filters, and the save/restore stack are reset with the exception
- * of the current matrix and clip stack. Additionally, as a side-effect
+ * layers, filters, and the save/restore stack are reset. Additionally,
* the canvas' target density is updated to match that of the bitmap.
*
+ * Prior to API level {@value Build.VERSION_CODES#O} the current matrix and
+ * clip stack were preserved.
+ *
* @param bitmap Specifies a mutable bitmap for the canvas to draw into.
* @see #setDensity(int)
* @see #getDensity()
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index e61d467..8f78319 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -123,39 +123,11 @@
* and {@link #connect(ColorSpace, ColorSpace)}, are also guaranteed to be
* thread-safe.</p>
*
- * <h3>Visualization and debugging</h3>
- *
- * <p>To visualize and debug color spaces, you can call {@link #createRenderer()}.
- * The {@link Renderer} created by calling this method can be used to compare
- * color spaces and locate specific colors on a CIE 1931 or CIE 1976 UCS
- * chromaticity diagram.</p>
- *
- * <p>The following code snippet shows how to render a bitmap that compares
- * the color gamuts and white points of {@link Named#DCI_P3} and
- * {@link Named#PRO_PHOTO_RGB}:</p>
- *
- * <pre class="prettyprint">
- * Bitmap bitmap = ColorSpace.createRenderer()
- * .size(768)
- * .clip(true)
- * .add(ColorSpace.get(ColorSpace.Named.DCI_P3), 0xffffc845)
- * .add(ColorSpace.get(ColorSpace.Named.PRO_PHOTO_RGB), 0xff097ae9)
- * .render();
- * </pre>
- * <p>
- * <img style="display: block; margin: 0 auto;" src="{@docRoot}reference/android/images/graphics/colorspace_renderer.png" />
- * <figcaption style="text-align: center;">DCI-P3 vs ProPhoto RGB</figcaption>
- * </p>
- *
- * <p>Please refer to the documentation of the {@link Renderer} class for more
- * information about its options and capabilities.</p>
- *
* @see #get(Named)
* @see Named
* @see Model
* @see Connector
* @see Adaptation
- * @see Renderer
*/
@AnyThread
@SuppressWarnings("StaticInitializerReferencesSubClass")
@@ -913,8 +885,32 @@
}
/**
- * Returns the name of this color space. The name is never null
- * and contains always at least 1 character.
+ * <p>Returns the name of this color space. The name is never null
+ * and contains always at least 1 character.</p>
+ *
+ * <p>Color space names are recommended to be unique but are not
+ * guaranteed to be. There is no defined format but the name usually
+ * falls in one of the following categories:</p>
+ * <ul>
+ * <li>Generic names used to identify color spaces in non-RGB
+ * color models. For instance: {@link Named#CIE_LAB Generic L*a*b*}.</li>
+ * <li>Names tied to a particular specification. For instance:
+ * {@link Named#SRGB sRGB IEC61966-2.1} or
+ * {@link Named#ACES SMPTE ST 2065-1:2012 ACES}.</li>
+ * <li>Ad-hoc names, often generated procedurally or by the user
+ * during a calibration workflow. These names often contain the
+ * make and model of the display.</li>
+ * </ul>
+ *
+ * <p>Because the format of color space names is not defined, it is
+ * not recommended to programmatically identify a color space by its
+ * name alone. Names can be used as a first approximation.</p>
+ *
+ * <p>It is however perfectly acceptable to display color space names to
+ * users in a UI, or in debuggers and logs. When displaying a color space
+ * name to the user, it is recommended to add extra information to avoid
+ * ambiguities: color model, a representation of the color space's gamut,
+ * white point, etc.</p>
*
* @return A non-null String of length >= 1
*/
@@ -1417,6 +1413,8 @@
* @return A new non-null {@link Renderer} instance
*
* @see Renderer
+ *
+ * @hide
*/
@NonNull
public static Renderer createRenderer() {
@@ -2105,8 +2103,11 @@
throw new IllegalArgumentException("Parameters cannot be NaN");
}
- if (!(d >= 0.0 && d <= 1.0 + Math.ulp(1.0))) {
- throw new IllegalArgumentException("Parameter d must be in the range [0..1]");
+ // Next representable float after 1.0
+ // We use doubles here but the representation inside our native code is often floats
+ if (!(d >= 0.0 && d <= 1.0f + Math.ulp(1.0f))) {
+ throw new IllegalArgumentException("Parameter d must be in the range [0..1], " +
+ "was " + d);
}
if (d == 0.0 && (a == 0.0 || g == 0.0)) {
@@ -2521,7 +2522,7 @@
x -> Math.pow(x < 0.0 ? 0.0 : x, gamma),
min, max, id);
mTransferParameters = gamma == 1.0 ?
- new TransferParameters(0.0, 0.0, 1.0, 1.0 + Math.ulp(1.0), gamma) :
+ new TransferParameters(0.0, 0.0, 1.0, 1.0 + Math.ulp(1.0f), gamma) :
new TransferParameters(1.0, 0.0, 0.0, 0.0, gamma);
}
@@ -3712,6 +3713,8 @@
* See {@link #add(ColorSpace, float, float, float, int)} for more information.</p>
*
* @see ColorSpace#createRenderer()
+ *
+ * @hide
*/
public static class Renderer {
private static final int NATIVE_SIZE = 1440;
@@ -4054,7 +4057,7 @@
*/
@NonNull
@Size(6)
- private static float[] getPrimaries(@NonNull Rgb rgb,
+ private static void getPrimaries(@NonNull Rgb rgb,
@NonNull @Size(6) float[] primaries, boolean asUcs) {
// TODO: We should find a better way to handle these cases
if (rgb.equals(ColorSpace.get(Named.EXTENDED_SRGB)) ||
@@ -4069,7 +4072,6 @@
rgb.getPrimaries(primaries);
}
if (asUcs) xyYToUv(primaries);
- return primaries;
}
/**
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index 4b1b0c6..d9a77e7 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -52,12 +52,19 @@
mBuilderPtr = nInitBuilder(lang, variant);
}
- public void freeze() {
+ /**
+ * Finalize the FontFamily creation.
+ *
+ * @return boolean returns false if some error happens in native code, e.g. broken font file is
+ * passed, etc.
+ */
+ public boolean freeze() {
if (mBuilderPtr == 0) {
throw new IllegalStateException("This FontFamily is already frozen");
}
mNativePtr = nCreateFamily(mBuilderPtr);
mBuilderPtr = 0;
+ return mNativePtr != 0;
}
public void abortCreation() {
@@ -143,6 +150,25 @@
isItalic);
}
+ /**
+ * Allow creating unsupported FontFamily.
+ *
+ * For compatibility reasons, we still need to create a FontFamily object even if Minikin failed
+ * to find any usable 'cmap' table for some reasons, e.g. broken 'cmap' table, no 'cmap' table
+ * encoded with Unicode code points, etc. Without calling this method, the freeze() method will
+ * return null if Minikin fails to find any usable 'cmap' table. By calling this method, the
+ * freeze() won't fail and will create an empty FontFamily. This empty FontFamily is placed at
+ * the top of the fallback chain but is never used. if we don't create this empty FontFamily
+ * and put it at top, bad things (performance regressions, unexpected glyph selection) will
+ * happen.
+ */
+ public void allowUnsupportedFont() {
+ if (mBuilderPtr == 0) {
+ throw new IllegalStateException("Unable to allow unsupported font.");
+ }
+ nAllowUnsupportedFont(mBuilderPtr);
+ }
+
// TODO: Remove once internal user stop using private API.
private static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex) {
return nAddFont(builderPtr, font, ttcIndex, -1, -1);
@@ -154,6 +180,9 @@
private static native long nCreateFamily(long mBuilderPtr);
@CriticalNative
+ private static native void nAllowUnsupportedFont(long builderPtr);
+
+ @CriticalNative
private static native void nAbort(long mBuilderPtr);
@CriticalNative
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 5afe5e9..56f9cc7 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -33,6 +33,8 @@
import android.graphics.fonts.FontRequest;
import android.graphics.fonts.FontResult;
import android.graphics.fonts.FontVariationAxis;
+import android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
@@ -106,6 +108,7 @@
/**
* Cache for Typeface objects dynamically loaded from assets. Currently max size is 16.
*/
+ @GuardedBy("sLock")
private static final LruCache<String, Typeface> sDynamicTypefaceCache = new LruCache<>(16);
static Typeface sDefaultTypeface;
@@ -127,6 +130,16 @@
public static final int BOLD_ITALIC = 3;
private int mStyle = 0;
+ private int mBaseWeight = 0;
+
+ // Value for weight and italic. Indicates the value is resolved by font metadata.
+ // Must be the same as the C++ constant in core/jni/android/graphics/FontFamily.cpp
+ /** @hide */
+ public static final int RESOLVE_BY_FONT_TABLE = -1;
+
+ // Style value for building typeface.
+ private static final int STYLE_NORMAL = 0;
+ private static final int STYLE_ITALIC = 1;
private int[] mSupportedAxes;
private static final int[] EMPTY_AXES = {};
@@ -160,18 +173,22 @@
if (sFallbackFonts != null) {
synchronized (sDynamicTypefaceCache) {
final String key = Builder.createAssetUid(
- mgr, path, 0 /* ttcIndex */, null /* axes */);
+ mgr, path, 0 /* ttcIndex */, null /* axes */,
+ RESOLVE_BY_FONT_TABLE /* weight */, RESOLVE_BY_FONT_TABLE /* italic */);
Typeface typeface = sDynamicTypefaceCache.get(key);
if (typeface != null) return typeface;
FontFamily fontFamily = new FontFamily();
// TODO: introduce ttc index and variation settings to resource type font.
if (fontFamily.addFontFromAssetManager(mgr, path, cookie, false /* isAsset */,
- 0 /* ttcIndex */, Builder.RESOLVE_BY_FONT_TABLE /* weight */,
- Builder.RESOLVE_BY_FONT_TABLE /* italic */, null /* axes */)) {
- fontFamily.freeze();
+ 0 /* ttcIndex */, RESOLVE_BY_FONT_TABLE /* weight */,
+ RESOLVE_BY_FONT_TABLE /* italic */, null /* axes */)) {
+ if (!fontFamily.freeze()) {
+ return null;
+ }
FontFamily[] families = {fontFamily};
- typeface = createFromFamiliesWithDefault(families);
+ typeface = createFromFamiliesWithDefault(families,
+ RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
sDynamicTypefaceCache.put(key, typeface);
return typeface;
}
@@ -225,18 +242,23 @@
for (final FontFileResourceEntry fontFile : filesEntry.getEntries()) {
if (!fontFamily.addFontFromAssetManager(mgr, fontFile.getFileName(),
0 /* resourceCookie */, false /* isAsset */, 0 /* ttcIndex */,
- fontFile.getWeight(),
- fontFile.isItalic() ? Builder.ITALIC : Builder.NORMAL,
+ fontFile.getWeight(), fontFile.isItalic() ? STYLE_ITALIC : STYLE_NORMAL,
null /* axes */)) {
return null;
}
}
+ // Due to backward compatibility, even if the font is not supported by our font stack,
+ // we need to place the empty font at the first place. The typeface with empty font
+ // behaves different from default typeface especially in fallback font selection.
+ fontFamily.allowUnsupportedFont();
fontFamily.freeze();
FontFamily[] familyChain = { fontFamily };
- typeface = createFromFamiliesWithDefault(familyChain);
+ typeface = createFromFamiliesWithDefault(familyChain,
+ RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
synchronized (sDynamicTypefaceCache) {
final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */,
- null /* axes */);
+ null /* axes */, RESOLVE_BY_FONT_TABLE /* weight */,
+ RESOLVE_BY_FONT_TABLE /* italic */);
sDynamicTypefaceCache.put(key, typeface);
}
return typeface;
@@ -250,7 +272,8 @@
*/
public static Typeface findFromCache(AssetManager mgr, String path) {
synchronized (sDynamicTypefaceCache) {
- final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */, null /* axes */);
+ final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */, null /* axes */,
+ RESOLVE_BY_FONT_TABLE /* weight */, RESOLVE_BY_FONT_TABLE /* italic */);
Typeface typeface = sDynamicTypefaceCache.get(key);
if (typeface != null) {
return typeface;
@@ -282,6 +305,7 @@
* request. May not be null.
* @param callback A callback that will be triggered when results are obtained. May not be null.
*/
+ @Deprecated
public static void create(@NonNull FontRequest request, @NonNull FontRequestCallback callback) {
// Check the cache first
// TODO: would the developer want to avoid a cache hit and always ask for the freshest
@@ -358,7 +382,7 @@
ByteBuffer fontBuffer = fileChannel.map(
FileChannel.MapMode.READ_ONLY, 0, fontSize);
int weight = result.getWeight();
- int italic = result.getItalic() ? Builder.ITALIC : Builder.NORMAL;
+ int italic = result.getItalic() ? STYLE_ITALIC : STYLE_NORMAL;
FontVariationAxis[] axes = null;
try {
axes = FontVariationAxis.fromFontVariationSettings(
@@ -382,8 +406,14 @@
IoUtils.closeQuietly(fd);
}
}
- fontFamily.freeze();
- Typeface typeface = Typeface.createFromFamiliesWithDefault(new FontFamily[] { fontFamily });
+ if (!fontFamily.freeze()) {
+ callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR);
+ return;
+ }
+ Typeface typeface = Typeface.createFromFamiliesWithDefault(
+ new FontFamily[] { fontFamily },
+ RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
synchronized (sDynamicTypefaceCache) {
String key = createProviderUid(request.getProviderAuthority(), request.getQuery());
sDynamicTypefaceCache.put(key, typeface);
@@ -394,6 +424,7 @@
/**
* Interface used to receive asynchronously fetched typefaces.
*/
+ @Deprecated
public interface FontRequestCallback {
/**
* Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
@@ -468,55 +499,42 @@
/**
* A builder class for creating new Typeface instance.
*
+ * <p>
* Examples,
* 1) Create Typeface from ttf file.
* <pre>
* <code>
- * Typeface.Builder buidler = new Typeface.Builder.obtain();
- * builder.setSourceFromFilePath("your_font_file.ttf");
+ * Typeface.Builder buidler = new Typeface.Builder("your_font_file.ttf");
* Typeface typeface = builder.build();
- * builder.recycle();
* </code>
* </pre>
*
* 2) Create Typeface from ttc file in assets directory.
* <pre>
* <code>
- * Typeface.Builder buidler = new Typeface.Builder.obtain();
- * builder.setSourceFromAsset(getAssets(), "your_font_file.ttc");
- * builder.setTtcIndex(2); // set index of font collection.
+ * Typeface.Builder buidler = new Typeface.Builder(getAssets(), "your_font_file.ttc");
+ * builder.setTtcIndex(2); // Set index of font collection.
* Typeface typeface = builder.build();
- * builder.recycle();
* </code>
* </pre>
*
- * 3) Create Typeface from existing Typeface with variation settings.
+ * 3) Create Typeface with variation settings.
* <pre>
- *
- * <p>Note that only one source can be specified for the single Typeface.</p>
+ * <code>
+ * Typeface.Builder buidler = new Typeface.Builder("your_font_file.ttf");
+ * builder.setFontVariationSettings("'wght' 700, 'slnt' 20, 'ital' 1");
+ * builder.setWeight(700); // Tell the system that this is a bold font.
+ * builder.setItalic(true); // Tell the system that this is an italic style font.
+ * Typeface typeface = builder.build();
+ * </code>
+ * </pre>
+ * </p>
*/
public static final class Builder {
- /**
- * Value for weight and italic.
- *
- * Indicates the value is resolved by font metadata.
- */
- // Must be same with C++ constant in core/jni/android/graphics/FontFamily.cpp
- public static final int RESOLVE_BY_FONT_TABLE = -1;
-
- /**
- * Value for italic.
- *
- * Indicates the font style is not italic.
- */
- public static final int NORMAL = 0;
-
- /**
- * Value for italic.
- *
- * Indicates the font style is italic.
- */
- public static final int ITALIC = 1;
+ /** @hide */
+ public static final int NORMAL_WEIGHT = 400;
+ /** @hide */
+ public static final int BOLD_WEIGHT = 700;
private int mTtcIndex;
private FontVariationAxis[] mAxes;
@@ -524,134 +542,80 @@
private AssetManager mAssetManager;
private String mPath;
private FileDescriptor mFd;
- private @IntRange(from = -1) int mWeight = RESOLVE_BY_FONT_TABLE;
- /** @hide */
- @Retention(SOURCE)
- @IntDef({RESOLVE_BY_FONT_TABLE, NORMAL, ITALIC})
- public @interface Italic {}
- private @Italic int mItalic = RESOLVE_BY_FONT_TABLE;
+ private FontsContract.FontInfo[] mFonts;
+ private Map<Uri, ByteBuffer> mFontBuffers;
- private boolean mHasSourceSet = false;
- private boolean mRecycled = false;
+ private String mFallbackFamilyName;
- /** Use Builder.obtain() instead */
- private void Builder() {}
-
- private static AtomicReference<Builder> mCache = new AtomicReference<>();
+ private int mWeight = RESOLVE_BY_FONT_TABLE;
+ private int mItalic = RESOLVE_BY_FONT_TABLE;
/**
- * Returns Typeface.Builder from pool.
- */
- public static Builder obtain() {
- final Builder builder = mCache.getAndSet(null);
- if (builder != null) {
- builder.mRecycled = false;
- return builder;
- }
- return new Builder();
- }
-
- /**
- * Resets the internal states.
- */
- public void reset() {
- checkNotRecycled();
- mTtcIndex = 0;
- mAxes = null;
-
- mAssetManager = null;
- mPath = null;
- mFd = null;
-
- mWeight = RESOLVE_BY_FONT_TABLE;
- mItalic = RESOLVE_BY_FONT_TABLE;
-
- mHasSourceSet = false;
- }
-
- /**
- * Returns the instance to the pool.
- */
- public void recycle() {
- reset();
- mRecycled = true;
-
- mCache.compareAndSet(null, this);
- }
-
- private void checkNotRecycled() {
- if (mRecycled) {
- throw new IllegalStateException("Don't use Builder after calling recycle()");
- }
- }
-
- private void checkSingleFontSource() {
- if (mHasSourceSet) {
- throw new IllegalStateException("Typeface can only built with single font source.");
- }
- }
-
- /**
- * Sets a font file as a source of Typeface.
+ * Constructs a builder with a file path.
*
* @param path The file object refers to the font file.
*/
- public Builder setSourceFromFile(@NonNull File path) {
- return setSourceFromFilePath(path.getAbsolutePath());
+ public Builder(@NonNull File path) {
+ mPath = path.getAbsolutePath();
}
/**
- * Sets a font file as a source of Typeface.
+ * Constructs a builder with a file descriptor.
*
* @param fd The file descriptor. The passed fd must be mmap-able.
*/
- public Builder setSourceFromFile(@NonNull FileDescriptor fd) {
- checkNotRecycled();
- checkSingleFontSource();
+ public Builder(@NonNull FileDescriptor fd) {
mFd = fd;
- mHasSourceSet = true;
- return this;
}
/**
- * Sets a font file as a source of Typeface.
+ * Constructs a builder with a file path.
*
* @param path The full path to the font file.
*/
- public Builder setSourceFromFilePath(@NonNull String path) {
- checkNotRecycled();
- checkSingleFontSource();
+ public Builder(@NonNull String path) {
mPath = path;
- mHasSourceSet = true;
- return this;
}
/**
- * Sets an asset entry as a source of Typeface.
+ * Constructs a builder from an asset manager and a file path in an asset directory.
*
* @param assetManager The application's asset manager
* @param path The file name of the font data in the asset directory
*/
- public Builder setSourceFromAsset(@NonNull AssetManager assetManager,
- @NonNull String path) {
- checkNotRecycled();
- checkSingleFontSource();
+ public Builder(@NonNull AssetManager assetManager, @NonNull String path) {
mAssetManager = Preconditions.checkNotNull(assetManager);
mPath = Preconditions.checkStringNotEmpty(path);
- mHasSourceSet = true;
- return this;
+ }
+
+ /**
+ * Constracts a builder from an array of FontsContract.FontInfo.
+ *
+ * Since {@link FontsContract.FontInfo} holds information about TTC indices and
+ * variation settings, there is no need to call {@link #setTtcIndex} or
+ * {@link #setFontVariationSettings}. Similary, {@link FontsContract.FontInfo} holds
+ * weight and italic information, so {@link #setWeight} and {@link #setItalic} are used
+ * for style matching during font selection.
+ *
+ * @param results The array of {@link FontsContract.FontInfo}
+ * @param buffers The mapping from URI to buffers to be used during building.
+ * @hide
+ */
+ public Builder(@NonNull FontsContract.FontInfo[] fonts,
+ @NonNull Map<Uri, ByteBuffer> buffers) {
+ mFonts = fonts;
+ mFontBuffers = buffers;
}
/**
* Sets weight of the font.
*
- * By passing {@link #RESOLVE_BY_FONT_TABLE}, weight value is resolved by OS/2 table in
- * font file if possible.
- * @param weight a weight value or {@link #RESOLVE_BY_FONT_TABLE}
+ * Tells the system the weight of the given font. If not provided, the system will resolve
+ * the weight value by reading font tables.
+ * @param weight a weight value.
*/
- public Builder setWeight(@IntRange(from = -1) int weight) {
- checkNotRecycled();
+ public Builder setWeight(@IntRange(from = 1, to = 1000) int weight) {
mWeight = weight;
return this;
}
@@ -659,26 +623,27 @@
/**
* Sets italic information of the font.
*
- * By passing {@link #RESOLVE_BY_FONT_TABLE}, italic or normal is determined by OS/2 table
- * in font file if possible.
- * @param italic One of {@link #NORMAL}, {@link #ITALIC}, {@link #RESOLVE_BY_FONT_TABLE}.
- * will be used.
+ * Tells the system the style of the given font. If not provided, the system will resolve
+ * the style by reading font tables.
+ * @param italic {@code true} if the font is italic. Otherwise {@code false}.
*/
- public Builder setItalic(@Italic int italic) {
- checkNotRecycled();
- mItalic = italic;
+ public Builder setItalic(boolean italic) {
+ mItalic = italic ? STYLE_ITALIC : STYLE_NORMAL;
return this;
}
/**
- * Sets an idex of the font collection.
+ * Sets an index of the font collection.
*
* Can not be used for Typeface source. build() method will return null for invalid index.
* @param ttcIndex An index of the font collection. If the font source is not font
* collection, do not call this method or specify 0.
*/
public Builder setTtcIndex(@IntRange(from = 0) int ttcIndex) {
- checkNotRecycled();
+ if (mFonts != null) {
+ throw new IllegalArgumentException(
+ "TTC index can not be specified for FontResult source.");
+ }
mTtcIndex = ttcIndex;
return this;
}
@@ -687,12 +652,15 @@
* Sets a font variation settings.
*
* @param variationSettings See {@link android.widget.TextView#setFontVariationSettings}.
- * @throws FontVariationAxis.InvalidFormatException If given string is not a valid font
- * variation settings format.
+ * @throws InvalidFormatException If given string is not a valid font variation settings
+ * format.
*/
public Builder setFontVariationSettings(@Nullable String variationSettings)
- throws FontVariationAxis.InvalidFormatException {
- checkNotRecycled();
+ throws InvalidFormatException {
+ if (mFonts != null) {
+ throw new IllegalArgumentException(
+ "Font variation settings can not be specified for FontResult source.");
+ }
if (mAxes != null) {
throw new IllegalStateException("Font variation settings are already set.");
}
@@ -706,7 +674,10 @@
* @param axes An array of font variation axis tag-value pairs.
*/
public Builder setFontVariationSettings(@Nullable FontVariationAxis[] axes) {
- checkNotRecycled();
+ if (mFonts != null) {
+ throw new IllegalArgumentException(
+ "Font variation settings can not be specified for FontResult source.");
+ }
if (mAxes != null) {
throw new IllegalStateException("Font variation settings are already set.");
}
@@ -715,6 +686,33 @@
}
/**
+ * Sets a fallback family name.
+ *
+ * By specifying a fallback family name, a fallback Typeface will be returned if the
+ * {@link #build} method fails to create a Typeface from the provided font. The fallback
+ * family will be resolved with the provided weight and italic information specified by
+ * {@link #setWeight} and {@link #setItalic}.
+ *
+ * If {@link #setWeight} is not called, the fallback family keeps the default weight.
+ * Similary, if {@link #setItalic} is not called, the fallback family keeps the default
+ * italic information. For example, calling {@code builder.setFallback("sans-serif-light")}
+ * is equivalent to calling {@code builder.setFallback("sans-serif").setWeight(300)} in
+ * terms of fallback. The default weight and italic information are overridden by calling
+ * {@link #setWeight} and {@link #setItalic}. For example, if a Typeface is constructed
+ * using {@code builder.setFallback("sans-serif-light").setWeight(700)}, the fallback text
+ * will render as sans serif bold.
+ *
+ * @param familyName A family name to be used for fallback if the provided font can not be
+ * used. By passing {@code null}, build() returns {@code null}.
+ * If {@link #setFallback} is not called on the builder, {@code null}
+ * is assumed.
+ */
+ public Builder setFallback(@Nullable String familyName) {
+ mFallbackFamilyName = familyName;
+ return this;
+ }
+
+ /**
* Creates a unique id for a given AssetManager and asset path.
*
* @param mgr AssetManager instance
@@ -724,7 +722,7 @@
* @return Unique id for a given AssetManager and asset path.
*/
private static String createAssetUid(final AssetManager mgr, String path, int ttcIndex,
- @Nullable FontVariationAxis[] axes) {
+ @Nullable FontVariationAxis[] axes, int weight, int italic) {
final SparseArray<String> pkgs = mgr.getAssignedPackageIdentifiers();
final StringBuilder builder = new StringBuilder();
final int size = pkgs.size();
@@ -736,6 +734,10 @@
builder.append("-");
builder.append(Integer.toString(ttcIndex));
builder.append("-");
+ builder.append(Integer.toString(weight));
+ builder.append("-");
+ builder.append(Integer.toString(italic));
+ builder.append("-");
if (axes != null) {
for (FontVariationAxis axis : axes) {
builder.append(axis.getTag());
@@ -746,18 +748,61 @@
return builder.toString();
}
+ private static final Object sLock = new Object();
+ // TODO: Unify with Typeface.sTypefaceCache.
+ @GuardedBy("sLock")
+ private static final LongSparseArray<SparseArray<Typeface>> sTypefaceCache =
+ new LongSparseArray<>(3);
+
+ private Typeface resolveFallbackTypeface() {
+ if (mFallbackFamilyName == null) {
+ return null;
+ }
+
+ Typeface base = sSystemFontMap.get(mFallbackFamilyName);
+ if (base == null) {
+ base = sDefaultTypeface;
+ }
+
+ if (mWeight == RESOLVE_BY_FONT_TABLE && mItalic == RESOLVE_BY_FONT_TABLE) {
+ return base;
+ }
+
+ final int weight = (mWeight == RESOLVE_BY_FONT_TABLE) ? base.mBaseWeight : mWeight;
+ final boolean italic =
+ (mItalic == RESOLVE_BY_FONT_TABLE) ? (base.mStyle & ITALIC) != 0 : mItalic == 1;
+ final int key = weight << 1 | (italic ? 1 : 0);
+
+ Typeface typeface;
+ synchronized(sLock) {
+ SparseArray<Typeface> innerCache = sTypefaceCache.get(base.native_instance);
+ if (innerCache != null) {
+ typeface = innerCache.get(key);
+ if (typeface != null) {
+ return typeface;
+ }
+ }
+
+ typeface = new Typeface(
+ nativeCreateFromTypefaceWithExactStyle(
+ base.native_instance, weight, italic));
+
+ if (innerCache == null) {
+ innerCache = new SparseArray<>(4); // [regular, bold] x [upright, italic]
+ sTypefaceCache.put(base.native_instance, innerCache);
+ }
+ innerCache.put(key, typeface);
+ }
+ return typeface;
+ }
+
/**
* Generates new Typeface from specified configuration.
*
* @return Newly created Typeface. May return null if some parameters are invalid.
*/
public Typeface build() {
- checkNotRecycled();
- if (!mHasSourceSet) {
- return null;
- }
-
- if (mFd != null) { // set source by setSourceFromFile(FileDescriptor)
+ if (mFd != null) { // Builder is created with file descriptor.
try (FileInputStream fis = new FileInputStream(mFd)) {
FileChannel channel = fis.getChannel();
long size = channel.size();
@@ -766,43 +811,77 @@
final FontFamily fontFamily = new FontFamily();
if (!fontFamily.addFontFromBuffer(buffer, mTtcIndex, mAxes, mWeight, mItalic)) {
fontFamily.abortCreation();
- return null;
+ return resolveFallbackTypeface();
}
- fontFamily.freeze();
+ if (!fontFamily.freeze()) {
+ return resolveFallbackTypeface();
+ }
FontFamily[] families = { fontFamily };
- return createFromFamiliesWithDefault(families);
+ return createFromFamiliesWithDefault(families, mWeight, mItalic);
} catch (IOException e) {
- return null;
+ return resolveFallbackTypeface();
}
- } else if (mAssetManager != null) { // set source by setSourceFromAsset()
- final String key = createAssetUid(mAssetManager, mPath, mTtcIndex, mAxes);
- synchronized (sDynamicTypefaceCache) {
+ } else if (mAssetManager != null) { // Builder is created with asset manager.
+ final String key = createAssetUid(
+ mAssetManager, mPath, mTtcIndex, mAxes, mWeight, mItalic);
+ synchronized (sLock) {
Typeface typeface = sDynamicTypefaceCache.get(key);
if (typeface != null) return typeface;
final FontFamily fontFamily = new FontFamily();
if (!fontFamily.addFontFromAssetManager(mAssetManager, mPath, mTtcIndex,
true /* isAsset */, mTtcIndex, mWeight, mItalic, mAxes)) {
fontFamily.abortCreation();
- return null;
+ return resolveFallbackTypeface();
}
- fontFamily.freeze();
+ if (!fontFamily.freeze()) {
+ return resolveFallbackTypeface();
+ }
FontFamily[] families = { fontFamily };
- typeface = createFromFamiliesWithDefault(families);
+ typeface = createFromFamiliesWithDefault(families, mWeight, mItalic);
sDynamicTypefaceCache.put(key, typeface);
return typeface;
}
- } else if (mPath != null) { // set source by setSourceFromFile(File)
+ } else if (mPath != null) { // Builder is created with file path.
final FontFamily fontFamily = new FontFamily();
if (!fontFamily.addFont(mPath, mTtcIndex, mAxes, mWeight, mItalic)) {
fontFamily.abortCreation();
+ return resolveFallbackTypeface();
+ }
+ if (!fontFamily.freeze()) {
+ return resolveFallbackTypeface();
+ }
+ FontFamily[] families = { fontFamily };
+ return createFromFamiliesWithDefault(families, mWeight, mItalic);
+ } else if (mFonts != null) {
+ final FontFamily fontFamily = new FontFamily();
+ boolean atLeastOneFont = false;
+ for (FontsContract.FontInfo font : mFonts) {
+ final ByteBuffer fontBuffer = mFontBuffers.get(font.getUri());
+ if (fontBuffer == null) {
+ continue; // skip
+ }
+ final boolean success = fontFamily.addFontFromBuffer(fontBuffer,
+ font.getTtcIndex(), font.getAxes(), font.getWeight(),
+ font.isItalic() ? STYLE_ITALIC : STYLE_NORMAL);
+ if (!success) {
+ fontFamily.abortCreation();
+ return null;
+ }
+ atLeastOneFont = true;
+ }
+ if (!atLeastOneFont) {
+ // No fonts are avaialble. No need to create new Typeface and returns fallback
+ // Typeface instead.
+ fontFamily.abortCreation();
return null;
}
fontFamily.freeze();
FontFamily[] families = { fontFamily };
- return createFromFamiliesWithDefault(families);
- } else {
- throw new IllegalArgumentException("No source was set.");
+ return createFromFamiliesWithDefault(families, mWeight, mItalic);
}
+
+ // Must not reach here.
+ throw new IllegalArgumentException("No source was set.");
}
}
@@ -897,18 +976,35 @@
throw new NullPointerException(); // for backward compatibility
}
if (sFallbackFonts != null) {
- final Builder builder = Builder.obtain();
- try {
- builder.setSourceFromAsset(mgr, path);
- Typeface typeface = builder.build();
- if (typeface != null) {
+ synchronized (sLock) {
+ Typeface typeface = new Builder(mgr, path).build();
+ if (typeface != null) return typeface;
+
+ final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */,
+ null /* axes */, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
+ typeface = sDynamicTypefaceCache.get(key);
+ if (typeface != null) return typeface;
+
+ final FontFamily fontFamily = new FontFamily();
+ if (fontFamily.addFontFromAssetManager(mgr, path, 0, true /* isAsset */,
+ 0 /* ttc index */, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE,
+ null /* axes */)) {
+ // Due to backward compatibility, even if the font is not supported by our font
+ // stack, we need to place the empty font at the first place. The typeface with
+ // empty font behaves different from default typeface especially in fallback
+ // font selection.
+ fontFamily.allowUnsupportedFont();
+ fontFamily.freeze();
+ final FontFamily[] families = { fontFamily };
+ typeface = createFromFamiliesWithDefault(families, RESOLVE_BY_FONT_TABLE,
+ RESOLVE_BY_FONT_TABLE);
+ sDynamicTypefaceCache.put(key, typeface);
return typeface;
+ } else {
+ fontFamily.abortCreation();
}
- } finally {
- builder.recycle();
}
}
- // For the compatibility reasons, throw runtime exception if failed to create Typeface.
throw new RuntimeException("Font asset not found " + path);
}
@@ -943,23 +1039,21 @@
* @return The new typeface.
*/
public static Typeface createFromFile(@Nullable String path) {
- if (path == null) {
- // For the compatibility reasons, need to throw NPE if the argument is null.
- // See android.graphics.cts.TypefaceTest#testCreateFromFileByFileNameNull
- throw new NullPointerException();
- }
if (sFallbackFonts != null) {
- final Builder builder = Builder.obtain();
- try {
- builder.setSourceFromFilePath(path);
- Typeface typeface = builder.build();
- if (typeface != null) {
- // For the compatibility reasons, throw runtime exception if failed to create
- // Typeface.
- return typeface;
- }
- } finally {
- builder.recycle();
+ final FontFamily fontFamily = new FontFamily();
+ if (fontFamily.addFont(path, 0 /* ttcIndex */, null /* axes */,
+ RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE)) {
+ // Due to backward compatibility, even if the font is not supported by our font
+ // stack, we need to place the empty font at the first place. The typeface with
+ // empty font behaves different from default typeface especially in fallback font
+ // selection.
+ fontFamily.allowUnsupportedFont();
+ fontFamily.freeze();
+ FontFamily[] families = { fontFamily };
+ return createFromFamiliesWithDefault(families, RESOLVE_BY_FONT_TABLE,
+ RESOLVE_BY_FONT_TABLE);
+ } else {
+ fontFamily.abortCreation();
}
}
throw new RuntimeException("Font not found " + path);
@@ -975,16 +1069,25 @@
for (int i = 0; i < families.length; i++) {
ptrArray[i] = families[i].mNativePtr;
}
- return new Typeface(nativeCreateFromArray(ptrArray));
+ return new Typeface(nativeCreateFromArray(
+ ptrArray, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
}
/**
* Create a new typeface from an array of font families, including
* also the font families in the fallback list.
- *
+ * @param weight the weight for this family. {@link RESOLVE_BY_FONT_TABLE} can be used. In that
+ * case, the table information in the first family's font is used. If the first
+ * family has multiple fonts, the closest to the regular weight and upright font
+ * is used.
+ * @param italic the italic information for this family. {@link RESOLVE_BY_FONT_TABLE} can be
+ * used. In that case, the table information in the first family's font is used.
+ * If the first family has multiple fonts, the closest to the regular weight and
+ * upright font is used.
* @param families array of font families
*/
- private static Typeface createFromFamiliesWithDefault(FontFamily[] families) {
+ private static Typeface createFromFamiliesWithDefault(FontFamily[] families,
+ int weight, int italic) {
long[] ptrArray = new long[families.length + sFallbackFonts.length];
for (int i = 0; i < families.length; i++) {
ptrArray[i] = families[i].mNativePtr;
@@ -992,7 +1095,7 @@
for (int i = 0; i < sFallbackFonts.length; i++) {
ptrArray[i + families.length] = sFallbackFonts[i].mNativePtr;
}
- return new Typeface(nativeCreateFromArray(ptrArray));
+ return new Typeface(nativeCreateFromArray(ptrArray, weight, italic));
}
// don't allow clients to call this directly
@@ -1003,6 +1106,7 @@
native_instance = ni;
mStyle = nativeGetStyle(ni);
+ mBaseWeight = nativeGetBaseWeight(ni);
}
private static FontFamily makeFamilyFromParsed(FontConfig.Family family,
@@ -1023,11 +1127,15 @@
}
}
if (!fontFamily.addFontFromBuffer(fontBuffer, font.getTtcIndex(), font.getAxes(),
- font.getWeight(), font.isItalic() ? Builder.ITALIC : Builder.NORMAL)) {
+ font.getWeight(), font.isItalic() ? STYLE_ITALIC : STYLE_NORMAL)) {
Log.e(TAG, "Error creating font " + fullPathName + "#" + font.getTtcIndex());
}
}
- fontFamily.freeze();
+ if (!fontFamily.freeze()) {
+ // Treat as system error since reaching here means that a system pre-installed font
+ // can't be used by our font stack.
+ Log.e(TAG, "Unable to load Family: " + family.getName() + ":" + family.getLanguage());
+ }
return fontFamily;
}
@@ -1070,7 +1178,8 @@
} else {
FontFamily fontFamily = makeFamilyFromParsed(f, bufferForPath);
FontFamily[] families = { fontFamily };
- typeface = Typeface.createFromFamiliesWithDefault(families);
+ typeface = Typeface.createFromFamiliesWithDefault(families,
+ RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
}
systemFonts.put(f.getName(), typeface);
}
@@ -1168,13 +1277,16 @@
}
private static native long nativeCreateFromTypeface(long native_instance, int style);
+ private static native long nativeCreateFromTypefaceWithExactStyle(
+ long native_instance, int weight, boolean italic);
// TODO: clean up: change List<FontVariationAxis> to FontVariationAxis[]
private static native long nativeCreateFromTypefaceWithVariation(
long native_instance, List<FontVariationAxis> axes);
private static native long nativeCreateWeightAlias(long native_instance, int weight);
private static native void nativeUnref(long native_instance);
private static native int nativeGetStyle(long native_instance);
- private static native long nativeCreateFromArray(long[] familyArray);
+ private static native int nativeGetBaseWeight(long native_instance);
+ private static native long nativeCreateFromArray(long[] familyArray, int weight, int italic);
private static native void nativeSetDefault(long native_instance);
private static native int[] nativeGetSupportedAxes(long native_instance);
}
diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
index 643c0da..283a3e2 100644
--- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
+++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
@@ -29,6 +29,7 @@
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Outline;
@@ -51,12 +52,27 @@
import java.io.IOException;
/**
- * This drawable supports two layers: foreground and background.
- *
- * <p>The layers are clipped when rendering using the mask path defined in the device configuration.
- *
* <p>This class can also be created via XML inflation using <code><adaptive-icon></code> tag
* in addition to dynamic creation.
+ *
+ * <p>This drawable supports two drawable layers: foreground and background. The layers are clipped
+ * when rendering using the mask defined in the device configuration.
+ *
+ * <ul>
+ * <li>Both foreground and background layers should be sized at 108 x 108 dp.</li>
+ * <li>The inner 72 x 72 dp of the icon appears within the masked viewport.</li>
+ * <li>The outer 18 dp on each of the 4 sides of the layers is reserved for use by the system UI
+ * surfaces to create interesting visual effects, such as parallax or pulsing.</li>
+ * </ul>
+ *
+ * Such motion effect is achieved by internally setting the bounds of the foreground and
+ * background layer as following:
+ * <pre>
+ * Rect(getBounds().left - getBounds().getWidth() * #getExtraInsetFraction(),
+ * getBounds().top - getBounds().getHeight() * #getExtraInsetFraction(),
+ * getBounds().right + getBounds().getWidth() * #getExtraInsetFraction(),
+ * getBounds().bottom + getBounds().getHeight() * #getExtraInsetFraction())
+ * </pre>
*/
public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback {
@@ -65,7 +81,11 @@
* @hide
*/
public static final float MASK_SIZE = 100f;
- private static final float SAFEZONE_SCALE = .9f;
+
+ /**
+ * Launcher icons design guideline
+ */
+ private static final float SAFEZONE_SCALE = 72f/66f;
/**
* All four sides of the layers are padded with extra inset so as to provide
@@ -80,7 +100,7 @@
private static final float DEFAULT_VIEW_PORT_SCALE = 1f / (1 + 2 * EXTRA_INSET_PERCENTAGE);
/**
- * Clip path defined in {@link com.android.internal.R.string.config_icon_mask}.
+ * Clip path defined in R.string.config_icon_mask.
*/
private static Path sMask;
@@ -134,9 +154,10 @@
if (sMask == null) {
sMask = PathParser.createPathFromPathData(
- Resources.getSystem().getString(com.android.internal.R.string.config_icon_mask));
+ Resources.getSystem().getString(R.string.config_icon_mask));
}
- mMask = new Path();
+ mMask = PathParser.createPathFromPathData(
+ Resources.getSystem().getString(R.string.config_icon_mask));
mMaskMatrix = new Matrix();
mCanvas = new Canvas();
mTransparentRegion = new Region();
@@ -212,13 +233,24 @@
* All four sides of the layers are padded with extra inset so as to provide
* extra content to reveal within the clip path when performing affine transformations on the
* layers.
+ *
+ * @see #getForeground() and #getBackground() for more info on how this value is used
+ */
+ public static float getExtraInsetFraction() {
+ return EXTRA_INSET_PERCENTAGE;
+ }
+
+ /**
+ * @hide
*/
public static float getExtraInsetPercentage() {
return EXTRA_INSET_PERCENTAGE;
}
/**
- * Only call this method after bound is set on this drawable.
+ * When called before the bound is set, the returned path is identical to
+ * R.string.config_icon_mask. After the bound is set, the
+ * returned path's computed bound is same as the #getBounds().
*
* @return the mask path object used to clip the drawable
*/
@@ -227,6 +259,10 @@
}
/**
+ * Returns the foreground drawable managed by this class. The bound of this drawable is
+ * extended by {@link #getExtraInsetFraction()} * getBounds().width on left/right sides and by
+ * {@link #getExtraInsetFraction()} * getBounds().height on top/bottom sides.
+ *
* @return the foreground drawable managed by this drawable
*/
public Drawable getForeground() {
@@ -234,6 +270,10 @@
}
/**
+ * Returns the foreground drawable managed by this class. The bound of this drawable is
+ * extended by {@link #getExtraInsetFraction()} * getBounds().width on left/right sides and by
+ * {@link #getExtraInsetFraction()} * getBounds().height on top/bottom sides.
+ *
* @return the background drawable managed by this drawable
*/
public Drawable getBackground() {
@@ -293,10 +333,15 @@
mMaskBitmap = Bitmap.createBitmap(b.width(), b.height(), Bitmap.Config.ALPHA_8);
mLayersBitmap = Bitmap.createBitmap(b.width(), b.height(), Bitmap.Config.ARGB_8888);
}
+ // mMaskBitmap bound [0, w] x [0, h]
mCanvas.setBitmap(mMaskBitmap);
mPaint.setShader(null);
mCanvas.drawPath(mMask, mPaint);
+ // mMask bound [left, top, right, bottom]
+ mMaskMatrix.postTranslate(b.left, b.top);
+ mMask.reset();
+ sMask.transform(mMaskMatrix, mMask);
// reset everything that depends on the view bounds
mTransparentRegion.setEmpty();
mLayersShader = null;
@@ -309,6 +354,7 @@
}
if (mLayersShader == null) {
mCanvas.setBitmap(mLayersBitmap);
+ mCanvas.drawColor(Color.BLACK);
for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
if (mLayerState.mChildren[i] == null) {
continue;
@@ -728,6 +774,12 @@
return mLayerState.isStateful();
}
+ /** @hide */
+ @Override
+ public boolean hasFocusStateSpecified() {
+ return mLayerState.hasFocusStateSpecified();
+ }
+
@Override
protected boolean onStateChange(int[] state) {
boolean changed = false;
@@ -1035,6 +1087,17 @@
return isStateful;
}
+ public final boolean hasFocusStateSpecified() {
+ final ChildDrawable[] array = mChildren;
+ for (int i = 0; i < N_CHILDREN; i++) {
+ final Drawable dr = array[i].mDrawable;
+ if (dr != null && dr.hasFocusStateSpecified()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public final boolean canConstantState() {
final ChildDrawable[] array = mChildren;
for (int i = 0; i < N_CHILDREN; i++) {
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 6deeb0d..5004667 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -737,6 +737,12 @@
|| super.isStateful();
}
+ /** @hide */
+ @Override
+ public boolean hasFocusStateSpecified() {
+ return mBitmapState.mTint != null && mBitmapState.mTint.hasFocusStateSpecified();
+ }
+
@Override
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index 7524cac..559e3d3 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -207,6 +207,12 @@
return mColorState.mTint != null && mColorState.mTint.isStateful();
}
+ /** @hide */
+ @Override
+ public boolean hasFocusStateSpecified() {
+ return mColorState.mTint != null && mColorState.mTint.hasFocusStateSpecified();
+ }
+
@Override
public int getOpacity() {
if (mTintFilter != null || mPaint.getColorFilter() != null) {
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 850f40e..44fb1c7 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -26,6 +26,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
@@ -713,6 +714,25 @@
}
/**
+ * Indicates whether this drawable has at least one state spec explicitly
+ * specifying {@link android.R.attr#state_focused}.
+ *
+ * <p>Note: A View uses a {@link Drawable} instance as its background and it
+ * changes its appearance based on a state. On keyboard devices, it should
+ * specify its {@link android.R.attr#state_focused} to make sure the user
+ * knows which view is holding the focus.</p>
+ *
+ * @return {@code true} if {@link android.R.attr#state_focused} is specified
+ * for this drawable.
+ *
+ * @hide
+ */
+ @TestApi
+ public boolean hasFocusStateSpecified() {
+ return false;
+ }
+
+ /**
* Specify a set of states for the drawable. These are use-case specific,
* so see the relevant documentation. As an example, the background for
* widgets like Button understand the following states:
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index a491d7e..aa4cd9c 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -242,6 +242,18 @@
return mDrawableContainerState.isStateful();
}
+ /** @hide */
+ @Override
+ public boolean hasFocusStateSpecified() {
+ if (mCurrDrawable != null) {
+ return mCurrDrawable.hasFocusStateSpecified();
+ }
+ if (mLastDrawable != null) {
+ return mLastDrawable.hasFocusStateSpecified();
+ }
+ return false;
+ }
+
@Override
public void setAutoMirrored(boolean mirrored) {
if (mDrawableContainerState.mAutoMirrored != mirrored) {
diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java
index 5887939..431b63b 100644
--- a/graphics/java/android/graphics/drawable/DrawableWrapper.java
+++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java
@@ -323,6 +323,12 @@
return mDrawable != null && mDrawable.isStateful();
}
+ /** @hide */
+ @Override
+ public boolean hasFocusStateSpecified() {
+ return mDrawable != null && mDrawable.hasFocusStateSpecified();
+ }
+
@Override
protected boolean onStateChange(int[] state) {
if (mDrawable != null && mDrawable.isStateful()) {
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 7aad7df..6c3aea2 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -987,6 +987,15 @@
|| (s.mTint != null && s.mTint.isStateful());
}
+ /** @hide */
+ @Override
+ public boolean hasFocusStateSpecified() {
+ final GradientState s = mGradientState;
+ return (s.mSolidColors != null && s.mSolidColors.hasFocusStateSpecified())
+ || (s.mStrokeColors != null && s.mStrokeColors.hasFocusStateSpecified())
+ || (s.mTint != null && s.mTint.hasFocusStateSpecified());
+ }
+
@Override
public @Config int getChangingConfigurations() {
return super.getChangingConfigurations() | mGradientState.getChangingConfigurations();
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index b159f0f..4725c2c 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -1476,6 +1476,12 @@
return mLayerState.isStateful();
}
+ /** @hide */
+ @Override
+ public boolean hasFocusStateSpecified() {
+ return mLayerState.hasFocusStateSpecified();
+ }
+
@Override
protected boolean onStateChange(int[] state) {
boolean changed = false;
@@ -2117,6 +2123,18 @@
return isStateful;
}
+ public final boolean hasFocusStateSpecified() {
+ final int N = mNumChildren;
+ final ChildDrawable[] array = mChildren;
+ for (int i = 0; i < N; i++) {
+ final Drawable dr = array[i].mDrawable;
+ if (dr != null && dr.hasFocusStateSpecified()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public final boolean canConstantState() {
final ChildDrawable[] array = mChildren;
final int N = mNumChildren;
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index c7183d9..1790020 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -574,6 +574,12 @@
return super.isStateful() || (s.mTint != null && s.mTint.isStateful());
}
+ /** @hide */
+ @Override
+ public boolean hasFocusStateSpecified() {
+ return mNinePatchState.mTint != null && mNinePatchState.mTint.hasFocusStateSpecified();
+ }
+
final static class NinePatchState extends ConstantState {
@Config int mChangingConfigurations;
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index f83c160..bfd0604 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -377,6 +377,12 @@
return true;
}
+ /** @hide */
+ @Override
+ public boolean hasFocusStateSpecified() {
+ return true;
+ }
+
/**
* Sets the ripple color.
*
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 6758607..34da928 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -17,6 +17,8 @@
package android.graphics.drawable;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
@@ -32,6 +34,7 @@
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.Shader;
+import android.graphics.Xfermode;
import android.graphics.drawable.shapes.Shape;
import android.util.AttributeSet;
@@ -306,6 +309,16 @@
invalidateSelf();
}
+ /**
+ * @hide
+ */
+ @Override
+ @TestApi
+ public void setXfermode(@Nullable Xfermode mode) {
+ mShapeState.mPaint.setXfermode(mode);
+ invalidateSelf();
+ }
+
@Override
public int getOpacity() {
if (mShapeState.mShape == null) {
@@ -352,6 +365,12 @@
return super.isStateful() || (s.mTint != null && s.mTint.isStateful());
}
+ /** @hide */
+ @Override
+ public boolean hasFocusStateSpecified() {
+ return mShapeState.mTint != null && mShapeState.mTint.hasFocusStateSpecified();
+ }
+
/**
* Subclasses override this to parse custom subelements. If you handle it,
* return true, else return <em>super.inflateTag(...)</em>.
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index 64a9eb5..c98f160 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -90,6 +90,12 @@
return true;
}
+ /** @hide */
+ @Override
+ public boolean hasFocusStateSpecified() {
+ return mStateListState.hasFocusStateSpecified();
+ }
+
@Override
protected boolean onStateChange(int[] stateSet) {
final boolean changed = super.onStateChange(stateSet);
@@ -342,6 +348,10 @@
return -1;
}
+ boolean hasFocusStateSpecified() {
+ return StateSet.containsAttribute(mStateSets, R.attr.state_focused);
+ }
+
@Override
public Drawable newDrawable() {
return new StateListDrawable(this, null);
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index a1539b8..41e5af1 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -413,6 +413,12 @@
return super.isStateful() || (mVectorState != null && mVectorState.isStateful());
}
+ /** @hide */
+ @Override
+ public boolean hasFocusStateSpecified() {
+ return mVectorState != null && mVectorState.hasFocusStateSpecified();
+ }
+
@Override
protected boolean onStateChange(int[] stateSet) {
boolean changed = false;
@@ -976,6 +982,11 @@
|| (mRootGroup != null && mRootGroup.isStateful());
}
+ public boolean hasFocusStateSpecified() {
+ return mTint != null && mTint.hasFocusStateSpecified()
+ || (mRootGroup != null && mRootGroup.hasFocusStateSpecified());
+ }
+
void setViewportSize(float viewportWidth, float viewportHeight) {
mViewportWidth = viewportWidth;
mViewportHeight = viewportHeight;
@@ -1326,6 +1337,21 @@
}
@Override
+ public boolean hasFocusStateSpecified() {
+ boolean result = false;
+
+ final ArrayList<VObject> children = mChildren;
+ for (int i = 0, count = children.size(); i < count; i++) {
+ final VObject child = children.get(i);
+ if (child.isStateful()) {
+ result |= child.hasFocusStateSpecified();
+ }
+ }
+
+ return result;
+ }
+
+ @Override
int getNativeSize() {
// Return the native allocation needed for the subtree.
int size = NATIVE_ALLOCATION_SIZE;
@@ -1569,6 +1595,11 @@
}
@Override
+ public boolean hasFocusStateSpecified() {
+ return false;
+ }
+
+ @Override
int getNativeSize() {
return NATIVE_ALLOCATION_SIZE;
}
@@ -1819,6 +1850,14 @@
}
@Override
+ public boolean hasFocusStateSpecified() {
+ return (mStrokeColors != null && mStrokeColors instanceof ColorStateList &&
+ ((ColorStateList) mStrokeColors).hasFocusStateSpecified()) &&
+ (mFillColors != null && mFillColors instanceof ColorStateList &&
+ ((ColorStateList) mFillColors).hasFocusStateSpecified());
+ }
+
+ @Override
int getNativeSize() {
return NATIVE_ALLOCATION_SIZE;
}
@@ -2116,6 +2155,7 @@
abstract void applyTheme(Theme t);
abstract boolean onStateChange(int[] state);
abstract boolean isStateful();
+ abstract boolean hasFocusStateSpecified();
abstract int getNativeSize();
abstract Property getProperty(String propertyName);
}
diff --git a/graphics/java/android/graphics/fonts/FontVariationAxis.java b/graphics/java/android/graphics/fonts/FontVariationAxis.java
index 91ec0e8..fb2a3a8 100644
--- a/graphics/java/android/graphics/fonts/FontVariationAxis.java
+++ b/graphics/java/android/graphics/fonts/FontVariationAxis.java
@@ -18,8 +18,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
import android.text.TextUtils;
import java.util.ArrayList;
@@ -28,7 +26,7 @@
/**
* Class that holds information about single font variation axis.
*/
-public final class FontVariationAxis implements Parcelable {
+public final class FontVariationAxis {
private final int mTag;
private final String mTagString;
private final float mStyleValue;
@@ -74,39 +72,6 @@
}
/**
- * @hide
- */
- public FontVariationAxis(Parcel in) {
- mTag = in.readInt();
- mTagString = in.readString();
- mStyleValue = in.readFloat();
- }
-
- @Override
- public void writeToParcel(Parcel out, int flag) {
- out.writeInt(mTag);
- out.writeString(mTagString);
- out.writeFloat(mStyleValue);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Creator<FontVariationAxis> CREATOR = new Creator<FontVariationAxis>() {
- @Override
- public FontVariationAxis createFromParcel(Parcel in) {
- return new FontVariationAxis(in);
- }
-
- @Override
- public FontVariationAxis[] newArray(int size) {
- return new FontVariationAxis[size];
- }
- };
-
- /**
* Returns a valid font variation setting string for this object.
*/
@Override
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 9f649ea..d95acff 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -23,6 +23,7 @@
#include "hwui/MinikinUtils.h"
#include "pipeline/skia/AnimatedDrawables.h"
+#include <SkCanvasStateUtils.h>
#include <SkColorSpaceXformCanvas.h>
#include <SkDrawable.h>
#include <SkDeque.h>
@@ -59,7 +60,8 @@
SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) {
sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
- mCanvasOwned = std::unique_ptr<SkCanvas>(new SkCanvas(bitmap));
+ mCanvasOwned =
+ std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
mCanvasWrapper = SkCreateColorSpaceXformCanvas(mCanvasOwned.get(),
cs == nullptr ? SkColorSpace::MakeSRGB() : std::move(cs));
mCanvas = mCanvasWrapper.get();
@@ -80,38 +82,13 @@
// Canvas state operations: Replace Bitmap
// ----------------------------------------------------------------------------
-class ClipCopier : public SkCanvas::ClipVisitor {
-public:
- explicit ClipCopier(SkCanvas* dstCanvas) : m_dstCanvas(dstCanvas) {}
-
- virtual void clipRect(const SkRect& rect, SkClipOp op, bool antialias) {
- m_dstCanvas->clipRect(rect, op, antialias);
- }
- virtual void clipRRect(const SkRRect& rrect, SkClipOp op, bool antialias) {
- m_dstCanvas->clipRRect(rrect, op, antialias);
- }
- virtual void clipPath(const SkPath& path, SkClipOp op, bool antialias) {
- m_dstCanvas->clipPath(path, op, antialias);
- }
-
-private:
- SkCanvas* m_dstCanvas;
-};
-
void SkiaCanvas::setBitmap(const SkBitmap& bitmap) {
sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
- std::unique_ptr<SkCanvas> newCanvas = std::unique_ptr<SkCanvas>(new SkCanvas(bitmap));
+ std::unique_ptr<SkCanvas> newCanvas =
+ std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
std::unique_ptr<SkCanvas> newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(),
cs == nullptr ? SkColorSpace::MakeSRGB() : std::move(cs));
- if (!bitmap.isNull()) {
- // Copy the canvas matrix & clip state.
- newCanvasWrapper->setMatrix(mCanvas->getTotalMatrix());
-
- ClipCopier copier(newCanvasWrapper.get());
- mCanvas->replayClips(&copier);
- }
-
// deletes the previously owned canvas (if any)
mCanvasOwned = std::move(newCanvas);
mCanvasWrapper = std::move(newCanvasWrapper);
@@ -437,6 +414,30 @@
}
// ----------------------------------------------------------------------------
+// Canvas state operations: Capture
+// ----------------------------------------------------------------------------
+
+SkCanvasState* SkiaCanvas::captureCanvasState() const {
+ SkCanvas* canvas = mCanvas;
+ if (mCanvasOwned) {
+ // Important to use the underlying SkCanvas, not the wrapper.
+ canvas = mCanvasOwned.get();
+ }
+
+ // Workarounds for http://crbug.com/271096: SW draw only supports
+ // translate & scale transforms, and a simple rectangular clip.
+ // (This also avoids significant wasted time in calling
+ // SkCanvasStateUtils::CaptureCanvasState when the clip is complex).
+ if (!canvas->isClipRect() ||
+ (canvas->getTotalMatrix().getType() &
+ ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))) {
+ return nullptr;
+ }
+
+ return SkCanvasStateUtils::CaptureCanvasState(canvas);
+}
+
+// ----------------------------------------------------------------------------
// Canvas draw operations
// ----------------------------------------------------------------------------
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index 13f979cf..aeecafa 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -102,6 +102,8 @@
virtual SkDrawFilter* getDrawFilter() override;
virtual void setDrawFilter(SkDrawFilter* drawFilter) override;
+ virtual SkCanvasState* captureCanvasState() const override;
+
virtual void drawColor(int color, SkBlendMode mode) override;
virtual void drawPaint(const SkPaint& paint) override;
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index ed32832..86af678 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -27,6 +27,8 @@
#include <SkCanvas.h>
#include <SkMatrix.h>
+class SkCanvasState;
+
namespace minikin {
class Layout;
}
@@ -200,6 +202,9 @@
virtual SkDrawFilter* getDrawFilter() = 0;
virtual void setDrawFilter(SkDrawFilter* drawFilter) = 0;
+ // WebView only
+ virtual SkCanvasState* captureCanvasState() const { return nullptr; }
+
// ----------------------------------------------------------------------------
// Canvas draw operations
// ----------------------------------------------------------------------------
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index 4b8575a..4fb4b53 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -39,14 +39,22 @@
namespace android {
-// Resolve the 1..9 weight based on base weight and bold flag
+// This indicates that the passed information should be resolved by OS/2 table.
+// This value must be the same as the android.graphics.Typeface$Builder.RESOLVE_BY_FONT_TABLE.
+constexpr int RESOLVE_BY_FONT_TABLE = -1;
+
+// Resolve the 1..10 weight based on base weight and bold flag
static void resolveStyle(Typeface* typeface) {
- int weight = typeface->fBaseWeight / 100;
+ // TODO: Better to use raw base weight value for font selection instead of dividing by 100.
+ int weight = (typeface->fBaseWeight + 50) / 100;
if (typeface->fSkiaStyle & SkTypeface::kBold) {
weight += 3;
}
- if (weight > 9) {
- weight = 9;
+ if (weight > 10) {
+ weight = 10;
+ }
+ if (weight < 1) {
+ weight = 1;
}
bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0;
typeface->fStyle = minikin::FontStyle(weight, italic);
@@ -71,6 +79,18 @@
return result;
}
+Typeface* Typeface::createFromTypefaceWithStyle(Typeface* base, int weight, bool italic) {
+ Typeface* resolvedFace = Typeface::resolveDefault(base);
+ Typeface* result = new Typeface();
+ if (result != nullptr) {
+ result->fFontCollection = resolvedFace->fFontCollection;
+ result->fBaseWeight = weight;
+ result->fStyle = minikin::FontStyle(weight / 100, italic);
+ result->fSkiaStyle = resolvedFace->fSkiaStyle;
+ }
+ return result;
+}
+
Typeface* Typeface::createFromTypefaceWithVariation(Typeface* src,
const std::vector<minikin::FontVariation>& variations) {
Typeface* resolvedFace = Typeface::resolveDefault(src);
@@ -103,26 +123,50 @@
}
Typeface* Typeface::createFromFamilies(
- std::vector<std::shared_ptr<minikin::FontFamily>>&& families) {
+ std::vector<std::shared_ptr<minikin::FontFamily>>&& families,
+ int weight, int italic) {
Typeface* result = new Typeface;
result->fFontCollection.reset(new minikin::FontCollection(families));
- if (families.empty()) {
- ALOGW("createFromFamilies creating empty collection");
- result->fSkiaStyle = SkTypeface::kNormal;
- } else {
+
+ if (weight == RESOLVE_BY_FONT_TABLE || italic == RESOLVE_BY_FONT_TABLE) {
+ int weightFromFont;
+ bool italicFromFont;
+
const minikin::FontStyle defaultStyle;
- const std::shared_ptr<minikin::FontFamily>& firstFamily = families[0];
- const minikin::MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font;
+ const minikin::MinikinFont* mf =
+ families.empty() ? nullptr : families[0]->getClosestMatch(defaultStyle).font;
if (mf != nullptr) {
SkTypeface* skTypeface = reinterpret_cast<const MinikinFontSkia*>(mf)->GetSkTypeface();
- // TODO: probably better to query more precise style from family, will be important
- // when we open up API to access 100..900 weights
- result->fSkiaStyle = skTypeface->style();
+ const SkFontStyle& style = skTypeface->fontStyle();
+ weightFromFont = style.weight();
+ italicFromFont = style.slant() != SkFontStyle::kUpright_Slant;
} else {
- result->fSkiaStyle = SkTypeface::kNormal;
+ // We can't obtain any information from fonts. Just use default values.
+ weightFromFont = SkFontStyle::kNormal_Weight;
+ italicFromFont = false;
+ }
+
+ if (weight == RESOLVE_BY_FONT_TABLE) {
+ weight = weightFromFont;
+ }
+ if (italic == RESOLVE_BY_FONT_TABLE) {
+ italic = italicFromFont? 1 : 0;
}
}
- result->fBaseWeight = 400;
+
+ // Sanitize the invalid value passed from public API.
+ if (weight < 0) {
+ weight = SkFontStyle::kNormal_Weight;
+ }
+
+ result->fBaseWeight = weight;
+ // This bold detection comes from SkTypefae.h
+ const bool isBold = weight >= SkFontStyle::kSemiBold_Weight;
+ const bool isItalic = italic == 1;
+ // TODO: remove fSkiaStyle
+ result->fSkiaStyle = isBold ?
+ (isItalic ? SkTypeface::kBoldItalic : SkTypeface::kBold) :
+ (isItalic ? SkTypeface::kItalic : SkTypeface::kNormal);
resolveStyle(result);
return result;
}
@@ -153,7 +197,7 @@
Typeface* hwTypeface = new Typeface();
hwTypeface->fFontCollection = collection;
hwTypeface->fSkiaStyle = SkTypeface::kNormal;
- hwTypeface->fBaseWeight = 400;
+ hwTypeface->fBaseWeight = SkFontStyle::kSemiBold_Weight;
hwTypeface->fStyle = minikin::FontStyle(4 /* weight */, false /* italic */);
Typeface::setDefault(hwTypeface);
diff --git a/libs/hwui/hwui/Typeface.h b/libs/hwui/hwui/Typeface.h
index 19a4f6c5..e35a7b4 100644
--- a/libs/hwui/hwui/Typeface.h
+++ b/libs/hwui/hwui/Typeface.h
@@ -42,13 +42,16 @@
static Typeface* createFromTypeface(Typeface* src, SkTypeface::Style style);
+ static Typeface* createFromTypefaceWithStyle(Typeface* base, int weight, bool italic);
+
static Typeface* createFromTypefaceWithVariation(Typeface* src,
const std::vector<minikin::FontVariation>& variations);
static Typeface* createWeightAlias(Typeface* src, int baseweight);
static Typeface* createFromFamilies(
- std::vector<std::shared_ptr<minikin::FontFamily>>&& families);
+ std::vector<std::shared_ptr<minikin::FontFamily>>&& families,
+ int weight, int italic);
static void setDefault(Typeface* face);
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index d26eb59..68a0869 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -190,9 +190,32 @@
}
const Vector3 lightPos = SkiaPipeline::getLightCenter();
SkPoint3 skiaLightPos = SkPoint3::Make(lightPos.x, lightPos.y, lightPos.z);
- SkShadowUtils::DrawShadow(canvas, *casterPath, casterZValue, skiaLightPos,
+ if (shadowMatrix.hasPerspective() || revealClipPath || clippedToBounds) {
+ std::function<SkScalar(SkScalar, SkScalar)> casterHeightFunc;
+ if (shadowMatrix.hasPerspective()) {
+ // get the matrix with the full 3D transform
+ mat4 zMatrix;
+ caster->getRenderNode()->applyViewPropertyTransforms(zMatrix, true);
+ SkScalar A = zMatrix[2];
+ SkScalar B = zMatrix[6];
+ SkScalar C = zMatrix[mat4::kTranslateZ];
+ casterHeightFunc = [A, B, C](SkScalar x, SkScalar y) {
+ return A*x + B*y + C; // casterZValue already baked into C
+ };
+ } else {
+ casterHeightFunc = [casterZValue] (SkScalar, SkScalar) {
+ return casterZValue;
+ };
+ }
+
+ SkShadowUtils::DrawUncachedShadow(canvas, *casterPath, casterHeightFunc, skiaLightPos,
SkiaPipeline::getLightRadius(), ambientAlpha, spotAlpha, SK_ColorBLACK,
casterAlpha < 1.0f ? SkShadowFlags::kTransparentOccluder_ShadowFlag : 0);
+ } else {
+ SkShadowUtils::DrawShadow(canvas, *casterPath, casterZValue, skiaLightPos,
+ SkiaPipeline::getLightRadius(), ambientAlpha, spotAlpha, SK_ColorBLACK,
+ casterAlpha < 1.0f ? SkShadowFlags::kTransparentOccluder_ShadowFlag : 0);
+ }
}
}; // namespace skiapipeline
diff --git a/libs/hwui/tests/unit/SkiaCanvasTests.cpp b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
index 44476af..0aecb85 100644
--- a/libs/hwui/tests/unit/SkiaCanvasTests.cpp
+++ b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
@@ -19,6 +19,7 @@
#include <gtest/gtest.h>
#include <RecordingCanvas.h>
#include <SkBlurDrawLooper.h>
+#include <SkCanvasStateUtils.h>
#include <SkPicture.h>
#include <SkPictureRecorder.h>
@@ -103,14 +104,20 @@
skBitmap.lockPixels();
ASSERT_EQ(0xFF0000FF, *skBitmap.getAddr32(0, 0));
+ // Create a software canvas with an Adobe color space.
+ SkiaCanvas adobeSkCanvas(adobeSkBitmap);
+ adobeSkCanvas.drawBitmap(*bitmap, 0, 0, nullptr);
+ // The result should be less than fully red, since we convert to Adobe RGB at draw time.
+ ASSERT_EQ(0xFF0000DC, *adobeSkBitmap.getAddr32(0, 0));
+
// Now try in kDefer mode. This is a little strange given that, in practice, all software
// canvases are kImmediate.
SkCanvas skCanvas(skBitmap);
SkiaCanvas deferCanvas(&skCanvas, Canvas::XformToSRGB::kDefer);
deferCanvas.drawBitmap(*adobeBitmap, 0, 0, nullptr);
- // The result should be as initialized, since we deferred the conversion to sRGB.
+ // The result should be as before, since we deferred the conversion to sRGB.
skBitmap.lockPixels();
- ASSERT_EQ(0xFF0000F0, *skBitmap.getAddr32(0, 0));
+ ASSERT_EQ(0xFF0000DC, *skBitmap.getAddr32(0, 0));
// Test picture recording. We will kDefer the xform at recording time, but handle it when
// we playback to the software canvas.
@@ -120,11 +127,40 @@
picCanvas.drawBitmap(*adobeBitmap, 0, 0, nullptr);
sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
- // Playback to a deferred canvas. The result should be as initialized.
+ // Playback to a deferred canvas. The result should be as before.
deferCanvas.asSkCanvas()->drawPicture(picture);
- ASSERT_EQ(0xFF0000F0, *skBitmap.getAddr32(0, 0));
+ ASSERT_EQ(0xFF0000DC, *skBitmap.getAddr32(0, 0));
// Playback to an immediate canvas. The result should be fully red.
canvas.asSkCanvas()->drawPicture(picture);
ASSERT_EQ(0xFF0000FF, *skBitmap.getAddr32(0, 0));
}
+
+TEST(SkiaCanvas, captureCanvasState) {
+ // Create a software canvas.
+ SkImageInfo info = SkImageInfo::Make(1, 1, kN32_SkColorType, kOpaque_SkAlphaType);
+ sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(info);
+ SkBitmap skBitmap;
+ bitmap->getSkBitmap(&skBitmap);
+ skBitmap.eraseColor(0);
+ SkiaCanvas canvas(skBitmap);
+
+ // Translate, then capture and verify the CanvasState.
+ canvas.translate(1.0f, 1.0f);
+ SkCanvasState* state = canvas.captureCanvasState();
+ ASSERT_NE(state, nullptr);
+ std::unique_ptr<SkCanvas> newCanvas = SkCanvasStateUtils::MakeFromCanvasState(state);
+ ASSERT_NE(newCanvas.get(), nullptr);
+ newCanvas->translate(-1.0f, -1.0f);
+ ASSERT_TRUE(newCanvas->getTotalMatrix().isIdentity());
+ SkCanvasStateUtils::ReleaseCanvasState(state);
+
+ // Create a picture canvas.
+ SkPictureRecorder recorder;
+ SkCanvas* skPicCanvas = recorder.beginRecording(1, 1, NULL, 0);
+ SkiaCanvas picCanvas(skPicCanvas, Canvas::XformToSRGB::kDefer);
+ state = picCanvas.captureCanvasState();
+
+ // Verify that we cannot get the CanvasState.
+ ASSERT_EQ(state, nullptr);
+}
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index aac9727..de85c16 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -670,6 +670,8 @@
* related to L5 will be filled.
*
* <p>The value is only available if {@link #hasCarrierFrequencyHz()} is {@code true}.
+ *
+ * @return the carrier frequency of the signal tracked in Hz.
*/
public float getCarrierFrequencyHz() {
return mCarrierFrequencyHz;
@@ -888,10 +890,10 @@
}
/**
- * Returns {@code true} if {@link #getAutomaticGainControlLevelInDb()} is available,
+ * Returns {@code true} if {@link #getAutomaticGainControlLevelDb()} is available,
* {@code false} otherwise.
*/
- public boolean hasAutomaticGainControlLevelInDb() {
+ public boolean hasAutomaticGainControlLevelDb() {
return isFlagSet(HAS_AUTOMATIC_GAIN_CONTROL);
}
@@ -908,9 +910,9 @@
* components) may also affect the typical output of of this value on any given hardware design
* in an open sky test - the important aspect of this output is that changes in this value are
* indicative of changes on input signal power in the frequency band for this measurement.
- * <p>The value is only available if {@link #hasAutomaticGainControlLevelInDb()} is {@code true}
+ * <p>The value is only available if {@link #hasAutomaticGainControlLevelDb()} is {@code true}
*/
- public double getAutomaticGainControlLevelInDb() {
+ public double getAutomaticGainControlLevelDb() {
return mAutomaticGainControlLevelInDb;
}
@@ -1064,7 +1066,7 @@
builder.append(String.format(
format,
"AgcLevelDb",
- hasAutomaticGainControlLevelInDb() ? mAutomaticGainControlLevelInDb : null));
+ hasAutomaticGainControlLevelDb() ? mAutomaticGainControlLevelInDb : null));
return builder.toString();
}
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index e90a174..a44bc5b 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -224,7 +224,7 @@
*
* @param satIndex the index of the satellite in the list.
*/
- public boolean hasCarrierFrequency(int satIndex) {
+ public boolean hasCarrierFrequencyHz(int satIndex) {
return (mSvidWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_CARRIER_FREQUENCY) != 0;
}
@@ -239,7 +239,11 @@
* will be reported for this same satellite, in one all the values related to L1 will be filled,
* and in the other all of the values related to L5 will be filled.
*
- * <p>The value is only available if {@link #hasCarrierFrequency(int satIndex)} is {@code true}.
+ * <p>The value is only available if {@link #hasCarrierFrequencyHz(int satIndex)} is {@code true}.
+ *
+ * @param satIndex the index of the satellite in the list.
+ *
+ * @return the carrier frequency of the signal tracked in Hz.
*/
public float getCarrierFrequencyHz(int satIndex) {
return mCarrierFrequencies[satIndex];
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 4c39c30..6bc5e91 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -242,8 +242,7 @@
}
public boolean getInEmergency() {
- boolean isInEmergencyCallback = Boolean.parseBoolean(
- SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE));
+ boolean isInEmergencyCallback = mTelephonyManager.getEmergencyCallbackMode();
return mIsInEmergency || isInEmergencyCallback;
}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 7f5d3a0..bf5939f 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -2523,8 +2523,11 @@
mAvSyncHeader = ByteBuffer.allocate(16);
mAvSyncHeader.order(ByteOrder.BIG_ENDIAN);
mAvSyncHeader.putInt(0x55550001);
- mAvSyncHeader.putInt(sizeInBytes);
- mAvSyncHeader.putLong(timestamp);
+ }
+
+ if (mAvSyncBytesRemaining == 0) {
+ mAvSyncHeader.putInt(4, sizeInBytes);
+ mAvSyncHeader.putLong(8, timestamp);
mAvSyncHeader.position(0);
mAvSyncBytesRemaining = sizeInBytes;
}
@@ -2556,9 +2559,6 @@
}
mAvSyncBytesRemaining -= ret;
- if (mAvSyncBytesRemaining == 0) {
- mAvSyncHeader = null;
- }
return ret;
}
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index ed71849..06555c1 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -17,6 +17,8 @@
package android.media;
import android.graphics.ImageFormat;
+import android.graphics.PixelFormat;
+import android.hardware.HardwareBuffer;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -72,6 +74,12 @@
private static final int ACQUIRE_MAX_IMAGES = 2;
/**
+ * Invalid consumer buffer usage flag. This usage flag will be ignored
+ * by the {@code ImageReader} instance is constructed with this value.
+ */
+ private static final long BUFFER_USAGE_UNKNOWN = 0;
+
+ /**
* <p>
* Create a new reader for images of the desired size and format.
* </p>
@@ -121,13 +129,104 @@
* @see Image
*/
public static ImageReader newInstance(int width, int height, int format, int maxImages) {
- return new ImageReader(width, height, format, maxImages);
+ return new ImageReader(width, height, format, maxImages, BUFFER_USAGE_UNKNOWN);
+ }
+
+ /**
+ * <p>
+ * Create a new reader for images of the desired size, format and consumer usage flag.
+ * </p>
+ * <p>
+ * The {@code maxImages} parameter determines the maximum number of {@link Image} objects that
+ * can be be acquired from the {@code ImageReader} simultaneously. Requesting more buffers will
+ * use up more memory, so it is important to use only the minimum number necessary for the use
+ * case.
+ * </p>
+ * <p>
+ * The valid sizes and formats depend on the source of the image data.
+ * </p>
+ * <p>
+ * The format and usage flag combination describes how the buffer will be used by
+ * consumer end-points. For example, if the application intends to send the images to
+ * {@link android.media.MediaCodec} or {@link android.media.MediaRecorder} for hardware video
+ * encoding, the format and usage flag combination needs to be
+ * {@link ImageFormat#PRIVATE PRIVATE} and {@link HardwareBuffer#USAGE0_VIDEO_ENCODE}. When an
+ * {@link ImageReader} object is created with a valid size and such format/usage flag
+ * combination, the application can send the {@link Image images} to an {@link ImageWriter} that
+ * is created with the input {@link android.view.Surface} provided by the
+ * {@link android.media.MediaCodec} or {@link android.media.MediaRecorder}.
+ * </p>
+ * <p>
+ * If the {@code format} is {@link ImageFormat#PRIVATE PRIVATE}, the created {@link ImageReader}
+ * will produce images that are not directly accessible by the application. The application can
+ * still acquire images from this {@link ImageReader}, and send them to the
+ * {@link android.hardware.camera2.CameraDevice camera} for reprocessing, or to the
+ * {@link android.media.MediaCodec} / {@link android.media.MediaRecorder} for hardware video
+ * encoding via {@link ImageWriter} interface. However, the {@link Image#getPlanes()
+ * getPlanes()} will return an empty array for {@link ImageFormat#PRIVATE PRIVATE} format
+ * images. The application can check if an existing reader's format by calling
+ * {@link #getImageFormat()}.
+ * </p>
+ * <p>
+ * {@link ImageFormat#PRIVATE PRIVATE} format {@link ImageReader ImageReaders} are more
+ * efficient to use when application access to image data is not necessary, compared to
+ * ImageReaders using other format such as {@link ImageFormat#YUV_420_888 YUV_420_888}.
+ * </p>
+ * <p>
+ * Note that not all format and usage flag combination is supported by the
+ * {@link ImageReader}. Below are the supported combinations by the {@link ImageReader}
+ * (assuming the consumer end-points support the such image consumption, e.g., hardware video
+ * encoding).
+ * <table>
+ * <tr>
+ * <th>Format</th>
+ * <th>Compatible usage flags</th>
+ * </tr>
+ * <tr>
+ * <td>non-{@link android.graphics.ImageFormat#PRIVATE PRIVATE} formats defined by
+ * {@link android.graphics.ImageFormat ImageFormat} or
+ * {@link android.graphics.PixelFormat PixelFormat}</td>
+ * <td>{@link HardwareBuffer#USAGE0_CPU_READ} or
+ * {@link HardwareBuffer#USAGE0_CPU_READ_OFTEN}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link android.graphics.ImageFormat#PRIVATE}</td>
+ * <td>{@link HardwareBuffer#USAGE0_VIDEO_ENCODE} or
+ * {@link HardwareBuffer#USAGE0_GPU_SAMPLED_IMAGE}, or combined</td>
+ * </tr>
+ * </table>
+ * Using other combinations may result in {@link IllegalArgumentException}.
+ * </p>
+ * @param width The default width in pixels of the Images that this reader will produce.
+ * @param height The default height in pixels of the Images that this reader will produce.
+ * @param format The format of the Image that this reader will produce. This must be one of the
+ * {@link android.graphics.ImageFormat} or {@link android.graphics.PixelFormat}
+ * constants. Note that not all formats are supported, like ImageFormat.NV21.
+ * @param maxImages The maximum number of images the user will want to access simultaneously.
+ * This should be as small as possible to limit memory use. Once maxImages Images are
+ * obtained by the user, one of them has to be released before a new Image will
+ * become available for access through {@link #acquireLatestImage()} or
+ * {@link #acquireNextImage()}. Must be greater than 0.
+ * @param usage The intended usage of the images produced by this ImageReader. It needs
+ * to be one of the Usage0 defined by {@link HardwareBuffer}, or an
+ * {@link IllegalArgumentException} will be thrown.
+ * @see Image
+ * @see HardwareBuffer
+ * @hide
+ */
+ public static ImageReader newInstance(int width, int height, int format, int maxImages,
+ long usage) {
+ if (!isFormatUsageCombinationAllowed(format, usage)) {
+ throw new IllegalArgumentException("Format usage combination is not supported:"
+ + " format = " + format + ", usage = " + usage);
+ }
+ return new ImageReader(width, height, format, maxImages, usage);
}
/**
* @hide
*/
- protected ImageReader(int width, int height, int format, int maxImages) {
+ protected ImageReader(int width, int height, int format, int maxImages, long usage) {
mWidth = width;
mHeight = height;
mFormat = format;
@@ -149,7 +248,7 @@
mNumPlanes = ImageUtils.getNumPlanesForFormat(mFormat);
- nativeInit(new WeakReference<ImageReader>(this), width, height, format, maxImages);
+ nativeInit(new WeakReference<>(this), width, height, format, maxImages, usage);
mSurface = nativeGetSurface();
@@ -617,6 +716,30 @@
return si.getReader() == this;
}
+ private static boolean isFormatUsageCombinationAllowed(int format, long usage) {
+ if (!ImageFormat.isPublicFormat(format) && !PixelFormat.isPublicFormat(format)) {
+ return false;
+ }
+
+ // Valid usage needs to be provided.
+ if (usage == BUFFER_USAGE_UNKNOWN) {
+ return false;
+ }
+
+ if (format == ImageFormat.PRIVATE) {
+ // Usage need to be either USAGE0_GPU_SAMPLED_IMAGE or USAGE0_VIDEO_ENCODE or combined.
+ boolean isAllowed = (usage == HardwareBuffer.USAGE0_GPU_SAMPLED_IMAGE);
+ isAllowed = isAllowed || (usage == HardwareBuffer.USAGE0_VIDEO_ENCODE);
+ isAllowed = isAllowed || (usage ==
+ (HardwareBuffer.USAGE0_VIDEO_ENCODE | HardwareBuffer.USAGE0_GPU_SAMPLED_IMAGE));
+ return isAllowed;
+ } else {
+ // Usage need to make the buffer CPU readable for explicit format.
+ return ((usage == HardwareBuffer.USAGE0_CPU_READ) ||
+ (usage == HardwareBuffer.USAGE0_CPU_READ_OFTEN));
+ }
+ }
+
/**
* Called from Native code when an Event happens.
*
@@ -655,7 +778,7 @@
private ListenerHandler mListenerHandler;
// Keep track of the successfully acquired Images. This need to be thread safe as the images
// could be closed by different threads (e.g., application thread and GC thread).
- private List<Image> mAcquiredImages = new CopyOnWriteArrayList<Image>();
+ private List<Image> mAcquiredImages = new CopyOnWriteArrayList<>();
/**
* This field is used by native code, do not access or modify.
@@ -896,7 +1019,7 @@
}
private synchronized native void nativeInit(Object weakSelf, int w, int h,
- int fmt, int maxImgs);
+ int fmt, int maxImgs, long consumerUsage);
private synchronized native void nativeClose();
private synchronized native void nativeReleaseImage(Image i);
private synchronized native Surface nativeGetSurface();
diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java
index b142ddd..349c9cb 100644
--- a/media/java/android/media/ImageWriter.java
+++ b/media/java/android/media/ImageWriter.java
@@ -17,6 +17,7 @@
package android.media;
import android.graphics.ImageFormat;
+import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.camera2.utils.SurfaceUtils;
import android.os.Handler;
@@ -89,7 +90,7 @@
private final int mMaxImages;
// Keep track of the currently dequeued Image. This need to be thread safe as the images
// could be closed by different threads (e.g., application thread and GC thread).
- private List<Image> mDequeuedImages = new CopyOnWriteArrayList<Image>();
+ private List<Image> mDequeuedImages = new CopyOnWriteArrayList<>();
private int mEstimatedNativeAllocBytes;
/**
@@ -118,22 +119,75 @@
* @return a new ImageWriter instance.
*/
public static ImageWriter newInstance(Surface surface, int maxImages) {
- return new ImageWriter(surface, maxImages);
+ return new ImageWriter(surface, maxImages, ImageFormat.UNKNOWN);
+ }
+
+ /**
+ * <p>
+ * Create a new ImageWriter with given number of max Images and format.
+ * </p>
+ * <p>
+ * The {@code maxImages} parameter determines the maximum number of
+ * {@link Image} objects that can be be dequeued from the
+ * {@code ImageWriter} simultaneously. Requesting more buffers will use up
+ * more memory, so it is important to use only the minimum number necessary.
+ * </p>
+ * <p>
+ * The format specifies the image format of this ImageWriter. The format
+ * from the {@code surface} will be overridden with this format. For example,
+ * if the surface is obtained from a {@link android.graphics.SurfaceTexture}, the default
+ * format may be {@link PixelFormat#RGBA_8888}. If the application creates an ImageWriter
+ * with this surface and {@link ImageFormat#PRIVATE}, this ImageWriter will be able to operate
+ * with {@link ImageFormat#PRIVATE} Images.
+ * </p>
+ * <p>
+ * Note that the consumer end-point may or may not be able to support Images with different
+ * format, for such case, the application should only use this method if the consumer is able
+ * to consume such images.
+ * </p>
+ * <p>
+ * The input Image size depends on the Surface that is provided by
+ * the downstream consumer end-point.
+ * </p>
+ *
+ * @param surface The destination Surface this writer produces Image data
+ * into.
+ * @param maxImages The maximum number of Images the user will want to
+ * access simultaneously for producing Image data. This should be
+ * as small as possible to limit memory use. Once maxImages
+ * Images are dequeued by the user, one of them has to be queued
+ * back before a new Image can be dequeued for access via
+ * {@link #dequeueInputImage()}.
+ * @param format The format of this ImageWriter. It can be any valid format specified by
+ * {@link ImageFormat} or {@link PixelFormat}.
+ *
+ * @return a new ImageWriter instance.
+ * @hide
+ */
+ public static ImageWriter newInstance(Surface surface, int maxImages, int format) {
+ if (!ImageFormat.isPublicFormat(format) && !PixelFormat.isPublicFormat(format)) {
+ throw new IllegalArgumentException("Invalid format is specified: " + format);
+ }
+ return new ImageWriter(surface, maxImages, format);
}
/**
* @hide
*/
- protected ImageWriter(Surface surface, int maxImages) {
+ protected ImageWriter(Surface surface, int maxImages, int format) {
if (surface == null || maxImages < 1) {
throw new IllegalArgumentException("Illegal input argument: surface " + surface
+ ", maxImages: " + maxImages);
}
mMaxImages = maxImages;
+
+ if (format == ImageFormat.UNKNOWN) {
+ format = SurfaceUtils.getSurfaceFormat(surface);
+ }
// Note that the underlying BufferQueue is working in synchronous mode
// to avoid dropping any buffers.
- mNativeContext = nativeInit(new WeakReference<ImageWriter>(this), surface, maxImages);
+ mNativeContext = nativeInit(new WeakReference<>(this), surface, maxImages, format);
// Estimate the native buffer allocation size and register it so it gets accounted for
// during GC. Note that this doesn't include the buffers required by the buffer queue
@@ -142,7 +196,6 @@
// complex, and 1 buffer is enough for the VM to treat the ImageWriter as being of some
// size.
Size surfSize = SurfaceUtils.getSurfaceSize(surface);
- int format = SurfaceUtils.getSurfaceFormat(surface);
mEstimatedNativeAllocBytes =
ImageUtils.getEstimatedNativeAllocBytes(surfSize.getWidth(),surfSize.getHeight(),
format, /*buffer count*/ 1);
@@ -809,7 +862,8 @@
}
// Native implemented ImageWriter methods.
- private synchronized native long nativeInit(Object weakSelf, Surface surface, int maxImgs);
+ private synchronized native long nativeInit(Object weakSelf, Surface surface, int maxImgs,
+ int format);
private synchronized native void nativeClose(long nativeCtx);
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index 611fdd1..ce50cc8 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -51,12 +51,13 @@
* management messages) can be distributed out-of-band, or in-band with the stream.
* <p>
* To descramble elementary streams, the app first calls {@link #openSession} to
- * generate a sessionId that will uniquely identify a session. A session provides
- * a context for subsequent key updates and descrambling activities. The ECMs
- * (Entitlement control messages) are sent to the session via method {@link #processEcm}.
+ * generate a {@link Session} object that will uniquely identify a session. A session
+ * provides a context for subsequent key updates and descrambling activities. The ECMs
+ * (Entitlement control messages) are sent to the session via method
+ * {@link Session#processEcm}.
* <p>
* The app next constructs a MediaDescrambler object, and initializes it with the
- * sessionId using {@link MediaDescrambler#setMediaCasSession}. This ties the
+ * session using {@link MediaDescrambler#setMediaCasSession}. This ties the
* descrambler to the session, and the descrambler can then be used to descramble
* content secured with the session's key, either during extraction, or during decoding
* with {@link android.media.MediaCodec}.
@@ -79,19 +80,20 @@
* If the app uses {@link MediaExtractor}, it can delegate the CAS session
* management to MediaExtractor by calling {@link MediaExtractor#setMediaCas}.
* MediaExtractor will take over and call {@link #openSession}, {@link #processEmm}
- * and/or {@link #processEcm}, etc.. if necessary.
+ * and/or {@link Session#processEcm}, etc.. if necessary.
* <p>
* When using {@link MediaExtractor}, the app would still need a MediaDescrambler
* to use with {@link MediaCodec} if the licensing requires a secure decoder. The
- * sessionId of the descrambler can be retrieved by {@link MediaExtractor#getDrmInitData}
- * and used to initialize a MediaDescrambler object for MediaCodec.
+ * session associated with the descrambler of a track can be retrieved by calling
+ * {@link MediaExtractor#getCasInfo}, and used to initialize a MediaDescrambler
+ * object for MediaCodec.
* <p>
* <h3>Listeners</h3>
* <p>The app may register a listener to receive events from the CA system using
* method {@link #setEventListener}. The exact format of the event is scheme-specific
* and is not specified by this API.
*/
-public final class MediaCas {
+public final class MediaCas implements AutoCloseable {
private static final String TAG = "MediaCas";
private final ParcelableCasData mCasData = new ParcelableCasData();
private ICas mICas;
@@ -229,6 +231,106 @@
}
/**
+ * Class for an open session with the CA system.
+ */
+ public final class Session implements AutoCloseable {
+ final byte[] mSessionId;
+
+ Session(@NonNull byte[] sessionId) {
+ mSessionId = sessionId;
+ }
+
+ /**
+ * Set the private data for a session.
+ *
+ * @param data byte array of the private data.
+ *
+ * @throws IllegalStateException if the MediaCas instance is not valid.
+ * @throws MediaCasException for CAS-specific errors.
+ * @throws MediaCasStateException for CAS-specific state exceptions.
+ */
+ public void setPrivateData(@NonNull byte[] data)
+ throws MediaCasException {
+ validateInternalStates();
+
+ try {
+ mICas.setSessionPrivateData(mSessionId, data);
+ } catch (ServiceSpecificException e) {
+ MediaCasException.throwExceptions(e);
+ } catch (RemoteException e) {
+ cleanupAndRethrowIllegalState();
+ }
+ }
+
+
+ /**
+ * Send a received ECM packet to the specified session of the CA system.
+ *
+ * @param data byte array of the ECM data.
+ * @param offset position within data where the ECM data begins.
+ * @param length length of the data (starting from offset).
+ *
+ * @throws IllegalStateException if the MediaCas instance is not valid.
+ * @throws MediaCasException for CAS-specific errors.
+ * @throws MediaCasStateException for CAS-specific state exceptions.
+ */
+ public void processEcm(@NonNull byte[] data, int offset, int length)
+ throws MediaCasException {
+ validateInternalStates();
+
+ try {
+ mCasData.set(data, offset, length);
+ mICas.processEcm(mSessionId, mCasData);
+ } catch (ServiceSpecificException e) {
+ MediaCasException.throwExceptions(e);
+ } catch (RemoteException e) {
+ cleanupAndRethrowIllegalState();
+ }
+ }
+
+ /**
+ * Send a received ECM packet to the specified session of the CA system.
+ * This is similar to {@link Session#processEcm(byte[], int, int)}
+ * except that the entire byte array is sent.
+ *
+ * @param data byte array of the ECM data.
+ *
+ * @throws IllegalStateException if the MediaCas instance is not valid.
+ * @throws MediaCasException for CAS-specific errors.
+ * @throws MediaCasStateException for CAS-specific state exceptions.
+ */
+ public void processEcm(@NonNull byte[] data) throws MediaCasException {
+ processEcm(data, 0, data.length);
+ }
+
+ /**
+ * Close the session.
+ *
+ * @throws IllegalStateException if the MediaCas instance is not valid.
+ * @throws MediaCasStateException for CAS-specific state exceptions.
+ */
+ @Override
+ public void close() {
+ validateInternalStates();
+
+ try {
+ mICas.closeSession(mSessionId);
+ } catch (ServiceSpecificException e) {
+ MediaCasStateException.throwExceptions(e);
+ } catch (RemoteException e) {
+ cleanupAndRethrowIllegalState();
+ }
+ }
+ }
+
+ Session createFromSessionId(byte[] sessionId) {
+ if (sessionId == null || sessionId.length == 0) {
+ return null;
+ }
+ return new Session(sessionId);
+ }
+
+ /**
* Class for parceling CAS plugin descriptors over IMediaCasService binder.
*/
static class ParcelableCasPluginDescriptor
@@ -404,21 +506,20 @@
}
/**
- * Open a session for the specified program.
+ * Open a session to descramble one or more streams scrambled by the
+ * conditional access system.
*
- * @param programNumber program_number of the program (as in ISO/IEC13818-1).
- *
- * @return session id of the newly opened session.
+ * @return session the newly opened session.
*
* @throws IllegalStateException if the MediaCas instance is not valid.
* @throws MediaCasException for CAS-specific errors.
* @throws MediaCasStateException for CAS-specific state exceptions.
*/
- public byte[] openSession(int programNumber) throws MediaCasException {
+ public Session openSession() throws MediaCasException {
validateInternalStates();
try {
- return mICas.openSession(programNumber);
+ return createFromSessionId(mICas.openSession());
} catch (ServiceSpecificException e) {
MediaCasException.throwExceptions(e);
} catch (RemoteException e) {
@@ -428,118 +529,6 @@
}
/**
- * Open a session for the specified stream.
- *
- * @param programNumber program_number of the stream (as in ISO/IEC13818-1).
- * @param elementaryPID elementary_PID of the stream (as in ISO/IEC13818-1).
- *
- * @return session id of the newly opened session.
- *
- * @throws IllegalStateException if the MediaCas instance is not valid.
- * @throws MediaCasException for CAS-specific errors.
- * @throws MediaCasStateException for CAS-specific state exceptions.
- */
- public byte[] openSession(int programNumber, int elementaryPID)
- throws MediaCasException {
- validateInternalStates();
-
- try {
- return mICas.openSessionForStream(programNumber, elementaryPID);
- } catch (ServiceSpecificException e) {
- MediaCasException.throwExceptions(e);
- } catch (RemoteException e) {
- cleanupAndRethrowIllegalState();
- }
- return null;
- }
-
- /**
- * Close the specified session.
- *
- * @param sessionId the session to be closed.
- *
- * @throws IllegalStateException if the MediaCas instance is not valid.
- * @throws MediaCasStateException for CAS-specific state exceptions.
- */
- public void closeSession(@NonNull byte[] sessionId) {
- validateInternalStates();
-
- try {
- mICas.closeSession(sessionId);
- } catch (ServiceSpecificException e) {
- MediaCasStateException.throwExceptions(e);
- } catch (RemoteException e) {
- cleanupAndRethrowIllegalState();
- }
- }
-
- /**
- * Set the private data for a session.
- *
- * @param sessionId the session for which the private data is intended.
- * @param data byte array of the private data.
- *
- * @throws IllegalStateException if the MediaCas instance is not valid.
- * @throws MediaCasException for CAS-specific errors.
- * @throws MediaCasStateException for CAS-specific state exceptions.
- */
- public void setSessionPrivateData(@NonNull byte[] sessionId, @NonNull byte[] data)
- throws MediaCasException {
- validateInternalStates();
-
- try {
- mICas.setSessionPrivateData(sessionId, data);
- } catch (ServiceSpecificException e) {
- MediaCasException.throwExceptions(e);
- } catch (RemoteException e) {
- cleanupAndRethrowIllegalState();
- }
- }
-
- /**
- * Send a received ECM packet to the specified session of the CA system.
- *
- * @param sessionId the session for which the ECM is intended.
- * @param data byte array of the ECM data.
- * @param offset position within data where the ECM data begins.
- * @param length length of the data (starting from offset).
- *
- * @throws IllegalStateException if the MediaCas instance is not valid.
- * @throws MediaCasException for CAS-specific errors.
- * @throws MediaCasStateException for CAS-specific state exceptions.
- */
- public void processEcm(@NonNull byte[] sessionId, @NonNull byte[] data,
- int offset, int length) throws MediaCasException {
- validateInternalStates();
-
- try {
- mCasData.set(data, offset, length);
- mICas.processEcm(sessionId, mCasData);
- } catch (ServiceSpecificException e) {
- MediaCasException.throwExceptions(e);
- } catch (RemoteException e) {
- cleanupAndRethrowIllegalState();
- }
- }
-
- /**
- * Send a received ECM packet to the specified session of the CA system.
- * This is similar to {@link #processEcm(byte[], byte[], int, int)}
- * except that the entire byte array is sent.
- *
- * @param sessionId the session for which the ECM is intended.
- * @param data byte array of the ECM data.
- *
- * @throws IllegalStateException if the MediaCas instance is not valid.
- * @throws MediaCasException for CAS-specific errors.
- * @throws MediaCasStateException for CAS-specific state exceptions.
- */
- public void processEcm(@NonNull byte[] sessionId, @NonNull byte[] data)
- throws MediaCasException {
- processEcm(sessionId, data, 0, data.length);
- }
-
- /**
* Send a received EMM packet to the CA system.
*
* @param data byte array of the EMM data.
@@ -650,10 +639,8 @@
}
}
- /**
- * Release the MediaCas instance.
- */
- public void release() {
+ @Override
+ public void close() {
if (mICas != null) {
try {
mICas.release();
@@ -666,6 +653,6 @@
@Override
protected void finalize() {
- release();
+ close();
}
}
\ No newline at end of file
diff --git a/media/java/android/media/MediaDescrambler.java b/media/java/android/media/MediaDescrambler.java
index 2dd1097..b75b7dd 100644
--- a/media/java/android/media/MediaDescrambler.java
+++ b/media/java/android/media/MediaDescrambler.java
@@ -38,7 +38,7 @@
* Scrambling schemes are identified by 16-bit unsigned integer as in CA_system_id.
*
*/
-public final class MediaDescrambler {
+public final class MediaDescrambler implements AutoCloseable {
private static final String TAG = "MediaDescrambler";
private IDescrambler mIDescrambler;
@@ -141,17 +141,17 @@
* android.media.MediaCodec#queueSecureInputBuffer} by specifying even
* or odd key in the {@link android.media.MediaCodec.CryptoInfo#key} field.
*
- * @param sessionId the MediaCas sessionId to associate with this
+ * @param session the MediaCas session to associate with this
* MediaDescrambler instance.
*
* @throws IllegalStateException if the descrambler instance is not valid.
* @throws MediaCasStateException for CAS-specific state exceptions.
*/
- public final void setMediaCasSession(@NonNull byte[] sessionId) {
+ public final void setMediaCasSession(@NonNull MediaCas.Session session) {
validateInternalStates();
try {
- mIDescrambler.setMediaCasSession(sessionId);
+ mIDescrambler.setMediaCasSession(session.mSessionId);
} catch (ServiceSpecificException e) {
MediaCasStateException.throwExceptions(e);
} catch (RemoteException e) {
@@ -163,11 +163,10 @@
* Descramble a ByteBuffer of data described by a
* {@link android.media.MediaCodec.CryptoInfo} structure.
*
- * @param srcBuf ByteBuffer containing the scrambled data.
- * @param srcPos position within src where the scrambled data starts.
- * @param dstBuf ByteBuffer to descramble into. If null, descrambling will happen
- * in-place and src will be used as dst.
- * @param dstPos position within dst to put the descrambled data.
+ * @param srcBuf ByteBuffer containing the scrambled data, which starts at
+ * srcBuf.position().
+ * @param dstBuf ByteBuffer to hold the descrambled data, which starts at
+ * dstBuf.position().
* @param cryptoInfo a {@link android.media.MediaCodec.CryptoInfo} structure
* describing the subsamples contained in src.
*
@@ -178,7 +177,7 @@
* @throws MediaCasStateException for CAS-specific state exceptions.
*/
public final int descramble(
- @NonNull ByteBuffer srcBuf, int srcPos, ByteBuffer dstBuf, int dstPos,
+ @NonNull ByteBuffer srcBuf, @NonNull ByteBuffer dstBuf,
@NonNull MediaCodec.CryptoInfo cryptoInfo) {
validateInternalStates();
@@ -208,14 +207,16 @@
cryptoInfo.numSubSamples,
cryptoInfo.numBytesOfClearData,
cryptoInfo.numBytesOfEncryptedData,
- srcBuf, srcPos, dstBuf, dstPos);
+ srcBuf, srcBuf.position(), srcBuf.limit(),
+ dstBuf, dstBuf.position(), dstBuf.limit());
} catch (ServiceSpecificException e) {
MediaCasStateException.throwExceptions(e);
}
return -1;
}
- public final void release() {
+ @Override
+ public void close() {
if (mIDescrambler != null) {
try {
mIDescrambler.release();
@@ -229,7 +230,7 @@
@Override
protected void finalize() {
- release();
+ close();
}
private static native final void native_init();
@@ -237,7 +238,8 @@
private native final void native_release();
private native final int native_descramble(
byte key, int numSubSamples, int[] numBytesOfClearData, int[] numBytesOfEncryptedData,
- @NonNull ByteBuffer srcBuf, int srcOffset, ByteBuffer dstBuf, int dstOffset);
+ @NonNull ByteBuffer srcBuf, int srcOffset, int srcLimit,
+ ByteBuffer dstBuf, int dstOffset, int dstLimit);
static {
System.loadLibrary("media_jni");
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index b8d1d12..88b1c5f 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -474,6 +474,9 @@
/**
* This event type indicates that the licensed usage duration for keys in a session
* has expired. The keys are no longer valid.
+ * @deprecated Use {@link OnKeyStatusChangeListener#onKeyStatusChange}
+ * and check for {@link MediaDrm.KeyStatus#STATUS_EXPIRED} in the {@link MediaDrm.KeyStatus}
+ * instead.
*/
public static final int EVENT_KEY_EXPIRED = 3;
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 2ed6668..a0a6a1e 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -259,11 +259,71 @@
* @param mediaCas the MediaCas object to use.
*/
public final void setMediaCas(@NonNull MediaCas mediaCas) {
+ mMediaCas = mediaCas;
nativeSetMediaCas(mediaCas.getBinder());
}
private native final void nativeSetMediaCas(@NonNull IBinder casBinder);
+ /**
+ * Describes the conditional access system used to scramble a track.
+ */
+ public static final class CasInfo {
+ private final int mSystemId;
+ private final MediaCas.Session mSession;
+
+ CasInfo(int systemId, @Nullable MediaCas.Session session) {
+ mSystemId = systemId;
+ mSession = session;
+ }
+
+ /**
+ * Retrieves the system id of the conditional access system.
+ *
+ * @return CA system id of the CAS used to scramble the track.
+ */
+ public int getSystemId() {
+ return mSystemId;
+ }
+
+ /**
+ * Retrieves the {@link MediaCas.Session} associated with a track. The
+ * session is needed to initialize a descrambler in order to decode the
+ * scrambled track.
+ * <p>
+ * @see MediaDescrambler#setMediaCasSession
+ * <p>
+ * @return a {@link MediaCas.Session} object associated with a track.
+ */
+ public MediaCas.Session getSession() {
+ return mSession;
+ }
+ }
+
+ /**
+ * Retrieves the information about the conditional access system used to scramble
+ * a track.
+ *
+ * @param index of the track.
+ * @return an {@link CasInfo} object describing the conditional access system.
+ */
+ public CasInfo getCasInfo(int index) {
+ Map<String, Object> formatMap = getTrackFormatNative(index);
+ if (formatMap.containsKey(MediaFormat.KEY_CA_SYSTEM_ID)) {
+ int systemId = ((Integer)formatMap.get(MediaFormat.KEY_CA_SYSTEM_ID)).intValue();
+ MediaCas.Session session = null;
+ if (mMediaCas != null && formatMap.containsKey(MediaFormat.KEY_CA_SESSION_ID)) {
+ ByteBuffer buf = (ByteBuffer) formatMap.get(MediaFormat.KEY_CA_SESSION_ID);
+ buf.rewind();
+ final byte[] sessionId = new byte[buf.remaining()];
+ buf.get(sessionId);
+ session = mMediaCas.createFromSessionId(sessionId);
+ }
+ return new CasInfo(systemId, session);
+ }
+ return null;
+ }
+
@Override
protected void finalize() {
native_finalize();
@@ -307,31 +367,6 @@
return initDataMap.get(schemeUuid);
}
};
- } else if (formatMap.containsKey("mime")
- && "video/mp2ts".equals(formatMap.get("mime"))) {
- final Map<UUID, DrmInitData.SchemeInitData> initDataMap =
- new HashMap<UUID, DrmInitData.SchemeInitData>();
-
- int numTracks = getTrackCount();
- for (int i = 0; i < numTracks; ++i) {
- Map<String, Object> trackFormatMap = getTrackFormatNative(i);
- if (!trackFormatMap.containsKey("cas")) {
- continue;
- }
- ByteBuffer buf = (ByteBuffer) trackFormatMap.get("cas");
- buf.rewind();
- final byte[] data = new byte[buf.remaining()];
- buf.get(data);
- initDataMap.put(new UUID(0, i), new DrmInitData.SchemeInitData("cas", data));
- }
- if (initDataMap.isEmpty()) {
- return null;
- }
- return new DrmInitData() {
- public SchemeInitData get(UUID schemeUuid) {
- return initDataMap.get(schemeUuid);
- }
- };
} else {
int numTracks = getTrackCount();
for (int i = 0; i < numTracks; ++i) {
@@ -349,8 +384,8 @@
}
};
}
- return null;
}
+ return null;
}
/**
@@ -680,5 +715,7 @@
native_init();
}
+ private MediaCas mMediaCas;
+
private long mNativeContext;
}
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index e77c00b..ed5f7d8 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -767,6 +767,29 @@
*/
public static final String KEY_TRACK_ID = "track-id";
+ /**
+ * A key describing the system id of the conditional access system used to scramble
+ * a media track.
+ * <p>
+ * This key is set by {@link MediaExtractor} if the track is scrambled with a conditional
+ * access system.
+ * <p>
+ * The associated value is an integer.
+ * @hide
+ */
+ public static final String KEY_CA_SYSTEM_ID = "ca-system-id";
+
+ /**
+ * A key describing the {@link MediaCas.Session} object associated with a media track.
+ * <p>
+ * This key is set by {@link MediaExtractor} if the track is scrambled with a conditional
+ * access system.
+ * <p>
+ * The associated value is a ByteBuffer.
+ * @hide
+ */
+ public static final String KEY_CA_SESSION_ID = "ca-session-id";
+
/* package private */ MediaFormat(Map<String, Object> map) {
mMap = map;
}
diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java
index af11e07..1dda6a4 100644
--- a/media/java/android/media/VolumeShaper.java
+++ b/media/java/android/media/VolumeShaper.java
@@ -301,7 +301,7 @@
.setInterpolatorType(INTERPOLATOR_TYPE_LINEAR)
.setCurve(new float[] {0.f, 1.f} /* times */,
new float[] {0.f, 1.f} /* volumes */)
- .setDurationMs(1000.)
+ .setDurationMillis(1000.)
.build();
/**
@@ -314,7 +314,7 @@
.setInterpolatorType(INTERPOLATOR_TYPE_CUBIC)
.setCurve(new float[] {0.f, 1.f} /* times */,
new float[] {0.f, 1.f} /* volumes */)
- .setDurationMs(1000.)
+ .setDurationMillis(1000.)
.build();
/**
@@ -348,12 +348,12 @@
SINE_RAMP = new VolumeShaper.Configuration.Builder()
.setInterpolatorType(INTERPOLATOR_TYPE_CUBIC)
.setCurve(times, sines)
- .setDurationMs(1000.)
+ .setDurationMillis(1000.)
.build();
SCURVE_RAMP = new VolumeShaper.Configuration.Builder()
.setInterpolatorType(INTERPOLATOR_TYPE_CUBIC)
.setCurve(times, scurve)
- .setDurationMs(1000.)
+ .setDurationMillis(1000.)
.build();
}
@@ -569,7 +569,7 @@
/**
* Returns the duration of the volume shape in milliseconds.
*/
- public double getDurationMs() {
+ public double getDurationMillis() {
return mDurationMs;
}
@@ -700,7 +700,7 @@
* .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
* .setCurve(new float[] { 0.f, 1.f }, // times
* new float[] { 0.f, 1.f }) // volumes
- * .setDurationMs(1000.)
+ * .setDurationMillis(1000.)
* .build();
* </pre>
* <p>
@@ -731,7 +731,7 @@
mId = configuration.getId();
mOptionFlags = configuration.getAllOptionFlags();
mInterpolatorType = configuration.getInterpolatorType();
- mDurationMs = configuration.getDurationMs();
+ mDurationMs = configuration.getDurationMillis();
mTimes = configuration.getTimes().clone();
mVolumes = configuration.getVolumes().clone();
}
@@ -805,17 +805,17 @@
*
* If omitted, the default duration is 1 second.
*
- * @param durationMs
+ * @param durationMillis
* @return the same {@code Builder} instance.
- * @throws IllegalArgumentException if {@code durationMs}
+ * @throws IllegalArgumentException if {@code durationMillis}
* is not strictly positive.
*/
- public @NonNull Builder setDurationMs(double durationMs) {
- if (durationMs <= 0.) {
+ public @NonNull Builder setDurationMillis(double durationMillis) {
+ if (durationMillis <= 0.) {
throw new IllegalArgumentException(
- "duration: " + durationMs + " not positive");
+ "duration: " + durationMillis + " not positive");
}
- mDurationMs = durationMs;
+ mDurationMs = durationMillis;
return this;
}
@@ -833,7 +833,7 @@
* time (x) coordinates should be monotonically increasing, from 0.f to 1.f;
* volume (y) coordinates must be within 0.f to 1.f.
* <p>
- * The time scale is set by {@link #setDurationMs}.
+ * The time scale is set by {@link #setDurationMillis}.
* <p>
* @param times an array of float values representing
* the time line of the volume curve.
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index 0d51b5b..b076bb6 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -17,6 +17,7 @@
package android.media.tv;
import android.content.ComponentName;
+import android.content.Intent;
import android.graphics.Rect;
import android.media.PlaybackParams;
import android.media.tv.DvbDeviceInfo;
@@ -105,4 +106,8 @@
// For DVB device binding
List<DvbDeviceInfo> getDvbDeviceList();
ParcelFileDescriptor openDvbDevice(in DvbDeviceInfo info, int device);
+
+ // For preview channels and programs
+ void sendTvInputNotifyIntent(in Intent intent, int userId);
+ void requestChannelBrowsable(in Uri channelUri, int userId);
}
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index e82dd82..1b55380 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -21,9 +21,11 @@
import android.annotation.Nullable;
import android.annotation.StringDef;
import android.annotation.SystemApi;
+import android.app.Activity;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentUris;
+import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@@ -75,8 +77,9 @@
private static final String PATH_PASSTHROUGH = "passthrough";
/**
- * Activity Action: sent by an application telling the system to set the given channel as
- * browsable. This is only relevant to channels with {@link Channels#TYPE_PREVIEW} type.
+ * Broadcast Action: sent when an application requests the system to make the given channel
+ * browsable. The operation is performed in the background without user interaction. This
+ * is only relevant to channels with {@link Channels#TYPE_PREVIEW} type.
*
* <p>The intent must contain the following bundle parameters:
* <ul>
@@ -84,9 +87,26 @@
* integer.</li>
* <li>{@link #EXTRA_PACKAGE_NAME}: the package name of the requesting application.</li>
* </ul>
+ * @hide
*/
- public static final String ACTION_MAKE_CHANNEL_BROWSABLE =
- "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
+ @SystemApi
+ public static final String ACTION_CHANNEL_BROWSABLE_REQUESTED =
+ "android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED";
+
+ /**
+ * Activity Action: sent by an application telling the system to make the given channel
+ * browsable with user interaction. The system may show UI to ask user to approve the channel.
+ * This is only relevant to channels with {@link Channels#TYPE_PREVIEW} type. Use
+ * {@link Activity#startActivityForResult} to get the result of the request.
+ *
+ * <p>The intent must contain the following bundle parameters:
+ * <ul>
+ * <li>{@link #EXTRA_CHANNEL_ID}: ID for the {@link Channels#TYPE_PREVIEW} channel as a long
+ * integer.</li>
+ * </ul>
+ */
+ public static final String ACTION_REQUEST_CHANNEL_BROWSABLE =
+ "android.media.tv.action.REQUEST_CHANNEL_BROWSABLE";
/**
* Broadcast Action: sent by the system to tell the target TV input that one of its preview
@@ -146,10 +166,16 @@
public static final String ACTION_INITIALIZE_PROGRAMS =
"android.media.tv.action.INITIALIZE_PROGRAMS";
- /** The key for a bundle parameter containing a channel ID as a long integer */
+ /**
+ * The key for a bundle parameter containing a channel ID as a long integer
+ */
public static final String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
- /** The key for a bundle parameter containing a package name as a string. */
+ /**
+ * The key for a bundle parameter containing a package name as a string.
+ * @hide
+ */
+ @SystemApi
public static final String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
/** The key for a bundle parameter containing a program ID as a long integer. */
@@ -161,6 +187,38 @@
"android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
/**
+ * The key for a bundle parameter containing the result code of a method call as an integer.
+ *
+ * @see #RESULT_OK
+ * @see #RESULT_ERROR_IO
+ * @see #RESULT_ERROR_INVALID_ARGUMENT
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_RESULT_CODE = "android.media.tv.extra.RESULT_CODE";
+
+ /**
+ * The result code for a successful execution without error.
+ * @hide
+ */
+ @SystemApi
+ public static final int RESULT_OK = 0;
+
+ /**
+ * The result code for a failure from I/O operation.
+ * @hide
+ */
+ @SystemApi
+ public static final int RESULT_ERROR_IO = 1;
+
+ /**
+ * The result code for a failure from invalid argument.
+ * @hide
+ */
+ @SystemApi
+ public static final int RESULT_ERROR_INVALID_ARGUMENT = 2;
+
+ /**
* The method name to get existing columns in the given table of the specified content provider.
*
* <p>The method caller must provide the following parameter:
@@ -209,6 +267,78 @@
public static final String METHOD_ADD_COLUMN = "add_column";
/**
+ * The method name to get all the blocked packages. When a package is blocked, all the data for
+ * preview programs/channels and watch next programs belonging to this package in the content
+ * provider will be cleared. Once a package is blocked, {@link SecurityException} will be thrown
+ * for all the requests to preview programs/channels and watch next programs via
+ * {@link android.content.ContentProvider} from it.
+ *
+ * <p>The returned {@link android.os.Bundle} will include all the blocked package names with the
+ * key {@link #EXTRA_BLOCKED_PACKAGES}.
+ *
+ * @see ContentResolver#call(Uri, String, String, Bundle)
+ * @see #EXTRA_BLOCKED_PACKAGES
+ * @see #METHOD_BLOCK_PACKAGE
+ * @see #METHOD_UNBLOCK_PACKAGE
+ * @hide
+ */
+ @SystemApi
+ public static final String METHOD_GET_BLOCKED_PACKAGES = "get_blocked_packages";
+
+ /**
+ * The method name to block the access from the given package. When a package is blocked, all
+ * the data for preview programs/channels and watch next programs belonging to this package in
+ * the content provider will be cleared. Once a package is blocked, {@link SecurityException}
+ * will be thrown for all the requests to preview programs/channels and watch next programs via
+ * {@link android.content.ContentProvider} from it.
+ *
+ * <p>The method caller must provide the following parameter:
+ * <ul>
+ * <li>{@code arg}: The package name to be added as blocked package {@link String}.</li>
+ * </ul>
+ *
+ * <p>The returned {@link android.os.Bundle} will include an integer code denoting whether the
+ * execution is successful or not with the key {@link #EXTRA_RESULT_CODE}. If {@code arg} is
+ * empty, the result code will be {@link #RESULT_ERROR_INVALID_ARGUMENT}. If success, the result
+ * code will be {@link #RESULT_OK}. Otherwise, the result code will be {@link #RESULT_ERROR_IO}.
+ *
+ * @see ContentResolver#call(Uri, String, String, Bundle)
+ * @see #EXTRA_RESULT_CODE
+ * @see #METHOD_GET_BLOCKED_PACKAGES
+ * @see #METHOD_UNBLOCK_PACKAGE
+ * @hide
+ */
+ @SystemApi
+ public static final String METHOD_BLOCK_PACKAGE = "block_package";
+
+ /**
+ * The method name to unblock the access from the given package. When a package is blocked, all
+ * the data for preview programs/channels and watch next programs belonging to this package in
+ * the content provider will be cleared. Once a package is blocked, {@link SecurityException}
+ * will be thrown for all the requests to preview programs/channels and watch next programs via
+ * {@link android.content.ContentProvider} from it.
+ *
+ * <p>The method caller must provide the following parameter:
+ * <ul>
+ * <li>{@code arg}: The package name to be removed from blocked list as a {@link String}.
+ * </li>
+ * </ul>
+ *
+ * <p>The returned {@link android.os.Bundle} will include an integer code denoting whether the
+ * execution is successful or not with the key {@link #EXTRA_RESULT_CODE}. If {@code arg} is
+ * empty, the result code will be {@link #RESULT_ERROR_INVALID_ARGUMENT}. If success, the result
+ * code will be {@link #RESULT_OK}. Otherwise, the result code will be {@link #RESULT_ERROR_IO}.
+ *
+ * @see ContentResolver#call(Uri, String, String, Bundle)
+ * @see #EXTRA_RESULT_CODE
+ * @see #METHOD_GET_BLOCKED_PACKAGES
+ * @see #METHOD_BLOCK_PACKAGE
+ * @hide
+ */
+ @SystemApi
+ public static final String METHOD_UNBLOCK_PACKAGE = "unblock_package";
+
+ /**
* The key for a returned {@link Bundle} value containing existing column names in the given
* table as an {@link ArrayList} of {@link String}.
*
@@ -253,6 +383,16 @@
public static final String EXTRA_DEFAULT_VALUE = "android.media.tv.extra.DEFAULT_VALUE";
/**
+ * The key for a returned {@link Bundle} value containing all the blocked package names as an
+ * {@link ArrayList} of {@link String}.
+ *
+ * @see #METHOD_GET_BLOCKED_PACKAGES
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_BLOCKED_PACKAGES = "android.media.tv.extra.BLOCKED_PACKAGES";
+
+ /**
* An optional query, update or delete URI parameter that allows the caller to specify TV input
* ID to filter channels.
* @hide
@@ -565,6 +705,24 @@
return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PROGRAM);
}
+ /**
+ * Requests to make a channel browsable.
+ *
+ * <p>Once called, the system will review the request and make the channel browsable based on
+ * its policy. The first request from a package is guaranteed to be approved. This is only
+ * relevant to channels with {@link Channels#TYPE_PREVIEW} type.
+ *
+ * @param context The context for accessing content provider.
+ * @param channelId The channel ID to be browsable.
+ * @see Channels#COLUMN_BROWSABLE
+ */
+ public static void requestChannelBrowsable(Context context, long channelId) {
+ TvInputManager manager = (TvInputManager) context.getSystemService(
+ Context.TV_INPUT_SERVICE);
+ if (manager != null) {
+ manager.requestChannelBrowsable(buildChannelUri(channelId));
+ }
+ }
private TvContract() {}
@@ -589,6 +747,36 @@
* @hide
*/
interface ProgramColumns {
+ /** @hide */
+ @IntDef({
+ REVIEW_RATING_STYLE_STARS,
+ REVIEW_RATING_STYLE_THUMBS_UP_DOWN,
+ REVIEW_RATING_STYLE_PERCENTAGE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface ReviewRatingStyle {}
+
+ /**
+ * The review rating style for five star rating.
+ *
+ * @see #COLUMN_REVIEW_RATING_STYLE
+ */
+ int REVIEW_RATING_STYLE_STARS = 0;
+
+ /**
+ * The review rating style for thumbs-up and thumbs-down rating.
+ *
+ * @see #COLUMN_REVIEW_RATING_STYLE
+ */
+ int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1;
+
+ /**
+ * The review rating style for 0 to 100 point system.
+ *
+ * @see #COLUMN_REVIEW_RATING_STYLE
+ */
+ int REVIEW_RATING_STYLE_PERCENTAGE = 2;
+
/**
* The title of this TV program.
*
@@ -851,6 +1039,33 @@
* <p>Type: INTEGER
*/
String COLUMN_VERSION_NUMBER = "version_number";
+
+ /**
+ * The review rating score style used for {@link #COLUMN_REVIEW_RATING}.
+ *
+ * <p> The value should match one of the followings: {@link #REVIEW_RATING_STYLE_STARS},
+ * {@link #REVIEW_RATING_STYLE_THUMBS_UP_DOWN}, and {@link #REVIEW_RATING_STYLE_PERCENTAGE}.
+ *
+ * <p>Type: INTEGER
+ * @see #COLUMN_REVIEW_RATING
+ */
+ String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+
+ /**
+ * The review rating score for this program.
+ *
+ * <p>The format of the value is dependent on {@link #COLUMN_REVIEW_RATING_STYLE}. If the
+ * style is {@link #REVIEW_RATING_STYLE_STARS}, the value should be a real number between
+ * 0.0 and 5.0. (e.g. "4.5") If the style is {@link #REVIEW_RATING_STYLE_THUMBS_UP_DOWN},
+ * the value should be two integers, one for thumbs-up count and the other for thumbs-down
+ * count, with a comma between them. (e.g. "200,40") If the style is
+ * {@link #REVIEW_RATING_STYLE_PERCENTAGE}, the value shoule be a real number between 0 and
+ * 100. (e.g. "99.9")
+ *
+ * <p>Type: TEXT
+ * @see #COLUMN_REVIEW_RATING_STYLE
+ */
+ String COLUMN_REVIEW_RATING = "review_rating";
}
/**
@@ -967,6 +1182,7 @@
ASPECT_RATIO_3_2,
ASPECT_RATIO_1_1,
ASPECT_RATIO_2_3,
+ ASPECT_RATIO_4_3,
})
@Retention(RetentionPolicy.SOURCE)
public @interface AspectRatio {}
@@ -988,12 +1204,20 @@
int ASPECT_RATIO_3_2 = 1;
/**
+ * The aspect ratio for 4:3.
+ *
+ * @see #COLUMN_POSTER_ART_ASPECT_RATIO
+ * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
+ */
+ int ASPECT_RATIO_4_3 = 2;
+
+ /**
* The aspect ratio for 1:1.
*
* @see #COLUMN_POSTER_ART_ASPECT_RATIO
* @see #COLUMN_THUMBNAIL_ASPECT_RATIO
*/
- int ASPECT_RATIO_1_1 = 2;
+ int ASPECT_RATIO_1_1 = 3;
/**
* The aspect ratio for 2:3.
@@ -1001,7 +1225,7 @@
* @see #COLUMN_POSTER_ART_ASPECT_RATIO
* @see #COLUMN_THUMBNAIL_ASPECT_RATIO
*/
- int ASPECT_RATIO_2_3 = 3;
+ int ASPECT_RATIO_2_3 = 4;
/** @hide */
@IntDef({
@@ -1096,36 +1320,6 @@
*/
int INTERACTION_TYPE_VIEWERS = 6;
- /** @hide */
- @IntDef({
- REVIEW_RATING_STYLE_STARS,
- REVIEW_RATING_STYLE_THUMBS_UP_DOWN,
- REVIEW_RATING_STYLE_PERCENTAGE,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ReviewRatingStyle {}
-
- /**
- * The review rating style for five star rating.
- *
- * @see #COLUMN_REVIEW_RATING_STYLE
- */
- int REVIEW_RATING_STYLE_STARS = 0;
-
- /**
- * The review rating style for thumbs-up and thumbs-down rating.
- *
- * @see #COLUMN_REVIEW_RATING_STYLE
- */
- int REVIEW_RATING_STYLE_THUMBS_UP_DOWN = 1;
-
- /**
- * The review rating style for 0 to 100 point system.
- *
- * @see #COLUMN_REVIEW_RATING_STYLE
- */
- int REVIEW_RATING_STYLE_PERCENTAGE = 2;
-
/**
* The type of this program content.
*
@@ -1156,6 +1350,7 @@
* <p>The value should match one of the followings:
* {@link #ASPECT_RATIO_16_9},
* {@link #ASPECT_RATIO_3_2},
+ * {@link #ASPECT_RATIO_4_3},
* {@link #ASPECT_RATIO_1_1}, and
* {@link #ASPECT_RATIO_2_3}.
*
@@ -1169,6 +1364,7 @@
* <p>The value should match one of the followings:
* {@link #ASPECT_RATIO_16_9},
* {@link #ASPECT_RATIO_3_2},
+ * {@link #ASPECT_RATIO_4_3},
* {@link #ASPECT_RATIO_1_1}, and
* {@link #ASPECT_RATIO_2_3}.
*
@@ -1375,33 +1571,6 @@
String COLUMN_AUTHOR = "author";
/**
- * The review rating score style used for {@link #COLUMN_REVIEW_RATING}.
- *
- * <p> The value should match one of the followings: {@link #REVIEW_RATING_STYLE_STARS},
- * {@link #REVIEW_RATING_STYLE_THUMBS_UP_DOWN}, and {@link #REVIEW_RATING_STYLE_PERCENTAGE}.
- *
- * <p>Type: INTEGER
- * @see #COLUMN_REVIEW_RATING
- */
- String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
-
- /**
- * The review rating score for this program.
- *
- * <p>The format of the value is dependent on {@link #COLUMN_REVIEW_RATING_STYLE}. If the
- * style is {@link #REVIEW_RATING_STYLE_STARS}, the value should be a real number between
- * 0.0 and 5.0. (e.g. "4.5") If the style is {@link #REVIEW_RATING_STYLE_THUMBS_UP_DOWN},
- * the value should be two integers, one for thumbs-up count and the other for thumbs-down
- * count, with a comma between them. (e.g. "200,40") If the style is
- * {@link #REVIEW_RATING_STYLE_PERCENTAGE}, the value shoule be a real number between 0 and
- * 100. (e.g. "99.9")
- *
- * <p>Type: TEXT
- * @see #COLUMN_REVIEW_RATING_STYLE
- */
- String COLUMN_REVIEW_RATING = "review_rating";
-
- /**
* The flag indicating whether this TV program is browsable or not.
*
* <p>This column can only be set by applications having proper system permission. For
@@ -2184,19 +2353,6 @@
*/
public static final String COLUMN_TRANSIENT = "transient";
- /**
- * The flag indicating whether this TV channel is approved to be shown by the system.
- *
- * <p>A value of 1 indicates that the channel is approved to be shown by the system, and a
- * value of 0 indicates that the channel is blocked by system. If not specified, this value
- * is set to 0 (not approved) by default.
- *
- * <p>Type: INTEGER (boolean)
- * @hide
- */
- @SystemApi
- public static final String COLUMN_SYSTEM_APPROVED = "system_approved";
-
private Channels() {}
/**
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 09b2050..68ee02c 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -21,6 +21,7 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.content.Intent;
import android.graphics.Rect;
import android.media.PlaybackParams;
import android.net.Uri;
@@ -1394,6 +1395,64 @@
}
/**
+ * Notifies the TV input of the given preview program that the program's browsable state is
+ * disabled.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NOTIFY_TV_INPUTS)
+ public void notifyPreviewProgramBrowsableDisabled(String packageName, long programId) {
+ Intent intent = new Intent();
+ intent.setAction(TvContract.ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED);
+ intent.putExtra(TvContract.EXTRA_PREVIEW_PROGRAM_ID, programId);
+ intent.setPackage(packageName);
+ try {
+ mService.sendTvInputNotifyIntent(intent, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Notifies the TV input of the given watch next program that the program's browsable state is
+ * disabled.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NOTIFY_TV_INPUTS)
+ public void notifyWatchNextProgramBrowsableDisabled(String packageName, long programId) {
+ Intent intent = new Intent();
+ intent.setAction(TvContract.ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED);
+ intent.putExtra(TvContract.EXTRA_WATCH_NEXT_PROGRAM_ID, programId);
+ intent.setPackage(packageName);
+ try {
+ mService.sendTvInputNotifyIntent(intent, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Notifies the TV input of the given preview program that the program is added to watch next.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NOTIFY_TV_INPUTS)
+ public void notifyPreviewProgramAddedToWatchNext(String packageName, long previewProgramId,
+ long watchNextProgramId) {
+ Intent intent = new Intent();
+ intent.setAction(TvContract.ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT);
+ intent.putExtra(TvContract.EXTRA_PREVIEW_PROGRAM_ID, previewProgramId);
+ intent.putExtra(TvContract.EXTRA_WATCH_NEXT_PROGRAM_ID, watchNextProgramId);
+ intent.setPackage(packageName);
+ try {
+ mService.sendTvInputNotifyIntent(intent, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Creates a {@link Session} for a given TV input.
*
* <p>The number of sessions that can be created at the same time is limited by the capability
@@ -1622,6 +1681,23 @@
}
/**
+ * Requests to make a channel browsable.
+ *
+ * <p>Once called, the system will review the request and make the channel browsable based on
+ * its policy. The first request from a package is guaranteed to be approved.
+ *
+ * @param channelUri The URI for the channel to be browsable.
+ * @hide
+ */
+ public void requestChannelBrowsable(Uri channelUri) {
+ try {
+ mService.requestChannelBrowsable(channelUri, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* The Session provides the per-session functionality of TV inputs.
* @hide
*/
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 431d5d8..c2ed8cf 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -51,6 +51,7 @@
libandroidfw
LOCAL_STATIC_LIBRARIES := \
+ libgrallocusage \
LOCAL_C_INCLUDES += \
external/libexif/ \
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index f5e19f9..163c4b0 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -31,6 +31,8 @@
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_view_Surface.h>
+#include <android_runtime/android_hardware_HardwareBuffer.h>
+#include <grallocusage/GrallocUsageConversion.h>
#include <jni.h>
#include <JNIHelp.h>
@@ -42,6 +44,7 @@
#define ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID "mNativeBuffer"
#define ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID "mTimestamp"
+#define CONSUMER_BUFFER_USAGE_UNKNOWN 0;
// ----------------------------------------------------------------------------
using namespace android;
@@ -327,8 +330,8 @@
"Can not find SurfacePlane constructor");
}
-static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz,
- jint width, jint height, jint format, jint maxImages)
+static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint width, jint height,
+ jint format, jint maxImages, jlong ndkUsage)
{
status_t res;
int nativeFormat;
@@ -358,17 +361,29 @@
width, height, format, maxImages, getpid(),
createProcessUniqueId());
uint32_t consumerUsage = GRALLOC_USAGE_SW_READ_OFTEN;
+ bool needUsageOverride = ndkUsage != CONSUMER_BUFFER_USAGE_UNKNOWN;
+ uint64_t outProducerUsage = 0;
+ uint64_t outConsumerUsage = 0;
+ android_hardware_HardwareBuffer_convertToGrallocUsageBits(&outProducerUsage, &outConsumerUsage,
+ ndkUsage, 0);
if (isFormatOpaque(nativeFormat)) {
// Use the SW_READ_NEVER usage to tell producer that this format is not for preview or video
// encoding. The only possibility will be ZSL output.
consumerUsage = GRALLOC_USAGE_SW_READ_NEVER;
+ if (needUsageOverride) {
+ consumerUsage = android_convertGralloc1To0Usage(0, outConsumerUsage);
+ }
+ } else if (needUsageOverride) {
+ ALOGW("Consumer usage override for non-opaque format is not implemented yet, "
+ "ignore the provided usage from the application");
}
bufferConsumer = new BufferItemConsumer(gbConsumer, consumerUsage, maxImages,
/*controlledByApp*/true);
if (bufferConsumer == nullptr) {
jniThrowExceptionFmt(env, "java/lang/RuntimeException",
- "Failed to allocate native buffer consumer for format 0x%x", nativeFormat);
+ "Failed to allocate native buffer consumer for format 0x%x and usage 0x%x",
+ nativeFormat, consumerUsage);
return;
}
ctx->setBufferConsumer(bufferConsumer);
@@ -788,7 +803,7 @@
static const JNINativeMethod gImageReaderMethods[] = {
{"nativeClassInit", "()V", (void*)ImageReader_classInit },
- {"nativeInit", "(Ljava/lang/Object;IIII)V", (void*)ImageReader_init },
+ {"nativeInit", "(Ljava/lang/Object;IIIIJ)V", (void*)ImageReader_init },
{"nativeClose", "()V", (void*)ImageReader_close },
{"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease },
{"nativeImageSetup", "(Landroid/media/Image;)I", (void*)ImageReader_imageSetup },
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index 0149d76..ed5fbcf 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -33,7 +33,7 @@
#include <inttypes.h>
#define IMAGE_BUFFER_JNI_ID "mNativeBuffer"
-
+#define IMAGE_FORMAT_UNKNOWN 0 // This is the same value as ImageFormat#UNKNOWN.
// ----------------------------------------------------------------------------
using namespace android;
@@ -222,7 +222,7 @@
}
static jlong ImageWriter_init(JNIEnv* env, jobject thiz, jobject weakThiz, jobject jsurface,
- jint maxImages) {
+ jint maxImages, jint userFormat) {
status_t res;
ALOGV("%s: maxImages:%d", __FUNCTION__, maxImages);
@@ -255,7 +255,7 @@
// Get the dimension and format of the producer.
sp<ANativeWindow> anw = producer;
- int32_t width, height, format;
+ int32_t width, height, surfaceFormat;
if ((res = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, &width)) != OK) {
ALOGE("%s: Query Surface width failed: %s (%d)", __FUNCTION__, strerror(-res), res);
jniThrowRuntimeException(env, "Failed to query Surface width");
@@ -270,21 +270,27 @@
}
ctx->setBufferHeight(height);
- if ((res = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &format)) != OK) {
- ALOGE("%s: Query Surface format failed: %s (%d)", __FUNCTION__, strerror(-res), res);
- jniThrowRuntimeException(env, "Failed to query Surface format");
- return 0;
+ // Query surface format if no valid user format is specified, otherwise, override surface format
+ // with user format.
+ if (userFormat == IMAGE_FORMAT_UNKNOWN) {
+ if ((res = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &surfaceFormat)) != OK) {
+ ALOGE("%s: Query Surface format failed: %s (%d)", __FUNCTION__, strerror(-res), res);
+ jniThrowRuntimeException(env, "Failed to query Surface format");
+ return 0;
+ }
+ } else {
+ surfaceFormat = userFormat;
}
- ctx->setBufferFormat(format);
- env->SetIntField(thiz, gImageWriterClassInfo.mWriterFormat, reinterpret_cast<jint>(format));
+ ctx->setBufferFormat(surfaceFormat);
+ env->SetIntField(thiz,
+ gImageWriterClassInfo.mWriterFormat, reinterpret_cast<jint>(surfaceFormat));
-
- if (!isFormatOpaque(format)) {
+ if (!isFormatOpaque(surfaceFormat)) {
res = native_window_set_usage(anw.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
if (res != OK) {
ALOGE("%s: Configure usage %08x for format %08x failed: %s (%d)",
__FUNCTION__, static_cast<unsigned int>(GRALLOC_USAGE_SW_WRITE_OFTEN),
- format, strerror(-res), res);
+ surfaceFormat, strerror(-res), res);
jniThrowRuntimeException(env, "Failed to SW_WRITE_OFTEN configure usage");
return 0;
}
@@ -784,7 +790,7 @@
static JNINativeMethod gImageWriterMethods[] = {
{"nativeClassInit", "()V", (void*)ImageWriter_classInit },
- {"nativeInit", "(Ljava/lang/Object;Landroid/view/Surface;I)J",
+ {"nativeInit", "(Ljava/lang/Object;Landroid/view/Surface;II)J",
(void*)ImageWriter_init },
{"nativeClose", "(J)V", (void*)ImageWriter_close },
{"nativeAttachAndQueueImage", "(JJIJIIII)I", (void*)ImageWriter_attachAndQueueImage },
diff --git a/media/jni/android_media_MediaDescrambler.cpp b/media/jni/android_media_MediaDescrambler.cpp
index f031dbb..85d33b7 100644
--- a/media/jni/android_media_MediaDescrambler.cpp
+++ b/media/jni/android_media_MediaDescrambler.cpp
@@ -54,11 +54,10 @@
}
static status_t getBufferAndSize(
- JNIEnv *env, jobject byteBuf, jint offset, size_t length,
+ JNIEnv *env, jobject byteBuf, jint offset, jint limit, size_t length,
void **outPtr, jbyteArray *outByteArray) {
void *ptr = env->GetDirectBufferAddress(byteBuf);
- size_t bufSize;
jbyteArray byteArray = NULL;
ScopedLocalRef<jclass> byteBufClass(env, env->FindClass("java/nio/ByteBuffer"));
@@ -78,13 +77,9 @@
jboolean isCopy;
ptr = env->GetByteArrayElements(byteArray, &isCopy);
-
- bufSize = (size_t) env->GetArrayLength(byteArray);
- } else {
- bufSize = (size_t) env->GetDirectBufferCapacity(byteBuf);
}
- if (length + offset > bufSize) {
+ if ((jint)length + offset > limit) {
if (byteArray != NULL) {
env->ReleaseByteArrayElements(byteArray, (jbyte *)ptr, 0);
}
@@ -294,7 +289,8 @@
static jint android_media_MediaDescrambler_native_descramble(
JNIEnv *env, jobject thiz, jbyte key, jint numSubSamples,
jintArray numBytesOfClearDataObj, jintArray numBytesOfEncryptedDataObj,
- jobject srcBuf, jint srcOffset, jobject dstBuf, jint dstOffset) {
+ jobject srcBuf, jint srcOffset, jint srcLimit,
+ jobject dstBuf, jint dstOffset, jint dstLimit) {
sp<JDescrambler> descrambler = getDescrambler(env, thiz);
if (descrambler == NULL) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -307,7 +303,7 @@
numBytesOfEncryptedDataObj, &subSamples);
if (totalLength < 0) {
jniThrowException(env, "java/lang/IllegalArgumentException",
- "Invalid sub sample info!");
+ "Invalid subsample info!");
return -1;
}
@@ -315,16 +311,23 @@
void *srcPtr = NULL, *dstPtr = NULL;
jbyteArray srcArray = NULL, dstArray = NULL;
status_t err = getBufferAndSize(
- env, srcBuf, srcOffset, totalLength, &srcPtr, &srcArray);
+ env, srcBuf, srcOffset, srcLimit, totalLength, &srcPtr, &srcArray);
if (err == OK) {
if (dstBuf == NULL) {
dstPtr = srcPtr;
} else {
err = getBufferAndSize(
- env, dstBuf, dstOffset, totalLength, &dstPtr, &dstArray);
+ env, dstBuf, dstOffset, dstLimit, totalLength, &dstPtr, &dstArray);
}
}
+
+ if (err != OK) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "Invalid buffer offset and/or size for subsamples!");
+ return -1;
+ }
+
Status status;
if (err == OK) {
status = descrambler->descramble(
@@ -394,7 +397,7 @@
(void *)android_media_MediaDescrambler_native_init },
{ "native_setup", "(Landroid/os/IBinder;)V",
(void *)android_media_MediaDescrambler_native_setup },
- { "native_descramble", "(BI[I[ILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;I)I",
+ { "native_descramble", "(BI[I[ILjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;II)I",
(void *)android_media_MediaDescrambler_native_descramble },
};
diff --git a/media/mca/samples/CameraEffectsRecordingSample/java/android/media/filterfw/samples/CameraEffectsRecordingSample.java b/media/mca/samples/CameraEffectsRecordingSample/java/android/media/filterfw/samples/CameraEffectsRecordingSample.java
index c0c3034..0b62bca 100644
--- a/media/mca/samples/CameraEffectsRecordingSample/java/android/media/filterfw/samples/CameraEffectsRecordingSample.java
+++ b/media/mca/samples/CameraEffectsRecordingSample/java/android/media/filterfw/samples/CameraEffectsRecordingSample.java
@@ -45,8 +45,8 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
- mRunButton = (Button) findViewById(R.id.runbutton);
- mCameraView = (SurfaceView) findViewById(R.id.cameraview);
+ mRunButton = findViewById(R.id.runbutton);
+ mCameraView = findViewById(R.id.cameraview);
mRunButton.setOnClickListener(mRunButtonClick);
Intent intent = getIntent();
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java b/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java
index 1a10d64..cce2acc 100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java
@@ -70,7 +70,7 @@
setContentView(R.layout.bassboosttest);
- mSessionText = (EditText) findViewById(R.id.sessionEdit);
+ mSessionText = findViewById(R.id.sessionEdit);
mSessionText.setOnKeyListener(mSessionKeyListener);
mSessionText.setText(Integer.toString(sSession));
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java b/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java
index 594e844..1731dba 100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java
@@ -73,9 +73,9 @@
ToggleButton button;
setContentView(R.layout.envreverbtest);
- ImageView playPause = (ImageView) findViewById(R.id.playPause1);
- ImageView stop = (ImageView) findViewById(R.id.stop1);
- textView = (TextView) findViewById(R.id.sessionText);
+ ImageView playPause = findViewById(R.id.playPause1);
+ ImageView stop = findViewById(R.id.stop1);
+ textView = findViewById(R.id.sessionText);
if (sPlayerController == null) {
sPlayerController = new SimplePlayer(this, R.id.playPause1, playPause,
R.id.stop1, stop, textView,
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java
index f30a26f..fd56956 100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java
@@ -72,7 +72,7 @@
setContentView(R.layout.equalizertest);
- mSessionText = (EditText) findViewById(R.id.sessionEdit);
+ mSessionText = findViewById(R.id.sessionEdit);
mSessionText.setOnKeyListener(mSessionKeyListener);
mSessionText.setText(Integer.toString(sSession));
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java
index bb32e6f..4f2180f 100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java
@@ -70,7 +70,7 @@
setContentView(R.layout.virtualizertest);
- mSessionText = (EditText) findViewById(R.id.sessionEdit);
+ mSessionText = findViewById(R.id.sessionEdit);
mSessionText.setOnKeyListener(mSessionKeyListener);
mSessionText.setText(Integer.toString(sSession));
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java
index 60583e0..7db1d8d 100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java
@@ -72,7 +72,7 @@
setContentView(R.layout.visualizertest);
- mSessionText = (EditText) findViewById(R.id.sessionEdit);
+ mSessionText = findViewById(R.id.sessionEdit);
mSessionText.setOnKeyListener(mSessionKeyListener);
mSessionText.setText(Integer.toString(sSession));
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewActivity.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewActivity.java
index c3dd842..963b20d 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewActivity.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewActivity.java
@@ -43,7 +43,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.surface_view_2);
- mSurfaceView = (SurfaceView) findViewById(R.id.surface_view);
+ mSurfaceView = findViewById(R.id.surface_view);
mSurfaceView.getHolder().addCallback(this);
//Acquire the full wake lock to keep the device up
diff --git a/media/tests/NativeMidiDemo/java/com/example/android/nativemididemo/NativeMidi.java b/media/tests/NativeMidiDemo/java/com/example/android/nativemididemo/NativeMidi.java
index 0969b10..b0ca0bb 100644
--- a/media/tests/NativeMidiDemo/java/com/example/android/nativemididemo/NativeMidi.java
+++ b/media/tests/NativeMidiDemo/java/com/example/android/nativemididemo/NativeMidi.java
@@ -269,12 +269,12 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
- mCallbackStatusTextView = (TextView) findViewById(R.id.callback_status);
- mJavaMidiStatusTextView = (TextView) findViewById(R.id.java_midi_status);
- mMessagesTextView = (TextView) findViewById(R.id.messages);
- mMessagesContainer = (TouchableScrollView) findViewById(R.id.messages_scroll);
- mMidiDevicesRadioGroup = (RadioGroup) findViewById(R.id.devices);
- RadioButton deviceNone = (RadioButton) findViewById(R.id.device_none);
+ mCallbackStatusTextView = findViewById(R.id.callback_status);
+ mJavaMidiStatusTextView = findViewById(R.id.java_midi_status);
+ mMessagesTextView = findViewById(R.id.messages);
+ mMessagesContainer = findViewById(R.id.messages_scroll);
+ mMidiDevicesRadioGroup = findViewById(R.id.devices);
+ RadioButton deviceNone = findViewById(R.id.device_none);
deviceNone.setOnClickListener(new MidiOutputPortSelector());
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
diff --git a/media/tests/ScoAudioTest/src/com/android/scoaudiotest/ScoAudioTest.java b/media/tests/ScoAudioTest/src/com/android/scoaudiotest/ScoAudioTest.java
index 7e21876..8427d16 100644
--- a/media/tests/ScoAudioTest/src/com/android/scoaudiotest/ScoAudioTest.java
+++ b/media/tests/ScoAudioTest/src/com/android/scoaudiotest/ScoAudioTest.java
@@ -97,8 +97,8 @@
setContentView(R.layout.scoaudiotest);
- mScoStateTxt = (TextView) findViewById(R.id.scoStateTxt);
- mVdStateTxt = (TextView) findViewById(R.id.vdStateTxt);
+ mScoStateTxt = findViewById(R.id.scoStateTxt);
+ mVdStateTxt = findViewById(R.id.vdStateTxt);
IntentFilter intentFilter =
new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
@@ -112,7 +112,7 @@
mMediaControllers[0] = new SimplePlayerController(this, R.id.playPause1, R.id.stop1,
R.raw.sine440_mo_16b_16k, AudioManager.STREAM_BLUETOOTH_SCO);
- TextView name = (TextView) findViewById(R.id.playPause1Text);
+ TextView name = findViewById(R.id.playPause1Text);
name.setText("VOICE_CALL stream");
mScoButton = (ToggleButton)findViewById(R.id.ForceScoButton);
@@ -135,7 +135,7 @@
mTtsParams.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,
UTTERANCE);
- mSpeakText = (EditText) findViewById(R.id.speakTextEdit);
+ mSpeakText = findViewById(R.id.speakTextEdit);
mSpeakText.setOnKeyListener(mSpeakKeyListener);
mSpeakText.setText("sco audio test sentence");
mTtsToFileButton = (ToggleButton)findViewById(R.id.TtsToFileButton);
@@ -143,7 +143,7 @@
mTtsToFile = true;
mTtsToFileButton.setChecked(mTtsToFile);
- mModeSpinner = (Spinner) findViewById(R.id.modeSpinner);
+ mModeSpinner = findViewById(R.id.modeSpinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, mModeStrings);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
@@ -208,12 +208,12 @@
mForceScoOn = isChecked;
AudioManager mngr = mAudioManager;
boolean useVirtualCall = false;
- CheckBox box = (CheckBox) findViewById(R.id.useSecondAudioManager);
+ CheckBox box = findViewById(R.id.useSecondAudioManager);
if (box.isChecked()) {
Log.i(TAG, "Using 2nd audio manager");
mngr = mAudioManager2;
}
- box = (CheckBox) findViewById(R.id.useVirtualCallCheckBox);
+ box = findViewById(R.id.useVirtualCallCheckBox);
useVirtualCall = box.isChecked();
if (mForceScoOn) {
@@ -278,8 +278,8 @@
mPlayPauseButtonId = playPausebuttonId;
mStopButtonId = stopButtonId;
mFileNameBase = fileName;
- mPlayPauseButton = (ImageButton) findViewById(playPausebuttonId);
- ImageButton stop = (ImageButton) findViewById(stopButtonId);
+ mPlayPauseButton = findViewById(playPausebuttonId);
+ ImageButton stop = findViewById(stopButtonId);
mPlayPauseButton.setOnClickListener(this);
mPlayPauseButton.requestFocus();
@@ -294,8 +294,8 @@
mStopButtonId = stopButtonId;
mFileNameBase = "";
mFileResId = fileResId;
- mPlayPauseButton = (ImageButton) findViewById(playPausebuttonId);
- ImageButton stop = (ImageButton) findViewById(stopButtonId);
+ mPlayPauseButton = findViewById(playPausebuttonId);
+ ImageButton stop = findViewById(stopButtonId);
mPlayPauseButton.setOnClickListener(this);
mPlayPauseButton.requestFocus();
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 5843637..eacda93 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -14,7 +14,7 @@
// The headers module is in frameworks/native/Android.bp.
ndk_library {
- name: "libandroid.ndk",
+ name: "libandroid",
symbol_file: "libandroid.map.txt",
first_version: "9",
unversioned_until: "current",
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index 17feb53..d456950 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -14,7 +14,7 @@
// The headers module is in frameworks/native/Android.bp.
ndk_library {
- name: "libjnigraphics.ndk",
+ name: "libjnigraphics",
symbol_file: "libjnigraphics.map.txt",
first_version: "9",
unversioned_until: "current",
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index 7fa5736..9fa7a664 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -173,13 +173,13 @@
setContentView(layoutId);
// Same resource IDs for each layout variant (backup / restore)
- mStatusView = (TextView) findViewById(R.id.package_name);
- mAllowButton = (Button) findViewById(R.id.button_allow);
- mDenyButton = (Button) findViewById(R.id.button_deny);
+ mStatusView = findViewById(R.id.package_name);
+ mAllowButton = findViewById(R.id.button_allow);
+ mDenyButton = findViewById(R.id.button_deny);
- mCurPassword = (TextView) findViewById(R.id.password);
- mEncPassword = (TextView) findViewById(R.id.enc_password);
- TextView curPwDesc = (TextView) findViewById(R.id.password_desc);
+ mCurPassword = findViewById(R.id.password);
+ mEncPassword = findViewById(R.id.enc_password);
+ TextView curPwDesc = findViewById(R.id.password_desc);
mAllowButton.setOnClickListener(new View.OnClickListener() {
@Override
@@ -214,7 +214,7 @@
curPwDesc.setVisibility(View.GONE);
mCurPassword.setVisibility(View.GONE);
if (layoutId == R.layout.confirm_backup) {
- TextView encPwDesc = (TextView) findViewById(R.id.enc_password_desc);
+ TextView encPwDesc = findViewById(R.id.enc_password_desc);
if (mIsEncrypted) {
encPwDesc.setText(R.string.backup_enc_password_required);
monitorEncryptionPassword();
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 6394c64..5d20cf3 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -117,7 +117,7 @@
}
mCm.registerNetworkCallback(builder.build(), mNetworkCallback);
- final WebView myWebView = (WebView) findViewById(R.id.webview);
+ final WebView myWebView = findViewById(R.id.webview);
myWebView.clearCache(true);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
@@ -184,7 +184,7 @@
@Override
public void onBackPressed() {
- WebView myWebView = (WebView) findViewById(R.id.webview);
+ WebView myWebView = findViewById(R.id.webview);
if (myWebView.canGoBack() && mWebViewClient.allowBack()) {
myWebView.goBack();
} else {
@@ -326,7 +326,7 @@
// For internally generated pages, leave URL bar listing prior URL as this is the URL
// the page refers to.
if (!url.startsWith(INTERNAL_ASSETS)) {
- final TextView myUrlBar = (TextView) findViewById(R.id.url_bar);
+ final TextView myUrlBar = findViewById(R.id.url_bar);
myUrlBar.setText(url);
}
testForCaptivePortal();
@@ -407,7 +407,7 @@
private class MyWebChromeClient extends WebChromeClient {
@Override
public void onProgressChanged(WebView view, int newProgress) {
- final ProgressBar myProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
+ final ProgressBar myProgressBar = findViewById(R.id.progress_bar);
myProgressBar.setProgress(newProgress);
}
}
diff --git a/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml b/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
index e78fca3..0492685 100644
--- a/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
@@ -7,12 +7,9 @@
<string name="no_data_notification_id" msgid="668400731803969521">"Mobilni podaci su deaktivirani"</string>
<string name="portal_notification_detail" msgid="2295729385924660881">"Dodirnite da biste posetili veb-sajt %s"</string>
<string name="no_data_notification_detail" msgid="3112125343857014825">"Kontaktirajte dobavljača usluge %s"</string>
- <!-- no translation found for action_bar_label (4290345990334377177) -->
- <skip />
- <!-- no translation found for ssl_error_warning (3127935140338254180) -->
- <skip />
- <!-- no translation found for ssl_error_example (6188711843183058764) -->
- <skip />
- <!-- no translation found for ssl_error_continue (1138548463994095584) -->
- <skip />
+ <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"Status mobilnih podataka"</string>
+ <string name="action_bar_label" msgid="4290345990334377177">"Prijavite se na mobilnu mrežu"</string>
+ <string name="ssl_error_warning" msgid="3127935140338254180">"Mreža kojoj pokušavate da se pridružite ima bezbednosnih problema."</string>
+ <string name="ssl_error_example" msgid="6188711843183058764">"Na primer, stranica za prijavljivanje možda ne pripada prikazanoj organizaciji."</string>
+ <string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi preko pregledača"</string>
</resources>
diff --git a/packages/CarrierDefaultApp/res/values-be/strings.xml b/packages/CarrierDefaultApp/res/values-be/strings.xml
index c46d0da..12677f2 100644
--- a/packages/CarrierDefaultApp/res/values-be/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-be/strings.xml
@@ -7,12 +7,9 @@
<string name="no_data_notification_id" msgid="668400731803969521">"Перадача мабільных даных была дэактывавана"</string>
<string name="portal_notification_detail" msgid="2295729385924660881">"Дакраніцеся, каб наведаць вэб-сайт %s"</string>
<string name="no_data_notification_detail" msgid="3112125343857014825">"Звярніцеся да свайго пастаўшчыка паслуг %s"</string>
- <!-- no translation found for action_bar_label (4290345990334377177) -->
- <skip />
- <!-- no translation found for ssl_error_warning (3127935140338254180) -->
- <skip />
- <!-- no translation found for ssl_error_example (6188711843183058764) -->
- <skip />
- <!-- no translation found for ssl_error_continue (1138548463994095584) -->
- <skip />
+ <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"Статус мабільнага трафіка"</string>
+ <string name="action_bar_label" msgid="4290345990334377177">"Увайсці ў мабільную сетку"</string>
+ <string name="ssl_error_warning" msgid="3127935140338254180">"У сеткі, да якой вы спрабуеце далучыцца, ёсць праблемы з бяспекай."</string>
+ <string name="ssl_error_example" msgid="6188711843183058764">"Напрыклад, старонка ўваходу можа не належаць указанай арганізацыі."</string>
+ <string name="ssl_error_continue" msgid="1138548463994095584">"Усё роўна працягнуць праз браўзер"</string>
</resources>
diff --git a/packages/CarrierDefaultApp/res/values-bs/strings.xml b/packages/CarrierDefaultApp/res/values-bs/strings.xml
index ba9863f..ec0a3a5 100644
--- a/packages/CarrierDefaultApp/res/values-bs/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bs/strings.xml
@@ -7,12 +7,9 @@
<string name="no_data_notification_id" msgid="668400731803969521">"Prijenos mobilnih podataka je deaktiviran"</string>
<string name="portal_notification_detail" msgid="2295729385924660881">"Dodirnite da posjetite %s web lokaciju"</string>
<string name="no_data_notification_detail" msgid="3112125343857014825">"Obratite se pružaocu usluga %s"</string>
- <!-- no translation found for action_bar_label (4290345990334377177) -->
- <skip />
- <!-- no translation found for ssl_error_warning (3127935140338254180) -->
- <skip />
- <!-- no translation found for ssl_error_example (6188711843183058764) -->
- <skip />
- <!-- no translation found for ssl_error_continue (1138548463994095584) -->
- <skip />
+ <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"Status mobilnih podataka"</string>
+ <string name="action_bar_label" msgid="4290345990334377177">"Prijavite se na mobilnu mrežu"</string>
+ <string name="ssl_error_warning" msgid="3127935140338254180">"Mreža kojoj pokušavate pristupiti ima sigurnosnih problema."</string>
+ <string name="ssl_error_example" msgid="6188711843183058764">"Naprimjer, stranica za prijavljivanje možda ne pripada prikazanoj organizaciji."</string>
+ <string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi preko preglednika"</string>
</resources>
diff --git a/packages/CarrierDefaultApp/res/values-gu/strings.xml b/packages/CarrierDefaultApp/res/values-gu/strings.xml
index 0d19811..9f68aa4 100644
--- a/packages/CarrierDefaultApp/res/values-gu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-gu/strings.xml
@@ -7,8 +7,7 @@
<string name="no_data_notification_id" msgid="668400731803969521">"તમારો મોબાઇલ ડેટા નિષ્ક્રિય કરવામાં આવ્યો છે"</string>
<string name="portal_notification_detail" msgid="2295729385924660881">"%s વેબસાઇટની મુલાકાત લેવા માટે ટૅપ કરો"</string>
<string name="no_data_notification_detail" msgid="3112125343857014825">"કૃપા કરીને તમારા સેવા પ્રદાતા %sનો સંપર્ક કરો"</string>
- <!-- no translation found for mobile_data_status_notification_channel_name (833999690121305708) -->
- <skip />
+ <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"મોબાઇલ ડેટાની સ્થિતિ"</string>
<string name="action_bar_label" msgid="4290345990334377177">"મોબાઇલ નેટવર્કમાં સાઇન ઇન કરો"</string>
<string name="ssl_error_warning" msgid="3127935140338254180">"તમે જોડાવાનો પ્રયાસ કરી રહ્યા છો તે નેટવર્કમાં સુરક્ષા સંબંધી સમસ્યાઓ છે."</string>
<string name="ssl_error_example" msgid="6188711843183058764">"ઉદાહરણ તરીકે, લોગિન પૃષ્ઠ બતાવવામાં આવેલી સંસ્થાનું ન પણ હોય."</string>
diff --git a/packages/CarrierDefaultApp/res/values-iw/strings.xml b/packages/CarrierDefaultApp/res/values-iw/strings.xml
index e220b692..ca42d33 100644
--- a/packages/CarrierDefaultApp/res/values-iw/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-iw/strings.xml
@@ -7,8 +7,7 @@
<string name="no_data_notification_id" msgid="668400731803969521">"חבילת הגלישה שלך הושבתה"</string>
<string name="portal_notification_detail" msgid="2295729385924660881">"הקש כדי לעבור לאתר של %s"</string>
<string name="no_data_notification_detail" msgid="3112125343857014825">"פנה לספק השירות %s"</string>
- <!-- no translation found for mobile_data_status_notification_channel_name (833999690121305708) -->
- <skip />
+ <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"סטטוס חבילת הגלישה"</string>
<string name="action_bar_label" msgid="4290345990334377177">"היכנס לרשת סלולרית"</string>
<string name="ssl_error_warning" msgid="3127935140338254180">"יש בעיות אבטחה ברשת שאליה אתה מנסה להתחבר."</string>
<string name="ssl_error_example" msgid="6188711843183058764">"לדוגמה, ייתכן שדף ההתחברות אינו שייך לארגון המוצג."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ky/strings.xml b/packages/CarrierDefaultApp/res/values-ky/strings.xml
index d638e60..19ad94e 100644
--- a/packages/CarrierDefaultApp/res/values-ky/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ky/strings.xml
@@ -7,7 +7,7 @@
<string name="no_data_notification_id" msgid="668400731803969521">"Мобилдик дайындарды колдонуу өчүрүлгөн"</string>
<string name="portal_notification_detail" msgid="2295729385924660881">"%s сайтына баш багуу үчүн басыңыз"</string>
<string name="no_data_notification_detail" msgid="3112125343857014825">"%s Интернет провайдери менен байланышыңыз"</string>
- <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"Мобилдик түзмөктүн статусу"</string>
+ <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"Мобилдик Интернеттин абалы"</string>
<string name="action_bar_label" msgid="4290345990334377177">"Мобилдик тармакка кирүү"</string>
<string name="ssl_error_warning" msgid="3127935140338254180">"Кошулайын деген тармагыңызда коопсуздук көйгөйлөрү бар."</string>
<string name="ssl_error_example" msgid="6188711843183058764">"Мисалы, каттоо эсебине кирүү баракчасы көрсөтүлгөн уюмга таандык эмес болушу мүмкүн."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mr/strings.xml b/packages/CarrierDefaultApp/res/values-mr/strings.xml
index a04ae31..53d7400 100644
--- a/packages/CarrierDefaultApp/res/values-mr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mr/strings.xml
@@ -7,8 +7,7 @@
<string name="no_data_notification_id" msgid="668400731803969521">"आपला मोबाइल डेटा निष्क्रिय केला गेला"</string>
<string name="portal_notification_detail" msgid="2295729385924660881">"%s वेबसाइटला भेट देण्यासाठी टॅप करा"</string>
<string name="no_data_notification_detail" msgid="3112125343857014825">"कृपया आपल्या %s सेवा प्रदात्याशी संपर्क साधा"</string>
- <!-- no translation found for mobile_data_status_notification_channel_name (833999690121305708) -->
- <skip />
+ <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"मोबाइल डेटा स्थिती"</string>
<string name="action_bar_label" msgid="4290345990334377177">"मोबाइल नेटवर्कमध्ये साइन इन करा"</string>
<string name="ssl_error_warning" msgid="3127935140338254180">"आपण ज्या नेटवर्कमध्ये सामील होण्याचा प्रयत्न करत आहात त्यात सुरक्षितता समस्या आहेत."</string>
<string name="ssl_error_example" msgid="6188711843183058764">"उदाहरणार्थ, लॉग इन पृष्ठ दर्शवलेल्या संस्थेच्या मालकीचे नसू शकते."</string>
diff --git a/packages/CarrierDefaultApp/res/values-nb/strings.xml b/packages/CarrierDefaultApp/res/values-nb/strings.xml
index d032bda..57d58a5 100644
--- a/packages/CarrierDefaultApp/res/values-nb/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-nb/strings.xml
@@ -7,8 +7,7 @@
<string name="no_data_notification_id" msgid="668400731803969521">"Mobildata er deaktivert"</string>
<string name="portal_notification_detail" msgid="2295729385924660881">"Trykk for å besøke %s-nettstedet"</string>
<string name="no_data_notification_detail" msgid="3112125343857014825">"Ta kontakt med tjenesteleverandøren din, %s"</string>
- <!-- no translation found for mobile_data_status_notification_channel_name (833999690121305708) -->
- <skip />
+ <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"Status for mobildata"</string>
<string name="action_bar_label" msgid="4290345990334377177">"Logg på mobilnettverk"</string>
<string name="ssl_error_warning" msgid="3127935140338254180">"Nettverket du prøver å logge på, har sikkerhetsproblemer."</string>
<string name="ssl_error_example" msgid="6188711843183058764">"Det er for eksempel mulig at påloggingssiden ikke tilhører organisasjonen som vises."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ne/strings.xml b/packages/CarrierDefaultApp/res/values-ne/strings.xml
index 694adfe..1070a62 100644
--- a/packages/CarrierDefaultApp/res/values-ne/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ne/strings.xml
@@ -7,8 +7,7 @@
<string name="no_data_notification_id" msgid="668400731803969521">"तपाईंको मोबाइल डेटा निष्क्रिय पारिएको छ"</string>
<string name="portal_notification_detail" msgid="2295729385924660881">"%s वेबसाइटमा जानका लागि ट्याप गर्नुहोस्"</string>
<string name="no_data_notification_detail" msgid="3112125343857014825">"कृपया आफ्नो सेवा प्रदायक %s लाई सम्पर्क गर्नुहोस्"</string>
- <!-- no translation found for mobile_data_status_notification_channel_name (833999690121305708) -->
- <skip />
+ <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"मोबाइल डेटाको स्थिति"</string>
<string name="action_bar_label" msgid="4290345990334377177">"मोबाइल नेटवर्कमा साइन इन गर्नुहोस्"</string>
<string name="ssl_error_warning" msgid="3127935140338254180">"तपाईंले सामेल हुने प्रयास गरिरहनु भएको नेटवर्कमा सुरक्षा सम्बन्धी समस्याहरू छन्।"</string>
<string name="ssl_error_example" msgid="6188711843183058764">"उदाहरणका लागि, लग इन पृष्ठ देखाइएको संस्थाको नहुन सक्छ।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pa/strings.xml b/packages/CarrierDefaultApp/res/values-pa/strings.xml
index a069240..6b754c1 100644
--- a/packages/CarrierDefaultApp/res/values-pa/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pa/strings.xml
@@ -7,7 +7,7 @@
<string name="no_data_notification_id" msgid="668400731803969521">"ਤੁਹਾਡਾ ਮੋਬਾਈਲ ਡੈਟਾ ਅਕਿਰਿਆਸ਼ੀਲ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ"</string>
<string name="portal_notification_detail" msgid="2295729385924660881">"%s ਵੈੱਬਸਾਈਟ \'ਤੇ ਜਾਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="no_data_notification_detail" msgid="3112125343857014825">"ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੇ ਸੇਵਾ ਪ੍ਰਦਾਨਕ %s ਨੂੰ ਸੰਪਰਕ ਕਰੋ"</string>
- <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"ਮੋਬਾਈਲ ਡੈਟੇ ਦੀ ਸਥਿਤੀ"</string>
+ <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"ਮੋਬਾਈਲ ਡੈਟੇ ਦੀ ਅਵਸਥਾ"</string>
<string name="action_bar_label" msgid="4290345990334377177">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਵਿੱਚ ਸਾਈਨ-ਇਨ ਕਰੋ"</string>
<string name="ssl_error_warning" msgid="3127935140338254180">"ਤੁਸੀਂ ਜਿਸ ਨੈੱਟਵਰਕ ਵਿੱਚ ਸ਼ਾਮਲ ਹੋਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰ ਰਹੇ ਹੋ ਉਸ ਵਿੱਚ ਸੁਰੱਖਿਆ ਸਬੰਧੀ ਸਮੱਸਿਆਵਾਂ ਹਨ।"</string>
<string name="ssl_error_example" msgid="6188711843183058764">"ਉਦਾਹਰਣ ਵਜੋਂ, ਹੋ ਸਕਦਾ ਹੈ ਲੌਗਇਨ ਪੰਨਾ ਦਿਖਾਈ ਗਈ ਸੰਸਥਾ ਨਾਲ ਸਬੰਧਿਤ ਨਾ ਹੋਵੇ।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-si/strings.xml b/packages/CarrierDefaultApp/res/values-si/strings.xml
index 108c3e2..a31e5c4 100644
--- a/packages/CarrierDefaultApp/res/values-si/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-si/strings.xml
@@ -7,8 +7,7 @@
<string name="no_data_notification_id" msgid="668400731803969521">"ඔබගේ ජංගම දත්ත අක්රිය කර ඇත"</string>
<string name="portal_notification_detail" msgid="2295729385924660881">"%s වෙබ් අඩවිය වෙත යාමට තට්ටු කරන්න"</string>
<string name="no_data_notification_detail" msgid="3112125343857014825">"කරුණාකර ඔබගේ සේවා සැපයුම්කරු %s අමතන්න"</string>
- <!-- no translation found for mobile_data_status_notification_channel_name (833999690121305708) -->
- <skip />
+ <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"ජංගම දත්ත තත්ත්වය"</string>
<string name="action_bar_label" msgid="4290345990334377177">"ජංගම ජාලය වෙත පුරනය වෙන්න"</string>
<string name="ssl_error_warning" msgid="3127935140338254180">"ඔබ සම්බන්ධ වීමට උත්සහ කරන ජාලයේ ආරක්ෂක ගැටළු ඇත."</string>
<string name="ssl_error_example" msgid="6188711843183058764">"උදාහරණයක් ලෙස, පුරනය වන පිටුව පෙන්වා ඇති සංවිධානයට අයිති නැති විය හැක."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ur/strings.xml b/packages/CarrierDefaultApp/res/values-ur/strings.xml
index 0627a8d..f5fbdc8 100644
--- a/packages/CarrierDefaultApp/res/values-ur/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ur/strings.xml
@@ -7,8 +7,7 @@
<string name="no_data_notification_id" msgid="668400731803969521">"آپ کا موبائل ڈیٹا غیر فعال کر دیا گیا ہے"</string>
<string name="portal_notification_detail" msgid="2295729385924660881">"%s ویب سائٹ ملاحظہ کرنے کیلئے تھپتھپائیں"</string>
<string name="no_data_notification_detail" msgid="3112125343857014825">"براہ کرم اپنے خدمت کے فراہم کنندہ %s سے رابطہ کریں"</string>
- <!-- no translation found for mobile_data_status_notification_channel_name (833999690121305708) -->
- <skip />
+ <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"موبائل ڈیٹا کی صورت حال"</string>
<string name="action_bar_label" msgid="4290345990334377177">"موبائل نیٹ ورک میں سائن ان کریں"</string>
<string name="ssl_error_warning" msgid="3127935140338254180">"آپ جس نیٹ ورک میں شامل ہونے کی کوشش کر رہے ہیں، اس میں سیکیورٹی کے مسائل ہیں۔"</string>
<string name="ssl_error_example" msgid="6188711843183058764">"مثال کے طور پر ہو سکتا ہے کہ لاگ ان صفحہ دکھائی گئی تنظیم سے تعلق نہ رکھتا ہو۔"</string>
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
index a5820f2..6276ce3 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -91,7 +91,7 @@
setContentView(R.layout.activity_captive_portal_login);
getActionBar().setDisplayShowHomeEnabled(false);
- mWebView = (WebView) findViewById(R.id.webview);
+ mWebView = findViewById(R.id.webview);
mWebView.clearCache(true);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
@@ -113,7 +113,7 @@
@Override
public void onBackPressed() {
- WebView myWebView = (WebView) findViewById(R.id.webview);
+ WebView myWebView = findViewById(R.id.webview);
if (myWebView.canGoBack() && mWebViewClient.allowBack()) {
myWebView.goBack();
} else {
@@ -328,7 +328,7 @@
// For internally generated pages, leave URL bar listing prior URL as this is the URL
// the page refers to.
if (!url.startsWith(INTERNAL_ASSETS)) {
- final TextView myUrlBar = (TextView) findViewById(R.id.url_bar);
+ final TextView myUrlBar = findViewById(R.id.url_bar);
myUrlBar.setText(url);
}
if (mNetwork != null) {
@@ -412,7 +412,7 @@
private class MyWebChromeClient extends WebChromeClient {
@Override
public void onProgressChanged(WebView view, int newProgress) {
- final ProgressBar myProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
+ final ProgressBar myProgressBar = findViewById(R.id.progress_bar);
myProgressBar.setProgress(newProgress);
}
}
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
index 14b9de5..76a64e5 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
@@ -65,7 +65,7 @@
} else {
setContentView(R.layout.device_chooser);
setTitle(Html.fromHtml(getString(R.string.chooser_title, getCallingAppName()), 0));
- mDeviceListView = (ListView) findViewById(R.id.device_list);
+ mDeviceListView = findViewById(R.id.device_list);
final DeviceDiscoveryService.DevicesAdapter adapter = getService().mDevicesAdapter;
mDeviceListView.setAdapter(adapter);
adapter.registerDataSetObserver(new DataSetObserver() {
@@ -101,7 +101,7 @@
@Override
public void setTitle(CharSequence title) {
- final TextView titleView = (TextView) findViewById(R.id.title);
+ final TextView titleView = findViewById(R.id.title);
final int padding = getPadding(getResources());
titleView.setPadding(padding, padding, padding, padding);
titleView.setText(title);
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
index f59f0d9..689e381 100644
--- a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
+++ b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
@@ -82,7 +82,7 @@
mPrefs = new PrefState(this);
mPrefs.setListener(this);
- final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.holder);
+ final RecyclerView recyclerView = findViewById(R.id.holder);
mAdapter = new CatAdapter();
recyclerView.setAdapter(mAdapter);
recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
diff --git a/packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml b/packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml
index 9d2f7bb..235b621 100644
--- a/packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml
@@ -17,8 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Spoljna memorija"</string>
- <!-- no translation found for storage_description (8541974407321172792) -->
- <skip />
+ <string name="storage_description" msgid="8541974407321172792">"Lokalni memorijski prostor"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Interna memorija"</string>
<string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-be/strings.xml b/packages/ExternalStorageProvider/res/values-be/strings.xml
index ea8837b..911ff54 100644
--- a/packages/ExternalStorageProvider/res/values-be/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-be/strings.xml
@@ -17,8 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Вонкавае сховішча"</string>
- <!-- no translation found for storage_description (8541974407321172792) -->
- <skip />
+ <string name="storage_description" msgid="8541974407321172792">"Лакальнае сховішча"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Унутранае сховішча"</string>
<string name="root_documents" msgid="4051252304075469250">"Дакументы"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-bs/strings.xml b/packages/ExternalStorageProvider/res/values-bs/strings.xml
index 194e66b..1eb3020 100644
--- a/packages/ExternalStorageProvider/res/values-bs/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-bs/strings.xml
@@ -17,8 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7123375275748530234">"Aplikacija za vanjsku pohranu"</string>
- <!-- no translation found for storage_description (8541974407321172792) -->
- <skip />
+ <string name="storage_description" msgid="8541974407321172792">"Lokalna pohrana"</string>
<string name="root_internal_storage" msgid="827844243068584127">"Interna pohrana"</string>
<string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
</resources>
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index e60b5a9..db88f2c 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -509,7 +509,7 @@
final DeviceToolkit toolkit =
new DeviceToolkit(mMtpManager, mResolver, mDatabase, device);
mDeviceToolkits.put(deviceId, toolkit);
- mIntentSender.sendUpdateNotificationIntent(device);
+ mIntentSender.sendUpdateNotificationIntent(getOpenedDeviceRecordsCache());
try {
mRootScanner.resume().await();
} catch (InterruptedException error) {
@@ -524,9 +524,9 @@
void closeDevice(int deviceId) throws IOException, InterruptedException {
synchronized (mDeviceListLock) {
closeDeviceInternal(deviceId);
+ mIntentSender.sendUpdateNotificationIntent(getOpenedDeviceRecordsCache());
}
mRootScanner.resume();
- mIntentSender.sendUpdateNotificationIntent(null);
}
MtpDeviceRecord[] getOpenedDeviceRecordsCache() {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
index 664d3c9..fa1a12030 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsService.java
@@ -16,13 +16,17 @@
package com.android.mtp;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.Notification;
import android.app.Service;
import android.app.NotificationManager;
-import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
+import android.os.Parcelable;
import android.service.notification.StatusBarNotification;
+import android.util.Log;
+import com.android.internal.util.Preconditions;
import java.util.HashSet;
import java.util.Set;
@@ -33,7 +37,8 @@
*/
public class MtpDocumentsService extends Service {
static final String ACTION_UPDATE_NOTIFICATION = "com.android.mtp.UPDATE_NOTIFICATION";
- static final String EXTRA_DEVICE = "device";
+ static final String EXTRA_DEVICE_IDS = "deviceIds";
+ static final String EXTRA_DEVICE_NOTIFICATIONS = "deviceNotifications";
private NotificationManager mNotificationManager;
@@ -53,7 +58,12 @@
public int onStartCommand(Intent intent, int flags, int startId) {
// If intent is null, the service was restarted.
if (intent == null || ACTION_UPDATE_NOTIFICATION.equals(intent.getAction())) {
- return updateForegroundState() ? START_STICKY : START_NOT_STICKY;
+ final int[] ids = intent.hasExtra(EXTRA_DEVICE_IDS) ?
+ intent.getExtras().getIntArray(EXTRA_DEVICE_IDS) : null;
+ final Notification[] notifications = intent.hasExtra(EXTRA_DEVICE_NOTIFICATIONS) ?
+ castToNotifications(intent.getExtras().getParcelableArray(
+ EXTRA_DEVICE_NOTIFICATIONS)) : null;
+ return updateForegroundState(ids, notifications) ? START_STICKY : START_NOT_STICKY;
}
return START_NOT_STICKY;
}
@@ -62,35 +72,38 @@
* Updates the foreground state of the service.
* @return Whether the service is foreground or not.
*/
- private boolean updateForegroundState() {
- final MtpDocumentsProvider provider = MtpDocumentsProvider.getInstance();
+ private boolean updateForegroundState(
+ @Nullable int[] ids, @Nullable Notification[] notifications) {
final Set<Integer> openedNotification = new HashSet<>();
- boolean hasForegroundNotification = false;
+ final int size = ids != null ? ids.length : 0;
+ if (size != 0) {
+ Preconditions.checkArgument(ids != null);
+ Preconditions.checkArgument(notifications != null);
+ Preconditions.checkArgument(ids.length == notifications.length);
+ }
+
+ for (int i = 0; i < size; i++) {
+ if (i == 0) {
+ // Mark this service as foreground with the notification so that the process is
+ // not killed by the system while a MTP device is opened.
+ startForeground(ids[i], notifications[i]);
+ } else {
+ // Only one notification can be shown as a foreground notification. We need to
+ // show the rest as normal notification.
+ mNotificationManager.notify(ids[i], notifications[i]);
+ }
+ openedNotification.add(ids[i]);
+ }
final StatusBarNotification[] activeNotifications =
mNotificationManager.getActiveNotifications();
-
- for (final MtpDeviceRecord record : provider.getOpenedDeviceRecordsCache()) {
- openedNotification.add(record.deviceId);
- if (!hasForegroundNotification) {
- // Mark this service as foreground with the notification so that the process is not
- // killed by the system while a MTP device is opened.
- startForeground(record.deviceId, createNotification(this, record));
- hasForegroundNotification = true;
- } else {
- // Only one notification can be shown as a foreground notification. We need to show
- // the rest as normal notification.
- mNotificationManager.notify(record.deviceId, createNotification(this, record));
- }
- }
-
for (final StatusBarNotification notification : activeNotifications) {
if (!openedNotification.contains(notification.getId())) {
mNotificationManager.cancel(notification.getId());
}
}
- if (!hasForegroundNotification) {
+ if (size == 0) {
// There is no opened device.
stopForeground(true /* removeNotification */);
stopSelf();
@@ -100,17 +113,12 @@
return true;
}
- public static Notification createNotification(Context context, MtpDeviceRecord device) {
- final String title = context.getResources().getString(
- R.string.accessing_notification_title,
- device.name);
- return new Notification.Builder(context)
- .setLocalOnly(true)
- .setContentTitle(title)
- .setSmallIcon(com.android.internal.R.drawable.stat_sys_data_usb)
- .setCategory(Notification.CATEGORY_SYSTEM)
- .setPriority(Notification.PRIORITY_LOW)
- .setFlag(Notification.FLAG_NO_CLEAR, true)
- .build();
+ private static @NonNull Notification[] castToNotifications(@NonNull Parcelable[] src) {
+ Preconditions.checkNotNull(src);
+ final Notification[] notifications = new Notification[src.length];
+ for (int i = 0; i < src.length; i++) {
+ notifications[i] = (Notification) src[i];
+ }
+ return notifications;
}
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java b/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
index d8c3d35..c5292b8 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
@@ -16,11 +16,12 @@
package com.android.mtp;
-import android.annotation.Nullable;
-import android.app.NotificationManager;
+import android.annotation.NonNull;
+import android.app.Notification;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import com.android.internal.util.Preconditions;
/**
* Sends intent to MtpDocumentsService.
@@ -34,20 +35,38 @@
/**
* Notify the change of opened device set.
- * @param record If a new device is opened, pass the device record. If a device is closed, pass
- * null.
+ * @param records List of opened devices. Can be empty.
*/
- void sendUpdateNotificationIntent(@Nullable MtpDeviceRecord record) {
+ void sendUpdateNotificationIntent(@NonNull MtpDeviceRecord[] records) {
+ Preconditions.checkNotNull(records);
final Intent intent = new Intent(MtpDocumentsService.ACTION_UPDATE_NOTIFICATION);
intent.setComponent(new ComponentName(mContext, MtpDocumentsService.class));
- final NotificationManager manager = mContext.getSystemService(NotificationManager.class);
- if (record != null) {
- manager.startServiceInForeground(
- intent,
- record.deviceId,
- MtpDocumentsService.createNotification(mContext, record));
+ if (records.length != 0) {
+ final int[] ids = new int[records.length];
+ final Notification[] notifications = new Notification[records.length];
+ for (int i = 0; i < records.length; i++) {
+ ids[i] = records[i].deviceId;
+ notifications[i] = createNotification(mContext, records[i]);
+ }
+ intent.putExtra(MtpDocumentsService.EXTRA_DEVICE_IDS, ids);
+ intent.putExtra(MtpDocumentsService.EXTRA_DEVICE_NOTIFICATIONS, notifications);
+ mContext.startForegroundService(intent);
} else {
mContext.startService(intent);
}
}
+
+ private static Notification createNotification(Context context, MtpDeviceRecord device) {
+ final String title = context.getResources().getString(
+ R.string.accessing_notification_title,
+ device.name);
+ return new Notification.Builder(context)
+ .setLocalOnly(true)
+ .setContentTitle(title)
+ .setSmallIcon(com.android.internal.R.drawable.stat_sys_data_usb)
+ .setCategory(Notification.CATEGORY_SYSTEM)
+ .setPriority(Notification.PRIORITY_LOW)
+ .setFlag(Notification.FLAG_NO_CLEAR, true)
+ .build();
+ }
}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestServiceIntentSender.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestServiceIntentSender.java
index 74dd429..ed2dc38 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestServiceIntentSender.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestServiceIntentSender.java
@@ -16,13 +16,11 @@
package com.android.mtp;
-import android.annotation.Nullable;
-
class TestServiceIntentSender extends ServiceIntentSender {
TestServiceIntentSender() {
super(null);
}
@Override
- void sendUpdateNotificationIntent(@Nullable MtpDeviceRecord record) {}
+ void sendUpdateNotificationIntent(MtpDeviceRecord[] record) {}
}
diff --git a/packages/Osu/src/com/android/hotspot2/app/MainActivity.java b/packages/Osu/src/com/android/hotspot2/app/MainActivity.java
index ae0a45c..7fd2238 100644
--- a/packages/Osu/src/com/android/hotspot2/app/MainActivity.java
+++ b/packages/Osu/src/com/android/hotspot2/app/MainActivity.java
@@ -123,7 +123,7 @@
if (osuData.size() > 0) {
noOsuView.setVisibility(View.GONE);
osuListAdapter = new OsuListAdapter(this, osuData);
- osuListView = (ListView) findViewById(R.id.profile_list);
+ osuListView = findViewById(R.id.profile_list);
osuListView.setAdapter(osuListAdapter);
osuListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUWebView.java b/packages/Osu/src/com/android/hotspot2/osu/OSUWebView.java
index afbd0d1..a6778c8 100644
--- a/packages/Osu/src/com/android/hotspot2/osu/OSUWebView.java
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUWebView.java
@@ -37,7 +37,7 @@
setContentView(R.layout.osu_web_view);
getActionBar().setDisplayShowHomeEnabled(false);
- final WebView myWebView = (WebView) findViewById(R.id.webview);
+ final WebView myWebView = findViewById(R.id.webview);
myWebView.clearCache(true);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
diff --git a/packages/PrintSpooler/res/values-af/strings.xml b/packages/PrintSpooler/res/values-af/strings.xml
index e0702af..5b8a341 100644
--- a/packages/PrintSpooler/res/values-af/strings.xml
+++ b/packages/PrintSpooler/res/values-af/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Meer inligting oor hierdie drukker"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Druktake wat tans loop"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Mislukte druktake"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Kon nie lêer skep nie"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Sommige drukdienste is gedeaktiveer"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Soek tans vir drukkers"</string>
diff --git a/packages/PrintSpooler/res/values-am/strings.xml b/packages/PrintSpooler/res/values-am/strings.xml
index b8e595e..832b855 100644
--- a/packages/PrintSpooler/res/values-am/strings.xml
+++ b/packages/PrintSpooler/res/values-am/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ተጨማሪ የዚህ አታሚ መረጃ"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"የህትመት ስራዎችን በማሄድ ላይ"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"የህትመት ስራዎች አልተሳኩም"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"ፋይል መፍጠር አልተቻለም"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"አንዳንድ የህትመት አገልግሎቶች ተሰናክለዋል"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"አታሚዎችን በመፈለግ ላይ"</string>
diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml
index cbbd017..eab784d 100644
--- a/packages/PrintSpooler/res/values-ar/strings.xml
+++ b/packages/PrintSpooler/res/values-ar/strings.xml
@@ -65,10 +65,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"مزيد من المعلومات حول هذه الطابعة"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"مهام الطباعة الجارية"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"مهام الطباعة التي تعذَّر تنفيذها"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"تعذَّر إنشاء الملف"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"بعض خدمات الطباعة معطَّلة"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"البحث عن طابعات"</string>
diff --git a/packages/PrintSpooler/res/values-az/strings.xml b/packages/PrintSpooler/res/values-az/strings.xml
index e57a9e7..4193afc 100644
--- a/packages/PrintSpooler/res/values-az/strings.xml
+++ b/packages/PrintSpooler/res/values-az/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Bu printer haqqında daha ətraflı məlumat"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Çap işləri çalışır"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Çap işləri alınmadı"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Fayl yaradıla bilmədi"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Bəzi çap xidmətləri deaktiv edilib."</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Printer axtarılır"</string>
diff --git a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
index 2b1b8ca..49fe52b 100644
--- a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
+++ b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
@@ -62,6 +62,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Još informacija o ovom štampaču"</string>
+ <string name="notification_channel_progress" msgid="872788690775721436">"Aktivni zadaci štampanja"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Neuspeli zadaci štampanja"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Pravljenje datoteke nije uspelo"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Neke usluge štampanja su onemogućene"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Pretraga štampača"</string>
diff --git a/packages/PrintSpooler/res/values-be/strings.xml b/packages/PrintSpooler/res/values-be/strings.xml
index 83d0627..c04756c 100644
--- a/packages/PrintSpooler/res/values-be/strings.xml
+++ b/packages/PrintSpooler/res/values-be/strings.xml
@@ -63,6 +63,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Больш падрабязная інфармацыя пра гэты прынтар"</string>
+ <string name="notification_channel_progress" msgid="872788690775721436">"Заданні друку, якія выконваюцца"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Заданні друку са збоямі"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Не ўдалося стварыць файл"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Некаторыя службы друку адключаны"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Пошук прынтараў"</string>
diff --git a/packages/PrintSpooler/res/values-bg/strings.xml b/packages/PrintSpooler/res/values-bg/strings.xml
index 4f1c598..d44b4ce 100644
--- a/packages/PrintSpooler/res/values-bg/strings.xml
+++ b/packages/PrintSpooler/res/values-bg/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Още информация за този принтер"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Активни задания за отпечатване"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Неуспешни задания за отпечатване"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Файлът не можа да бъде създаден"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Някои услуги за отпечатване са деактивирани"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Търсене на принтери"</string>
diff --git a/packages/PrintSpooler/res/values-bn/strings.xml b/packages/PrintSpooler/res/values-bn/strings.xml
index 33e4794..88ba6ee 100644
--- a/packages/PrintSpooler/res/values-bn/strings.xml
+++ b/packages/PrintSpooler/res/values-bn/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"এই মুদ্রকটির বিষয়ে আরো তথ্য"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"এগুলি প্রিন্ট হচ্ছে"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"এগুলি প্রিন্ট করা যায়নি"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"ফাইল তৈরি করা গেল না"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"কিছু মুদ্রণ পরিষেবা অক্ষম করা আছে"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"মুদ্রকগুলি অনুসন্ধান করা হচ্ছে"</string>
diff --git a/packages/PrintSpooler/res/values-bs/strings.xml b/packages/PrintSpooler/res/values-bs/strings.xml
index 2450be3..d3f1b80 100644
--- a/packages/PrintSpooler/res/values-bs/strings.xml
+++ b/packages/PrintSpooler/res/values-bs/strings.xml
@@ -62,6 +62,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Više informacija o ovom štampaču"</string>
+ <string name="notification_channel_progress" msgid="872788690775721436">"Tekući zadaci za štampanje"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Neizvršeni zadaci za štampanje"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Nije uspjelo kreiranje fajla"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Neke usluge za štampanje su isključene"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Traženje štampača"</string>
diff --git a/packages/PrintSpooler/res/values-ca/strings.xml b/packages/PrintSpooler/res/values-ca/strings.xml
index fa6cfeb..361e420 100644
--- a/packages/PrintSpooler/res/values-ca/strings.xml
+++ b/packages/PrintSpooler/res/values-ca/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Més informació sobre aquesta impressora"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Tasques d\'impressió actives"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Tasques d\'impressió amb problemes"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"No s\'ha pogut crear el fitxer"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Alguns serveis d\'impressió estan desactivats"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Cerca d\'impressores"</string>
diff --git a/packages/PrintSpooler/res/values-cs/strings.xml b/packages/PrintSpooler/res/values-cs/strings.xml
index 4647c1a..1f38e3c 100644
--- a/packages/PrintSpooler/res/values-cs/strings.xml
+++ b/packages/PrintSpooler/res/values-cs/strings.xml
@@ -63,10 +63,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Další informace o této tiskárně"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Spuštěné tiskové úlohy"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Nezdařené tiskové úlohy"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Soubor nelze vytvořit"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Některé tiskové služby nejsou aktivovány"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Vyhledávání tiskáren"</string>
diff --git a/packages/PrintSpooler/res/values-da/strings.xml b/packages/PrintSpooler/res/values-da/strings.xml
index f0a5be6..5f116dc 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Flere oplysninger om denne printer"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Aktive udskriftsjobs"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Mislykkede udskriftsjobs"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Filen kunne ikke oprettes"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Nogle udskrivningstjenester er deaktiveret"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Søger efter printere"</string>
diff --git a/packages/PrintSpooler/res/values-de/strings.xml b/packages/PrintSpooler/res/values-de/strings.xml
index b482350..c02e3c7 100644
--- a/packages/PrintSpooler/res/values-de/strings.xml
+++ b/packages/PrintSpooler/res/values-de/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Weitere Informationen über diesen Drucker"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Laufende Druckaufträge"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Fehlgeschlagene Druckaufträge"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Datei konnte nicht erstellt werden"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Einige Druckdienste sind deaktiviert"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Suche nach Druckern"</string>
diff --git a/packages/PrintSpooler/res/values-el/strings.xml b/packages/PrintSpooler/res/values-el/strings.xml
index ea1477e..9021f7c 100644
--- a/packages/PrintSpooler/res/values-el/strings.xml
+++ b/packages/PrintSpooler/res/values-el/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Περισσότερες πληροφορίες σχετικά με αυτόν τον εκτυπωτή"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Εργασίες εκτύπωσης σε εξέλιξη"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Αποτυχημένες εργασίες εκτύπωσης"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Δεν ήταν δυνατή η δημιουργία του αρχείου"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Ορισμένες υπηρ. εκτύπωσης είναι απενεργοποιημένες"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Αναζήτηση για εκτυπωτές"</string>
diff --git a/packages/PrintSpooler/res/values-en-rAU/strings.xml b/packages/PrintSpooler/res/values-en-rAU/strings.xml
index 5939182..7fbfeb3 100644
--- a/packages/PrintSpooler/res/values-en-rAU/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rAU/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"More information about this printer"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Running print jobs"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Failed print jobs"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Could not create file"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Some print services are disabled"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Searching for printers"</string>
diff --git a/packages/PrintSpooler/res/values-en-rGB/strings.xml b/packages/PrintSpooler/res/values-en-rGB/strings.xml
index 5939182..7fbfeb3 100644
--- a/packages/PrintSpooler/res/values-en-rGB/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rGB/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"More information about this printer"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Running print jobs"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Failed print jobs"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Could not create file"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Some print services are disabled"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Searching for printers"</string>
diff --git a/packages/PrintSpooler/res/values-en-rIN/strings.xml b/packages/PrintSpooler/res/values-en-rIN/strings.xml
index 5939182..7fbfeb3 100644
--- a/packages/PrintSpooler/res/values-en-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rIN/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"More information about this printer"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Running print jobs"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Failed print jobs"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Could not create file"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Some print services are disabled"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Searching for printers"</string>
diff --git a/packages/PrintSpooler/res/values-es-rUS/strings.xml b/packages/PrintSpooler/res/values-es-rUS/strings.xml
index 7ee41ee..441ae73 100644
--- a/packages/PrintSpooler/res/values-es-rUS/strings.xml
+++ b/packages/PrintSpooler/res/values-es-rUS/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Más información sobre esta impresora"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Trabajos de impresión activos"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Trabajos de impresión con errores"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"No se pudo crear el archivo"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Hay servicios de impresión inhabilitados"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Buscando impresoras"</string>
diff --git a/packages/PrintSpooler/res/values-es/strings.xml b/packages/PrintSpooler/res/values-es/strings.xml
index f970b83..c1ff282 100644
--- a/packages/PrintSpooler/res/values-es/strings.xml
+++ b/packages/PrintSpooler/res/values-es/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Más información sobre esta impresora"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Trabajos de impresión activos"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Trabajos de impresión con errores"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"No se ha podido crear el archivo"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Algunos servicios de impresión están inhabilitados"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Buscando impresoras"</string>
diff --git a/packages/PrintSpooler/res/values-et/strings.xml b/packages/PrintSpooler/res/values-et/strings.xml
index 92979e9..eebc569 100644
--- a/packages/PrintSpooler/res/values-et/strings.xml
+++ b/packages/PrintSpooler/res/values-et/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Lisateave selle printeri kohta"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Toimivad printimistööd"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Ebaõnnestunud printimistööd"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Faili ei õnnestunud luua"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Mõned printimisteenused on keelatud"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Printerite otsimine"</string>
diff --git a/packages/PrintSpooler/res/values-eu/strings.xml b/packages/PrintSpooler/res/values-eu/strings.xml
index df34e73..8fdea1f 100644
--- a/packages/PrintSpooler/res/values-eu/strings.xml
+++ b/packages/PrintSpooler/res/values-eu/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Informazio gehiago inprimagailuari buruz"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Abian diren inprimatze-lanak"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Huts egin duten inprimatze-lanak"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Ezin izan da sortu fitxategia"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Desgaituta daude inprimatzeko zerbitzu batzuk"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Inprimagailuak bilatzen"</string>
diff --git a/packages/PrintSpooler/res/values-fa/strings.xml b/packages/PrintSpooler/res/values-fa/strings.xml
index 06cdc23..596947d 100644
--- a/packages/PrintSpooler/res/values-fa/strings.xml
+++ b/packages/PrintSpooler/res/values-fa/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"اطلاعات بیشتر درباره چاپگر"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"کارهای چاپی درحال اجرا"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"کارهای چاپی ناموفق"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"فایل ایجاد نشد"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"بعضی از خدمات چاپ غیرفعال هستند"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"درحال جستجوی چاپگرها"</string>
diff --git a/packages/PrintSpooler/res/values-fi/strings.xml b/packages/PrintSpooler/res/values-fi/strings.xml
index 53b9695..724d1d7 100644
--- a/packages/PrintSpooler/res/values-fi/strings.xml
+++ b/packages/PrintSpooler/res/values-fi/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Lisätietoja tästä tulostimesta"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Käynnissä olevat tulostustyöt"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Epäonnistuneet tulostustyöt"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Tiedoston luominen epäonnistui."</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Osa tulostuspalveluista on poistettu käytöstä."</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Etsitään tulostimia"</string>
diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
index a483b9a..9329d2a 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Plus d\'information sur cette imprimante"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Tâches d\'impression en cours"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Tâches d\'impression échouées"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Impossible de créer le fichier"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Certains services d\'impression sont désactivés"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Recherche d\'imprimantes en cours..."</string>
diff --git a/packages/PrintSpooler/res/values-fr/strings.xml b/packages/PrintSpooler/res/values-fr/strings.xml
index 56920a42..d2a477d 100644
--- a/packages/PrintSpooler/res/values-fr/strings.xml
+++ b/packages/PrintSpooler/res/values-fr/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Plus d\'informations sur cette imprimante"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Tâches d\'impression en cours"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Tâches d\'impression non abouties"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Impossible de créer le fichier"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Certains services d\'impression sont désactivés."</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Recherche d\'imprimantes en cours"</string>
diff --git a/packages/PrintSpooler/res/values-gl/strings.xml b/packages/PrintSpooler/res/values-gl/strings.xml
index 75df019..4019d8d 100644
--- a/packages/PrintSpooler/res/values-gl/strings.xml
+++ b/packages/PrintSpooler/res/values-gl/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Máis información sobre esta impresora"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Executando traballos de impresión"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Erro nos traballos de impresión"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Non se puido crear o arquivo"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Algúns servizos de impresión están desactivados"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Busca de impresoras"</string>
diff --git a/packages/PrintSpooler/res/values-gu/strings.xml b/packages/PrintSpooler/res/values-gu/strings.xml
index 292c4fa..f5d698d 100644
--- a/packages/PrintSpooler/res/values-gu/strings.xml
+++ b/packages/PrintSpooler/res/values-gu/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"આ પ્રિન્ટર વિશે વધુ માહિતી"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"ચાલી રહેલા છાપવાનાં કાર્યો"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"નિષ્ફળ થયેલ છાપવાના કાર્યો"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"ફાઇલ બનાવી શક્યાં નથી"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"કેટલીક છાપવાની સેવાઓ અક્ષમ કરેલ છે"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"પ્રિન્ટર્સ માટે શોધી રહ્યું છે"</string>
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index 82dadcd..809431d 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"इस प्रिंटर के बारे में अधिक जानकारी"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"चल रहे प्रिंट कार्य"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"असफल रहे प्रिंट कार्य"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"फ़ाइल नहीं बनाई जा सकी"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"कुछ प्रिंट सेवाएं अक्षम हैं"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिंटर खोज रहा है"</string>
diff --git a/packages/PrintSpooler/res/values-hr/strings.xml b/packages/PrintSpooler/res/values-hr/strings.xml
index d657c51..217dbaa 100644
--- a/packages/PrintSpooler/res/values-hr/strings.xml
+++ b/packages/PrintSpooler/res/values-hr/strings.xml
@@ -62,10 +62,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Više informacija o ovom pisaču"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Zadaci ispisa u tijeku"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Neuspjeli zadaci ispisa"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Izrada datoteke nije uspjela"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Neke su usluge ispisa onemogućene"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Traženje pisača"</string>
diff --git a/packages/PrintSpooler/res/values-hu/strings.xml b/packages/PrintSpooler/res/values-hu/strings.xml
index 4b25171..b9a0d9d 100644
--- a/packages/PrintSpooler/res/values-hu/strings.xml
+++ b/packages/PrintSpooler/res/values-hu/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"További információ erről a nyomtatóról"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Folyamatban lévő nyomtatási feladatok"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Nem sikerült nyomtatási feladatok"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Nem sikerült létrehozni a fájlt"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Egyes nyomtatási szolgáltatások le vannak tiltva"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Nyomtatók keresése"</string>
diff --git a/packages/PrintSpooler/res/values-hy/strings.xml b/packages/PrintSpooler/res/values-hy/strings.xml
index 1162cb1..56045be 100644
--- a/packages/PrintSpooler/res/values-hy/strings.xml
+++ b/packages/PrintSpooler/res/values-hy/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Հավելյալ տեղեկություններ այս տպիչի մասին"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Ընթացիկ տպելու առաջադրանքները"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Ձախողված տպելու առաջադրանքները"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Չհաջողվեց ստեղծել ֆայլ"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Տպելու որոշ ծառայությունները կասեցված են"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Տպիչների որոնում"</string>
diff --git a/packages/PrintSpooler/res/values-in/strings.xml b/packages/PrintSpooler/res/values-in/strings.xml
index 9139f02..1e536f1 100644
--- a/packages/PrintSpooler/res/values-in/strings.xml
+++ b/packages/PrintSpooler/res/values-in/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Informasi selengkapnya tentang printer ini"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Menjalankan proses pencetakan"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Proses pencetakan yang gagal"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Tidak dapat membuat file"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Beberapa layanan cetak dinonaktifkan"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Mencari printer"</string>
diff --git a/packages/PrintSpooler/res/values-is/strings.xml b/packages/PrintSpooler/res/values-is/strings.xml
index 419ba60..eb7f01d 100644
--- a/packages/PrintSpooler/res/values-is/strings.xml
+++ b/packages/PrintSpooler/res/values-is/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Frekari upplýsingar um þennan prentara"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Prentverk í gangi"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Prentverk sem mistókust"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Ekki tókst að búa til skrá"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Hluti prentþjónustunnar er óvirkur"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Leitar að prentara"</string>
diff --git a/packages/PrintSpooler/res/values-it/strings.xml b/packages/PrintSpooler/res/values-it/strings.xml
index 84e3145..d898b1e 100644
--- a/packages/PrintSpooler/res/values-it/strings.xml
+++ b/packages/PrintSpooler/res/values-it/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Ulteriori informazioni su questa stampante"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Processi di stampa in esecuzione"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Processi di stampa non riusciti"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Impossibile creare il file"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Alcuni servizi di stampa sono disattivati"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Ricerca di stampanti"</string>
diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml
index 6227f46..7448079 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -63,10 +63,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"מידע נוסף על מדפסת זו"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"עבודות הדפסה פועלות"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"עבודות הדפסה שנכשלו"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"לא ניתן היה ליצור קובץ"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"שירותי הדפסה מסוימים מושבתים"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"מחפש מדפסות"</string>
diff --git a/packages/PrintSpooler/res/values-ja/strings.xml b/packages/PrintSpooler/res/values-ja/strings.xml
index 7e6f5e4..8529606 100644
--- a/packages/PrintSpooler/res/values-ja/strings.xml
+++ b/packages/PrintSpooler/res/values-ja/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"このプリンタの詳細"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"アクティブな印刷ジョブ"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"エラーが発生した印刷ジョブ"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"ファイルを作成できませんでした"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"一部の印刷サービスは無効になっています"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"プリンタの検索中"</string>
diff --git a/packages/PrintSpooler/res/values-ka/strings.xml b/packages/PrintSpooler/res/values-ka/strings.xml
index edfab76..f11c0e1 100644
--- a/packages/PrintSpooler/res/values-ka/strings.xml
+++ b/packages/PrintSpooler/res/values-ka/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> — <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"დამატებითი ინფორმაცია ამ პრინტერის შესახებ"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"ბეჭდვის გაშვებული დავალებები"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"ბეჭდვის შეუსრულებელი დავალებები"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"ფაილი ვერ შეიქმნა"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"ბეჭდვის ზოგიერთი სერვისი გათიშულია"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"მიმდინარეობს პრინტერების ძიება"</string>
diff --git a/packages/PrintSpooler/res/values-kk/strings.xml b/packages/PrintSpooler/res/values-kk/strings.xml
index 59b0cd0..a822d1c 100644
--- a/packages/PrintSpooler/res/values-kk/strings.xml
+++ b/packages/PrintSpooler/res/values-kk/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Осы принтер туралы қосымша ақпарат"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Басып шығару тапсырмасы орындалуда"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Басып шығару тапсырмасы орындалмады"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Файл жасалмады"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Кейбір басып шығару қызметтері өшірілген."</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Принтерлерді іздеу"</string>
diff --git a/packages/PrintSpooler/res/values-km/strings.xml b/packages/PrintSpooler/res/values-km/strings.xml
index 8072600..4409856 100644
--- a/packages/PrintSpooler/res/values-km/strings.xml
+++ b/packages/PrintSpooler/res/values-km/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ព័ត៌មានបន្ថែមអំពីម៉ាស៊ីបោះពុម្ពនេះ"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"កំពុងបោះពុម្ព"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"មិនអាចបោះពុម្ពបាន"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"មិនអាចបង្កើតឯកសារបានទេ"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"សេវាកម្មបោះពុម្ពមួយចំនួនត្រូវបានបិទដំណើរការ"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ស្វែងរកម៉ាស៊ីនបោះពុម្ព"</string>
diff --git a/packages/PrintSpooler/res/values-kn/strings.xml b/packages/PrintSpooler/res/values-kn/strings.xml
index e01dcf7b..c8eaf6e 100644
--- a/packages/PrintSpooler/res/values-kn/strings.xml
+++ b/packages/PrintSpooler/res/values-kn/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ಈ ಪ್ರಿಂಟರ್ ಬಗ್ಗೆ ಇನ್ನಷ್ಟು ಮಾಹಿತಿ"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"ಜಾರಿಯಲ್ಲಿರುವ ಮುದ್ರಣ ಕಾರ್ಯಗಳು"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"ವಿಫಲಗೊಂಡಿರುವ ಮುದ್ರಣ ಕಾರ್ಯಗಳು"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"ಫೈಲ್ ರಚಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"ಕೆಲವು ಮುದ್ರಣ ಸೇವೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ಪ್ರಿಂಟರ್ಗಳಿಗಾಗಿ ಹುಡುಕಲಾಗುತ್ತಿದೆ"</string>
diff --git a/packages/PrintSpooler/res/values-ko/strings.xml b/packages/PrintSpooler/res/values-ko/strings.xml
index 36d25fb..8219b5b 100644
--- a/packages/PrintSpooler/res/values-ko/strings.xml
+++ b/packages/PrintSpooler/res/values-ko/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"이 프린터에 대한 정보 더보기"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"실행 중인 인쇄 작업"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"실패한 인쇄 작업"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"파일을 만들 수 없습니다."</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"프린트 서비스 일부가 사용 중지되었습니다."</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"프린터 검색 중"</string>
diff --git a/packages/PrintSpooler/res/values-ky/strings.xml b/packages/PrintSpooler/res/values-ky/strings.xml
index 06cf8df..655201e 100644
--- a/packages/PrintSpooler/res/values-ky/strings.xml
+++ b/packages/PrintSpooler/res/values-ky/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Бул принтер жөнүндө көбүрөөк маалымат"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Басып чыгаруу тапшырмалары аткарылууда"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Басып чыгарылбай калган тапшырмалар"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Файл түзүлбөй койду"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Басып чыгаруу кызматтарынын айрымы өчүрүлгөн"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Принтерлер изделүүдө"</string>
diff --git a/packages/PrintSpooler/res/values-lo/strings.xml b/packages/PrintSpooler/res/values-lo/strings.xml
index 79b4fff..cee6376 100644
--- a/packages/PrintSpooler/res/values-lo/strings.xml
+++ b/packages/PrintSpooler/res/values-lo/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ຂໍ້ມູນເພີ່ມເຕີມກ່ຽວກັບເຄື່ອງພິມນີ້"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"ກຳລັງແລ່ນວຽກ"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"ພິມວຽກບໍ່ສຳເລັດ"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"ບໍ່ສາມາດສ້າງໄຟລ໌ໄດ້"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"ບາງການບໍລິການພິມຖືກປິດການນຳໃຊ້"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ກຳລັງຊອກຫາເຄື່ອງພິມ"</string>
diff --git a/packages/PrintSpooler/res/values-lt/strings.xml b/packages/PrintSpooler/res/values-lt/strings.xml
index b174341..9ed807f 100644
--- a/packages/PrintSpooler/res/values-lt/strings.xml
+++ b/packages/PrintSpooler/res/values-lt/strings.xml
@@ -63,10 +63,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"„<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g>“ – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Daugiau informacijos apie šį spausdintuvą"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Vykdomos spausdinimo užduotys"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Spausdinimo užduotys su triktimis"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Nepavyko sukurti failo"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Kai kurios spausdinimo paslaugos išjungtos"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Ieškoma spausdintuvų"</string>
diff --git a/packages/PrintSpooler/res/values-lv/strings.xml b/packages/PrintSpooler/res/values-lv/strings.xml
index 92b5d0e..bf9fb3b 100644
--- a/packages/PrintSpooler/res/values-lv/strings.xml
+++ b/packages/PrintSpooler/res/values-lv/strings.xml
@@ -62,10 +62,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> — <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Plašāka informācija par šo printeri"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Tiek veikti drukas darbi"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Neizdevās veikt drukas darbus"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Nevarēja izveidot failu."</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Daži drukas pakalpojumi ir atspējoti."</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Printeru meklēšana"</string>
diff --git a/packages/PrintSpooler/res/values-mk/strings.xml b/packages/PrintSpooler/res/values-mk/strings.xml
index 302f87f..11d7867 100644
--- a/packages/PrintSpooler/res/values-mk/strings.xml
+++ b/packages/PrintSpooler/res/values-mk/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Повеќе информации за овој печатач"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Тековни работи за печатење"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Неуспешни работи за печатење"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Не можеше да се создаде датотека"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Некои услуги за печатење се оневозможени"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Пребарување печатачи"</string>
diff --git a/packages/PrintSpooler/res/values-ml/strings.xml b/packages/PrintSpooler/res/values-ml/strings.xml
index e6add8c..05be7a7 100644
--- a/packages/PrintSpooler/res/values-ml/strings.xml
+++ b/packages/PrintSpooler/res/values-ml/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ഈ പ്രിന്ററിനെ കുറിച്ചുള്ള കൂടുതൽ വിവരങ്ങൾ"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"നടന്നുകൊണ്ടിരിക്കുന്ന പ്രിന്റ് ജോലികൾ"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"പരാജയപ്പെട്ട പ്രിന്റ് ജോലികൾ"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"ഫയൽ സൃഷ്ടിക്കാൻ കഴിഞ്ഞില്ല"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"ചില പ്രിന്റ് സേവനങ്ങൾ പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"പ്രിന്ററുകൾക്കായി തിരയുന്നു"</string>
diff --git a/packages/PrintSpooler/res/values-mn/strings.xml b/packages/PrintSpooler/res/values-mn/strings.xml
index b7d33bb..fa99354 100644
--- a/packages/PrintSpooler/res/values-mn/strings.xml
+++ b/packages/PrintSpooler/res/values-mn/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Энэ хэвлэгчийн талаарх дэлгэрэнгүй мэдээлэл"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Хэвлэж байна"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Хэвлэж чадсангүй"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Файл үүсгэж чадсангүй"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Зарим хэвлэх үйлчилгээг идэвхгүй болгосон байна"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Принтер хайж байна"</string>
diff --git a/packages/PrintSpooler/res/values-mr/strings.xml b/packages/PrintSpooler/res/values-mr/strings.xml
index 482c085..8981cd8 100644
--- a/packages/PrintSpooler/res/values-mr/strings.xml
+++ b/packages/PrintSpooler/res/values-mr/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"या प्रिंटर विषयी अधिक माहिती"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"प्रिंट कार्ये चालवणे"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"अयशस्वी प्रिंट कार्ये"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"फाईल तयार करणेे शक्य झाले नाही"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"काही मुद्रण सेवा अक्षम केल्या आहेत"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिंटर शोधत आहे"</string>
diff --git a/packages/PrintSpooler/res/values-ms/strings.xml b/packages/PrintSpooler/res/values-ms/strings.xml
index 65f2622..75ff205 100644
--- a/packages/PrintSpooler/res/values-ms/strings.xml
+++ b/packages/PrintSpooler/res/values-ms/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Maklumat lanjut tentang pencetak ini"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Tugas cetak yang sedang berjalan"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Tugas cetak yang gagal"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Tidak dapat membuat fail"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Sesetengah perkhidmatan cetak dilumpuhkan"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Mencari pencetak"</string>
diff --git a/packages/PrintSpooler/res/values-my/strings.xml b/packages/PrintSpooler/res/values-my/strings.xml
index 87c0b88..c581e59 100644
--- a/packages/PrintSpooler/res/values-my/strings.xml
+++ b/packages/PrintSpooler/res/values-my/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ဤပရင်တာ အကြောင်း ပိုမိုလေ့လာပါ"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"လုပ်နေဆဲ ပရင့်ထုတ်မှုများ"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"မအောင်မြင်သည့် ပရင့်ထုတ်မှုများ"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"ဖိုင်အမည်ကို ထည့်၍မရပါ"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"အချို့ပုံနှိပ်ဝန်ဆောင်မှုများကို ပိတ်ထားပါသည်"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"စာထုတ်စက်များကို ရှာနေပါသည်"</string>
diff --git a/packages/PrintSpooler/res/values-nb/strings.xml b/packages/PrintSpooler/res/values-nb/strings.xml
index 884e873..6b04c2e 100644
--- a/packages/PrintSpooler/res/values-nb/strings.xml
+++ b/packages/PrintSpooler/res/values-nb/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Mer informasjon om denne printeren"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Utskriftsjobber som er i gang"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Mislykkede utskriftsjobber"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Kunne ikke opprette filen"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Noen utskriftstjenester er slått av"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Søker etter skrivere"</string>
diff --git a/packages/PrintSpooler/res/values-ne/strings.xml b/packages/PrintSpooler/res/values-ne/strings.xml
index e746b34..c5f5978 100644
--- a/packages/PrintSpooler/res/values-ne/strings.xml
+++ b/packages/PrintSpooler/res/values-ne/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"यस प्रिन्टरको बारेमा थप जानकारी"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"चलिरहेका छपाइका कार्यहरू"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"कार्यहरूलाई छाप्न सकिएन"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"फाइल सिर्जना गर्न सकिएन"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"केही मुद्रण सम्बन्धी सेवाहरूलाई असक्षम गरिएको छ"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिन्टरहरू खोज्दै"</string>
diff --git a/packages/PrintSpooler/res/values-nl/strings.xml b/packages/PrintSpooler/res/values-nl/strings.xml
index 7f41bb5..8048914 100644
--- a/packages/PrintSpooler/res/values-nl/strings.xml
+++ b/packages/PrintSpooler/res/values-nl/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Meer informatie over deze printer"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Actieve afdruktaken"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Mislukte afdruktaken"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Kan bestand niet maken"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Sommige afdrukservices zijn uitgeschakeld"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Printers zoeken"</string>
diff --git a/packages/PrintSpooler/res/values-pa/strings.xml b/packages/PrintSpooler/res/values-pa/strings.xml
index c5d9bf4..d7885ad 100644
--- a/packages/PrintSpooler/res/values-pa/strings.xml
+++ b/packages/PrintSpooler/res/values-pa/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ਇਸ ਪ੍ਰਿੰਟਰ ਬਾਰੇ ਹੋਰ ਜਾਣਕਾਰੀ"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"ਚੱਲ ਰਹੇ ਪ੍ਰਿੰਟ ਕਾਰਜ"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"ਅਸਫਲ ਰਹੇ ਪ੍ਰਿੰਟ ਕਾਰਜ"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"ਫ਼ਾਈਲ ਨੂੰ ਬਣਾਇਆ ਨਹੀਂ ਜਾ ਸਕਿਆ"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"ਕੁਝ ਪ੍ਰਿੰਟ ਸੇਵਾਵਾਂ ਅਯੋਗ ਬਣਾਈਆਂ ਗਈਆਂ ਹਨ"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ਪ੍ਰਿੰਟਰ ਖੋਜ ਰਿਹਾ ਹੈ"</string>
diff --git a/packages/PrintSpooler/res/values-pl/strings.xml b/packages/PrintSpooler/res/values-pl/strings.xml
index 2f0f983..a960fe2 100644
--- a/packages/PrintSpooler/res/values-pl/strings.xml
+++ b/packages/PrintSpooler/res/values-pl/strings.xml
@@ -63,10 +63,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Więcej informacji o tej drukarce"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Realizowane zadania drukowania"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Nieudane zadania drukowania"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Nie udało się utworzyć pliku"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Niektóre usługi drukowania są wyłączone"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Szukanie drukarek"</string>
diff --git a/packages/PrintSpooler/res/values-pt-rBR/strings.xml b/packages/PrintSpooler/res/values-pt-rBR/strings.xml
index 5c68daf..a2f5ab0 100644
--- a/packages/PrintSpooler/res/values-pt-rBR/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rBR/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Mais informações sobre essa impressora"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Executando trabalhos de impressão"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Falha em trabalhos de impressão"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Não foi possível criar o arquivo"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Alguns serviços de impressão estão desativados"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Procurando impressoras"</string>
diff --git a/packages/PrintSpooler/res/values-pt-rPT/strings.xml b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
index 86abd03..5da31bd 100644
--- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Mais informações acerca desta impressora"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Tarefas de impressão em execução"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Tarefas de impressão falhadas"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Não foi possível criar o ficheiro"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Alguns serviços de impressão estão desativados"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"A procurar impressoras"</string>
diff --git a/packages/PrintSpooler/res/values-pt/strings.xml b/packages/PrintSpooler/res/values-pt/strings.xml
index 5c68daf..a2f5ab0 100644
--- a/packages/PrintSpooler/res/values-pt/strings.xml
+++ b/packages/PrintSpooler/res/values-pt/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Mais informações sobre essa impressora"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Executando trabalhos de impressão"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Falha em trabalhos de impressão"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Não foi possível criar o arquivo"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Alguns serviços de impressão estão desativados"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Procurando impressoras"</string>
diff --git a/packages/PrintSpooler/res/values-ro/strings.xml b/packages/PrintSpooler/res/values-ro/strings.xml
index 0530fc4..e0fb0b8 100644
--- a/packages/PrintSpooler/res/values-ro/strings.xml
+++ b/packages/PrintSpooler/res/values-ro/strings.xml
@@ -62,10 +62,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Mai multe informații despre această imprimantă"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Sarcini de printare în rulare"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Sarcini de printare nereușite"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Fișierul nu a putut fi creat"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Unele servicii de printare sunt dezactivate"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Se caută imprimante"</string>
diff --git a/packages/PrintSpooler/res/values-ru/strings.xml b/packages/PrintSpooler/res/values-ru/strings.xml
index 33f3166..e0aef53 100644
--- a/packages/PrintSpooler/res/values-ru/strings.xml
+++ b/packages/PrintSpooler/res/values-ru/strings.xml
@@ -63,10 +63,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Подробные сведения о принтере"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Активные задания печати"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Проблемные задания печати"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Не удалось создать файл"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Некоторые службы печати отключены"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Поиск принтеров…"</string>
diff --git a/packages/PrintSpooler/res/values-si/strings.xml b/packages/PrintSpooler/res/values-si/strings.xml
index 56eb909..fe17ee0 100644
--- a/packages/PrintSpooler/res/values-si/strings.xml
+++ b/packages/PrintSpooler/res/values-si/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"මෙම මුද්රණ යන්ත්රය ගැන තවත් තොරතුරු"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"කෙරෙමින් පවතින මුද්රණ කාර්යයන්"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"අසාර්තක වූ මුද්රණ කාර්යයන්"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"ගොනුව සෑදීමට නොහැකි විය"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"සමහර මුද්රණ සේවා අබලයි"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"මුද්රණ යන්ත්ර සොයමින්"</string>
diff --git a/packages/PrintSpooler/res/values-sk/strings.xml b/packages/PrintSpooler/res/values-sk/strings.xml
index 4c480f0..17a029a 100644
--- a/packages/PrintSpooler/res/values-sk/strings.xml
+++ b/packages/PrintSpooler/res/values-sk/strings.xml
@@ -63,10 +63,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Ďalšie informácie o tejto tlačiarni"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Prebiehajúce tlačové úlohy"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Neúspešné tlačové úlohy"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Súbor nie je možné vytvoriť"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Niektoré tlačové služby sú zakázané"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Vyhľadávanie tlačiarní"</string>
diff --git a/packages/PrintSpooler/res/values-sl/strings.xml b/packages/PrintSpooler/res/values-sl/strings.xml
index 94202dd..3217756 100644
--- a/packages/PrintSpooler/res/values-sl/strings.xml
+++ b/packages/PrintSpooler/res/values-sl/strings.xml
@@ -63,10 +63,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Več informacij o tem tiskalniku"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Tiskalna opravila, ki se izvajajo"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Neuspela tiskalna opravila"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Datoteke ni bilo mogoče ustvariti"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Nekatere tiskalne storitve so onemogočene"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Iskanje tiskalnikov"</string>
diff --git a/packages/PrintSpooler/res/values-sq/strings.xml b/packages/PrintSpooler/res/values-sq/strings.xml
index c2d9480..0fd5cbb 100644
--- a/packages/PrintSpooler/res/values-sq/strings.xml
+++ b/packages/PrintSpooler/res/values-sq/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Më shumë informacione mbi këtë printer"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Punët e printimit që po ekzekutohen"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Punët e printimit që kanë dështuar"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Skedari nuk mund të krijohej"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Disa shërbime printimi janë çaktivizuar"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Po kërkon për printerë"</string>
diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml
index 372986d..c20a5af 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -62,10 +62,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Још информација о овом штампачу"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Активни задаци штампања"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Неуспели задаци штампања"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Прављење датотеке није успело"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Неке услуге штампања су онемогућене"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Претрага штампача"</string>
diff --git a/packages/PrintSpooler/res/values-sv/strings.xml b/packages/PrintSpooler/res/values-sv/strings.xml
index a769a6e..9dac4cc 100644
--- a/packages/PrintSpooler/res/values-sv/strings.xml
+++ b/packages/PrintSpooler/res/values-sv/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Mer information om den här skrivaren"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Utskriftsjobb som pågår"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Utskriftsjobb som misslyckats"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Det gick inte att skapa filen"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Några utskriftstjänster har inaktiverats"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Söker efter skrivare"</string>
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index 2bee953..8aaf6f4 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Maelezo zaidi kuhusu printa hii"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Kazi ambazo zinachapishwa"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Kazi ambazo hazikuchapishwa"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Imeshindwa kuunda faili"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Baadhi ya huduma za uchapishaji haziruhusiwi"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Inatafuta printa"</string>
diff --git a/packages/PrintSpooler/res/values-ta/strings.xml b/packages/PrintSpooler/res/values-ta/strings.xml
index 124a1e6..47faf17 100644
--- a/packages/PrintSpooler/res/values-ta/strings.xml
+++ b/packages/PrintSpooler/res/values-ta/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"இந்தப் பிரிண்டர் பற்றிய கூடுதல் தகவல்"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"இயக்கத்திலுள்ள அச்சுப் பணிகள்"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"தோல்வியடைந்த அச்சுப் பணிகள்"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"கோப்பை உருவாக்க முடியவில்லை"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"சில அச்சுப் பொறிகள் முடக்கப்பட்டன"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"அச்சுப்பொறிகளைத் தேடுகிறது"</string>
diff --git a/packages/PrintSpooler/res/values-te/strings.xml b/packages/PrintSpooler/res/values-te/strings.xml
index f07f8f0..e5a0879 100644
--- a/packages/PrintSpooler/res/values-te/strings.xml
+++ b/packages/PrintSpooler/res/values-te/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ఈ ప్రింటర్ గురించి మరింత సమాచారం"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"జరుగుతున్న ముద్రణలు"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"విఫలమైన ముద్రణలు"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"ఫైల్ను సృష్టించలేకపోయాము"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"కొన్ని ముద్రణ సేవలు నిలిపివేయబడ్డాయి"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"ప్రింటర్ల కోసం శోధిస్తోంది"</string>
diff --git a/packages/PrintSpooler/res/values-th/strings.xml b/packages/PrintSpooler/res/values-th/strings.xml
index c230cac..5b73fa9 100644
--- a/packages/PrintSpooler/res/values-th/strings.xml
+++ b/packages/PrintSpooler/res/values-th/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"ข้อมูลเพิ่มเติมเกี่ยวกับเครื่องพิมพ์นี้"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"กำลังดำเนินการงานพิมพ์"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"งานพิมพ์ล้มเหลว"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"ไม่สามารถสร้างไฟล์ได้"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"บริการพิมพ์บางอย่างปิดใช้อยู่"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"กำลังค้นหาเครื่องพิมพ์"</string>
diff --git a/packages/PrintSpooler/res/values-tl/strings.xml b/packages/PrintSpooler/res/values-tl/strings.xml
index deafac3..ffc7738 100644
--- a/packages/PrintSpooler/res/values-tl/strings.xml
+++ b/packages/PrintSpooler/res/values-tl/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Higit pang impormasyon tungkol sa printer na ito"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Mga pag-print na walang naging problema"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Mga hindi matagumpay na pag-print"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Hindi makagawa ng file"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Naka-disable ang ilang serbisyo sa pag-print"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Naghahanap ng mga printer"</string>
diff --git a/packages/PrintSpooler/res/values-tr/strings.xml b/packages/PrintSpooler/res/values-tr/strings.xml
index b21dde2..3ff3f38 100644
--- a/packages/PrintSpooler/res/values-tr/strings.xml
+++ b/packages/PrintSpooler/res/values-tr/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Bu yazıcıyla ilgili daha fazla bilgi"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Devam eden yazdırma işleri"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Başarısız yazdırma işleri"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Dosya oluşturulamadı"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Bazı yazdırma hizmetleri devre dışı bırakıldı"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Yazıcılar aranıyor"</string>
diff --git a/packages/PrintSpooler/res/values-uk/strings.xml b/packages/PrintSpooler/res/values-uk/strings.xml
index 1e145d6..b5d426e 100644
--- a/packages/PrintSpooler/res/values-uk/strings.xml
+++ b/packages/PrintSpooler/res/values-uk/strings.xml
@@ -63,10 +63,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Докладніше про цей принтер"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Активні завдання друку"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Невиконані завдання друку"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Не вдалося створити файл"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Деякі служби друку вимкнено"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Пошук принтерів"</string>
diff --git a/packages/PrintSpooler/res/values-ur/strings.xml b/packages/PrintSpooler/res/values-ur/strings.xml
index 10938c8..026a41e 100644
--- a/packages/PrintSpooler/res/values-ur/strings.xml
+++ b/packages/PrintSpooler/res/values-ur/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"اس پرنٹر کے بارے میں مزید معلومات"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"چلنے والے پرنٹ جابز"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"ناکام پرنٹ جابز"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"فائل تخلیق نہیں ہو سکی"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"پرنٹ کی کچھ سروسز غیر فعال ہیں"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"پرنٹرز تلاش کر رہا ہے"</string>
diff --git a/packages/PrintSpooler/res/values-uz/strings.xml b/packages/PrintSpooler/res/values-uz/strings.xml
index 8e5f807..8921f8e 100644
--- a/packages/PrintSpooler/res/values-uz/strings.xml
+++ b/packages/PrintSpooler/res/values-uz/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Printer haqida batafsil ma’lumot"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Faol chop etish vazifalari"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Muammoli chop etish vazifalari"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Faylni yaratib bo‘lmadi"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Ayrim chop etish xizmatlari o‘chirib qo‘yilgan"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Printerlar qidirilmoqda"</string>
diff --git a/packages/PrintSpooler/res/values-vi/strings.xml b/packages/PrintSpooler/res/values-vi/strings.xml
index 627e858..a181424 100644
--- a/packages/PrintSpooler/res/values-vi/strings.xml
+++ b/packages/PrintSpooler/res/values-vi/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Thông tin khác về máy in này"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Lệnh in đang chạy"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Lệnh in bị lỗi"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Không thể tạo tệp"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Một số dịch vụ in đã bị tắt"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Đang tìm kiếm máy in"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rCN/strings.xml b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
index e657093..54e88c0 100644
--- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"此打印机的详细信息"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"进行中的打印作业"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"失败的打印作业"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"无法创建文件"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"部分打印服务已停用"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"正在搜索打印机"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rHK/strings.xml b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
index 4a3002e..9a98cee 100644
--- a/packages/PrintSpooler/res/values-zh-rHK/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"此打印機詳情"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"正在執行列印工作"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"列印工作失敗"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"無法建立檔案"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"部分列印服務已停用"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"正在搜尋打印機"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rTW/strings.xml b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
index 946a31d..f159605 100644
--- a/packages/PrintSpooler/res/values-zh-rTW/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"查看這台印表機的詳細資訊"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"執行中的列印工作"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"失敗的列印工作"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"無法建立檔案"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"已停用部分列印服務"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"正在搜尋印表機"</string>
diff --git a/packages/PrintSpooler/res/values-zu/strings.xml b/packages/PrintSpooler/res/values-zu/strings.xml
index 1f505ce..9b1d5bb 100644
--- a/packages/PrintSpooler/res/values-zu/strings.xml
+++ b/packages/PrintSpooler/res/values-zu/strings.xml
@@ -61,10 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"Olunye ulwazi mayelana nale phrinta"</string>
- <!-- no translation found for notification_channel_progress (872788690775721436) -->
- <skip />
- <!-- no translation found for notification_channel_failure (9042250774797916414) -->
- <skip />
+ <string name="notification_channel_progress" msgid="872788690775721436">"Yenza imisebenzi yokuphrinta"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"Imisebenzi yokuphrinta ehlulekile"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Ayikwazanga ukufala ifayela"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Amanye amasevisi okuphrinta akhutshaziwe"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"Isesha amaphrinta"</string>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 4cce166..ccdec62 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -1290,11 +1290,11 @@
private void bindUi() {
// Summary
mSummaryContainer = findViewById(R.id.summary_content);
- mSummaryCopies = (TextView) findViewById(R.id.copies_count_summary);
- mSummaryPaperSize = (TextView) findViewById(R.id.paper_size_summary);
+ mSummaryCopies = findViewById(R.id.copies_count_summary);
+ mSummaryPaperSize = findViewById(R.id.paper_size_summary);
// Options container
- mOptionsContent = (PrintContentView) findViewById(R.id.options_content);
+ mOptionsContent = findViewById(R.id.options_content);
mOptionsContent.setOptionsStateChangeListener(this);
mOptionsContent.setOpenOptionsController(this);
@@ -1302,7 +1302,7 @@
OnClickListener clickListener = new MyClickListener();
// Copies
- mCopiesEditText = (EditText) findViewById(R.id.copies_edittext);
+ mCopiesEditText = findViewById(R.id.copies_edittext);
mCopiesEditText.setOnFocusChangeListener(mSelectAllOnFocusListener);
mCopiesEditText.setText(MIN_COPIES_STRING);
mCopiesEditText.setSelection(mCopiesEditText.getText().length());
@@ -1311,28 +1311,28 @@
// Destination.
mPrintersObserver = new PrintersObserver();
mDestinationSpinnerAdapter.registerDataSetObserver(mPrintersObserver);
- mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
+ mDestinationSpinner = findViewById(R.id.destination_spinner);
mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
mDestinationSpinner.setOnItemSelectedListener(itemSelectedListener);
// Media size.
mMediaSizeSpinnerAdapter = new ArrayAdapter<>(
this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
- mMediaSizeSpinner = (Spinner) findViewById(R.id.paper_size_spinner);
+ mMediaSizeSpinner = findViewById(R.id.paper_size_spinner);
mMediaSizeSpinner.setAdapter(mMediaSizeSpinnerAdapter);
mMediaSizeSpinner.setOnItemSelectedListener(itemSelectedListener);
// Color mode.
mColorModeSpinnerAdapter = new ArrayAdapter<>(
this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
- mColorModeSpinner = (Spinner) findViewById(R.id.color_spinner);
+ mColorModeSpinner = findViewById(R.id.color_spinner);
mColorModeSpinner.setAdapter(mColorModeSpinnerAdapter);
mColorModeSpinner.setOnItemSelectedListener(itemSelectedListener);
// Duplex mode.
mDuplexModeSpinnerAdapter = new ArrayAdapter<>(
this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
- mDuplexModeSpinner = (Spinner) findViewById(R.id.duplex_spinner);
+ mDuplexModeSpinner = findViewById(R.id.duplex_spinner);
mDuplexModeSpinner.setAdapter(mDuplexModeSpinnerAdapter);
mDuplexModeSpinner.setOnItemSelectedListener(itemSelectedListener);
@@ -1345,32 +1345,32 @@
ORIENTATION_PORTRAIT, orientationLabels[0]));
mOrientationSpinnerAdapter.add(new SpinnerItem<>(
ORIENTATION_LANDSCAPE, orientationLabels[1]));
- mOrientationSpinner = (Spinner) findViewById(R.id.orientation_spinner);
+ mOrientationSpinner = findViewById(R.id.orientation_spinner);
mOrientationSpinner.setAdapter(mOrientationSpinnerAdapter);
mOrientationSpinner.setOnItemSelectedListener(itemSelectedListener);
// Range options
ArrayAdapter<SpinnerItem<Integer>> rangeOptionsSpinnerAdapter = new ArrayAdapter<>(
this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
- mRangeOptionsSpinner = (Spinner) findViewById(R.id.range_options_spinner);
+ mRangeOptionsSpinner = findViewById(R.id.range_options_spinner);
mRangeOptionsSpinner.setAdapter(rangeOptionsSpinnerAdapter);
mRangeOptionsSpinner.setOnItemSelectedListener(itemSelectedListener);
updatePageRangeOptions(PrintDocumentInfo.PAGE_COUNT_UNKNOWN);
// Page range
- mPageRangeTitle = (TextView) findViewById(R.id.page_range_title);
- mPageRangeEditText = (EditText) findViewById(R.id.page_range_edittext);
+ mPageRangeTitle = findViewById(R.id.page_range_title);
+ mPageRangeEditText = findViewById(R.id.page_range_edittext);
mPageRangeEditText.setVisibility(View.GONE);
mPageRangeTitle.setVisibility(View.GONE);
mPageRangeEditText.setOnFocusChangeListener(mSelectAllOnFocusListener);
mPageRangeEditText.addTextChangedListener(new RangeTextWatcher());
// Advanced options button.
- mMoreOptionsButton = (Button) findViewById(R.id.more_options_button);
+ mMoreOptionsButton = findViewById(R.id.more_options_button);
mMoreOptionsButton.setOnClickListener(clickListener);
// Print button
- mPrintButton = (ImageView) findViewById(R.id.print_button);
+ mPrintButton = findViewById(R.id.print_button);
mPrintButton.setOnClickListener(clickListener);
// The UI is now initialized
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
index 6f0caa2..a9a6cbd 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
@@ -134,7 +134,7 @@
LOADER_ID_PRINT_REGISTRY_INT);
// Hook up the list view.
- mListView = (ListView) findViewById(android.R.id.list);
+ mListView = findViewById(android.R.id.list);
final DestinationAdapter adapter = new DestinationAdapter();
adapter.registerDataSetObserver(new DataSetObserver() {
@Override
@@ -411,7 +411,7 @@
View emptyView = findViewById(R.id.empty_print_state);
mListView.setEmptyView(emptyView);
}
- TextView titleView = (TextView) findViewById(R.id.title);
+ TextView titleView = findViewById(R.id.title);
View progressBar = findViewById(R.id.progress_bar);
if (mEnabledPrintServices.size() == 0) {
titleView.setText(R.string.print_no_print_services);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
index 0bb4bfa..8b00ed0 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
@@ -136,12 +136,12 @@
@Override
protected void onFinishInflate() {
mStaticContent = findViewById(R.id.static_content);
- mSummaryContent = (ViewGroup) findViewById(R.id.summary_content);
+ mSummaryContent = findViewById(R.id.summary_content);
mDynamicContent = findViewById(R.id.dynamic_content);
mDraggableContent = findViewById(R.id.draggable_content);
mPrintButton = findViewById(R.id.print_button);
mMoreOptionsButton = findViewById(R.id.more_options_button);
- mOptionsContainer = (ViewGroup) findViewById(R.id.options_container);
+ mOptionsContainer = findViewById(R.id.options_container);
mEmbeddedContentContainer = findViewById(R.id.embedded_content_container);
mEmbeddedContentScrim = findViewById(R.id.embedded_content_scrim);
mExpandCollapseHandle = findViewById(R.id.expand_collapse_handle);
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index 7d09876..1eeed3c 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -58,12 +58,16 @@
<item msgid="3878793616631049349">"Koristi HDCP proveru samo za DRM sadržaj"</item>
<item msgid="45075631231212732">"Uvek koristi HDCP proveru"</item>
</string-array>
- <!-- no translation found for bluetooth_avrcp_versions:0 (5347678900838034763) -->
- <!-- no translation found for bluetooth_avrcp_versions:1 (2089555299377409443) -->
- <!-- no translation found for bluetooth_avrcp_versions:2 (2895327394279434278) -->
- <!-- no translation found for bluetooth_avrcp_version_values:0 (2838624067805073303) -->
- <!-- no translation found for bluetooth_avrcp_version_values:1 (1913619118958233129) -->
- <!-- no translation found for bluetooth_avrcp_version_values:2 (7142710449249088270) -->
+ <string-array name="bluetooth_avrcp_versions">
+ <item msgid="5347678900838034763">"AVRCP 1.4 (podrazumevano)"</item>
+ <item msgid="2089555299377409443">"AVRCP 1.5"</item>
+ <item msgid="2895327394279434278">"AVRCP 1.6"</item>
+ </string-array>
+ <string-array name="bluetooth_avrcp_version_values">
+ <item msgid="2838624067805073303">"avrcp14"</item>
+ <item msgid="1913619118958233129">"avrcp15"</item>
+ <item msgid="7142710449249088270">"avrcp16"</item>
+ </string-array>
<string-array name="bluetooth_a2dp_codec_titles">
<item msgid="7065842274271279580">"Koristi izbor sistema (podrazumevano)"</item>
<item msgid="7539690996561263909">"SBC"</item>
@@ -71,6 +75,8 @@
<item msgid="8910200421843557332">"aptX"</item>
<item msgid="8434403964359457768">"aptX HD"</item>
<item msgid="6751080638867012696">"LDAC"</item>
+ <item msgid="723675059572222462">"Omogući opcionalne kodeke"</item>
+ <item msgid="3304843301758635896">"Onemogući opcionalne kodeke"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="5062108632402595000">"Koristi izbor sistema (podrazumevano)"</item>
@@ -79,6 +85,8 @@
<item msgid="2279916056363477395">"aptX"</item>
<item msgid="6641171061200063516">"aptX HD"</item>
<item msgid="7950781694447359344">"LDAC"</item>
+ <item msgid="2209680154067241740">"Omogući opcionalne kodeke"</item>
+ <item msgid="741805482892725657">"Onemogući opcionalne kodeke"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="3093023430402746802">"Koristi izbor sistema (podrazumevano)"</item>
@@ -120,11 +128,13 @@
<item msgid="7158319962230727476">"Optimizovano za kvalitet zvuka (990 kb/s/909 kb/s)"</item>
<item msgid="2921767058740704969">"Ujednačen kvalitet zvuka i veze (660 kb/s/606 kb/s)"</item>
<item msgid="8860982705384396512">"Optimizovano za kvalitet veze (330 kb/s/303 kb/s)"</item>
+ <item msgid="4414060457677684127">"Najbolje moguće (prilagodljiva brzina prenosa)"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
<item msgid="6398189564246596868">"Optimizovano za kvalitet zvuka"</item>
<item msgid="4327143584633311908">"Ujednačen kvalitet zvuka i veze"</item>
<item msgid="4681409244565426925">"Optimizovano za kvalitet veze"</item>
+ <item msgid="364670732877872677">"Najbolje moguće (prilagodljiva brzina prenosa)"</item>
</string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Isključeno"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 24b2a13..f92cac8 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -32,10 +32,8 @@
<string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"Automatsko povezivanje nije uspelo"</string>
<string name="wifi_no_internet" msgid="3880396223819116454">"Nema pristupa internetu"</string>
<string name="saved_network" msgid="4352716707126620811">"Sačuvao/la je <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for connected_via_network_scorer (5713793306870815341) -->
- <skip />
- <!-- no translation found for connected_via_network_scorer_default (8430960324014668989) -->
- <skip />
+ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatski povezano preko %1$s"</string>
+ <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatski povezano preko dobavljača ocene mreže"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"Veza je uspostavljena preko pristupne tačke %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Dostupna je preko pristupne tačke %1$s"</string>
<string name="wifi_connected_no_internet" msgid="3149853966840874992">"Veza je uspostavljena, nema interneta"</string>
@@ -127,7 +125,7 @@
<string name="tts_engine_settings_title" msgid="3499112142425680334">"Podešavanja za <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
<string name="tts_engine_settings_button" msgid="1030512042040722285">"Pokreni podešavanja mašine"</string>
<string name="tts_engine_preference_section_title" msgid="448294500990971413">"Željena mašina"</string>
- <string name="tts_general_section_title" msgid="4402572014604490502">"Opšte"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Opšta"</string>
<string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Resetujte visinu tona govora"</string>
<string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Resetujte visinu tona kojom se tekst izgovara na podrazumevanu."</string>
<string-array name="tts_rate_entries">
@@ -141,7 +139,7 @@
<item msgid="5194774745031751806">"Veoma ubrzano"</item>
<item msgid="9085102246155045744">"Najbrže"</item>
</string-array>
- <string name="choose_profile" msgid="8229363046053568878">"Izaberite profil"</string>
+ <string name="choose_profile" msgid="6921016979430278661">"Izaberite profil"</string>
<string name="category_personal" msgid="1299663247844969448">"Lično"</string>
<string name="category_work" msgid="8699184680584175622">"Posao"</string>
<string name="development_settings_title" msgid="215179176067683667">"Opcije za programera"</string>
@@ -170,16 +168,12 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Sertifikacija bežičnog ekrana"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogući detaljniju evidenciju za Wi‑Fi"</string>
- <!-- no translation found for wifi_aggressive_handover (5309131983693661320) -->
- <skip />
+ <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresivan prelaz sa Wi‑Fi mreže na mobilnu"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvek dozvoli skeniranje Wi‑Fi-ja u romingu"</string>
- <!-- no translation found for mobile_data_always_on (8774857027458200434) -->
- <skip />
+ <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilni podaci su uvek aktivni"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogući glavno podešavanje jačine zvuka"</string>
- <!-- no translation found for bluetooth_select_avrcp_version_string (3750059931120293633) -->
- <skip />
- <!-- no translation found for bluetooth_select_avrcp_version_dialog_title (7277329668298705702) -->
- <skip />
+ <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Verzija Bluetooth AVRCP-a"</string>
+ <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Izaberite verziju Bluetooth AVRCP-a"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth audio kodek"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Izaberite Bluetooth audio kodek"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Brzina uzorkovanja za Bluetooth audio"</string>
@@ -193,8 +187,7 @@
<string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Strimovanje: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaz opcija za sertifikaciju bežičnog ekrana"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećava nivo evidentiranja za Wi‑Fi. Prikaz po SSID RSSI-u u biraču Wi‑Fi mreže"</string>
- <!-- no translation found for wifi_aggressive_handover_summary (7266329646559808827) -->
- <skip />
+ <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kad se omogući, Wi‑Fi će biti agresivniji pri prebacivanju mreže za prenos podataka na mobilnu ako je Wi‑Fi signal slab"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Dozvoli/zabrani skeniranje Wi-Fi-ja u romingu na osnovu prisutnog protoka podataka na interfejsu"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Veličine bafera podataka u programu za evidentiranje"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Izaberite veličine po baferu evidencije"</string>
@@ -323,38 +316,23 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Korekcija boja"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna i može da utiče na performanse."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamenjuje ga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_remaining_duration_only" msgid="845431008899029842">"Još oko <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> do potpunog punjenja"</string>
<string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Preostalo vreme: <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_discharging_duration (2843747179907396142) -->
- <skip />
+ <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – ostalo je oko <xliff:g id="TIME">%2$s</xliff:g>"</string>
<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>
- <!-- no translation found for power_charging_duration (4676999980973411875) -->
- <skip />
+ <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do potpunog punjenja"</string>
<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>
- <!-- no translation found for power_charging_duration_ac (7341243578143555689) -->
- <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>
- <!-- no translation found for power_charging_duration_usb (3720632890882121805) -->
- <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>
- <!-- no translation found for power_charging_duration_wireless (5768338238751562058) -->
- <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>
- <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>
- <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>
- <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Puni se"</string>
+ <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"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>
<string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Kontroliše administrator"</string>
- <string name="enabled_by_admin" msgid="2386503803463071894">"Omogućio je administrator"</string>
- <string name="disabled_by_admin" msgid="3669999613095206948">"Onemogućio je administrator"</string>
+ <string name="enabled_by_admin" msgid="5302986023578399263">"Omogućio je administrator"</string>
+ <string name="disabled_by_admin" msgid="8505398946020816620">"Administrator je onemogućio"</string>
<string name="home" msgid="3256884684164448244">"Početna za Podešavanja"</string>
<string-array name="battery_labels">
<item msgid="8494684293649631252">"0%"</item>
@@ -377,4 +355,7 @@
<string name="retail_demo_reset_title" msgid="696589204029930100">"Potrebna je lozinka"</string>
<string name="active_input_method_subtypes" msgid="3596398805424733238">"Metode aktivnog unosa"</string>
<string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Koristi jezike sistema"</string>
+ <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Otvaranje podešavanja za aplikaciju <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> nije uspelo"</string>
+ <string name="ime_security_warning" msgid="4135828934735934248">"Ovaj metod unosa možda može da prikuplja sav tekst koji unosite, uključujući lične podatke, kao što su lozinke i brojevi kreditnih kartica. Potiče od aplikacije <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Želite li da koristite ovaj metod unosa?"</string>
+ <string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Napomena: Posle restartovanja ova aplikacija ne može da se pokrene dok ne otključate telefon"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index 6c883e3e..8ea31e5 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -58,12 +58,16 @@
<item msgid="3878793616631049349">"Выкарыстанне праверкі HDCP только для змесціва, абароненага DRM"</item>
<item msgid="45075631231212732">"Заўсёды выкарыстоўваць праверку HDCP"</item>
</string-array>
- <!-- no translation found for bluetooth_avrcp_versions:0 (5347678900838034763) -->
- <!-- no translation found for bluetooth_avrcp_versions:1 (2089555299377409443) -->
- <!-- no translation found for bluetooth_avrcp_versions:2 (2895327394279434278) -->
- <!-- no translation found for bluetooth_avrcp_version_values:0 (2838624067805073303) -->
- <!-- no translation found for bluetooth_avrcp_version_values:1 (1913619118958233129) -->
- <!-- no translation found for bluetooth_avrcp_version_values:2 (7142710449249088270) -->
+ <string-array name="bluetooth_avrcp_versions">
+ <item msgid="5347678900838034763">"AVRCP 1.4 (стандартная)"</item>
+ <item msgid="2089555299377409443">"AVRCP 1.5"</item>
+ <item msgid="2895327394279434278">"AVRCP 1.6"</item>
+ </string-array>
+ <string-array name="bluetooth_avrcp_version_values">
+ <item msgid="2838624067805073303">"avrcp14"</item>
+ <item msgid="1913619118958233129">"avrcp15"</item>
+ <item msgid="7142710449249088270">"avrcp16"</item>
+ </string-array>
<string-array name="bluetooth_a2dp_codec_titles">
<item msgid="7065842274271279580">"Выбар сістэмы (стандартны)"</item>
<item msgid="7539690996561263909">"SBC"</item>
@@ -71,6 +75,8 @@
<item msgid="8910200421843557332">"aptX"</item>
<item msgid="8434403964359457768">"aptX HD"</item>
<item msgid="6751080638867012696">"LDAC"</item>
+ <item msgid="723675059572222462">"Уключыць дадатковыя кодэкі"</item>
+ <item msgid="3304843301758635896">"Адключыць дадатковыя кодэкі"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="5062108632402595000">"Выбар сістэмы (стандартны)"</item>
@@ -79,6 +85,8 @@
<item msgid="2279916056363477395">"aptX"</item>
<item msgid="6641171061200063516">"aptX HD"</item>
<item msgid="7950781694447359344">"LDAC"</item>
+ <item msgid="2209680154067241740">"Уключыць дадатковыя кодэкі"</item>
+ <item msgid="741805482892725657">"Адключыць дадатковыя кодэкі"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="3093023430402746802">"Выбар сістэмы (стандартны)"</item>
@@ -120,11 +128,13 @@
<item msgid="7158319962230727476">"Аптымізавана якасць гуку (990 кбіт/c / 909 кбіт/c)"</item>
<item msgid="2921767058740704969">"Збалансаваная якасць аўдыя і падключэння (660кбіт/c / 606 кбіт/c)"</item>
<item msgid="8860982705384396512">"Аптымізавана якасць падключэння (330 кбіт/c / 303 кбіт/c)"</item>
+ <item msgid="4414060457677684127">"Best Effort (адаптыўны бітрэйт)"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
<item msgid="6398189564246596868">"Аптымізавана якасць гуку"</item>
<item msgid="4327143584633311908">"Збалансаваная якасць аўдыя і падключэння"</item>
<item msgid="4681409244565426925">"Аптымізавана якасць падключэння"</item>
+ <item msgid="364670732877872677">"Best Effort (адаптыўны бітрэйт)"</item>
</string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Выкл."</item>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 36ebaa3..f340232 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -32,10 +32,8 @@
<string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"Не будзе аўтаматычна падключацца"</string>
<string name="wifi_no_internet" msgid="3880396223819116454">"Няма доступу да інтэрнэту"</string>
<string name="saved_network" msgid="4352716707126620811">"Хто захаваў: <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for connected_via_network_scorer (5713793306870815341) -->
- <skip />
- <!-- no translation found for connected_via_network_scorer_default (8430960324014668989) -->
- <skip />
+ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Аўтаматычна падключана праз %1$s"</string>
+ <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Аўтаматычна падключана праз пастаўшчыка паслугі ацэнкі сеткі"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"Падлучана праз %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Даступна праз %1$s"</string>
<string name="wifi_connected_no_internet" msgid="3149853966840874992">"Падлучана, няма інтэрнэту"</string>
@@ -141,7 +139,7 @@
<item msgid="5194774745031751806">"Вельмі шпарка"</item>
<item msgid="9085102246155045744">"Максімальна хутка"</item>
</string-array>
- <string name="choose_profile" msgid="8229363046053568878">"Выбраць профіль"</string>
+ <string name="choose_profile" msgid="6921016979430278661">"Выбраць профіль"</string>
<string name="category_personal" msgid="1299663247844969448">"Асабісты"</string>
<string name="category_work" msgid="8699184680584175622">"Рабочы"</string>
<string name="development_settings_title" msgid="215179176067683667">"Параметры распрацоўшчыка"</string>
@@ -170,16 +168,12 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Сеткі"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Сертыфікацыя бесправаднога дысплея"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Уключыць падрабязны журнал Wi‑Fi"</string>
- <!-- no translation found for wifi_aggressive_handover (5309131983693661320) -->
- <skip />
+ <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Інтэнсіўны пераход з Wi‑Fi на маб. сетку"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Заўсёды дазваляць роўмінгавае сканіраванне Wi‑Fi"</string>
- <!-- no translation found for mobile_data_always_on (8774857027458200434) -->
- <skip />
+ <string name="mobile_data_always_on" msgid="8774857027458200434">"Мабільная перадача даных заўсёды актыўная"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Адключыць абсалютны гук"</string>
- <!-- no translation found for bluetooth_select_avrcp_version_string (3750059931120293633) -->
- <skip />
- <!-- no translation found for bluetooth_select_avrcp_version_dialog_title (7277329668298705702) -->
- <skip />
+ <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Версія Bluetooth AVRCP"</string>
+ <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Выбраць версію Bluetooth AVRCP"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Кодэк Bluetooth Audio"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Выбраць аўдыякодэк Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Частата дыскрэтызацыі Bluetooth Audio"</string>
@@ -193,8 +187,7 @@
<string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Перадача плынню: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Паказаць опцыі сертыфікацыі бесправаднога дысплея"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Падвыс. узровень дэтал-цыі журнала Wi‑Fi у залежн. ад SSID RSSI у Wi‑Fi Picker"</string>
- <!-- no translation found for wifi_aggressive_handover_summary (7266329646559808827) -->
- <skip />
+ <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Калі гэта функцыя ўключана, Wi-Fi будзе больш інтэнсіўна імкнуцца перайсці на падключ. маб. перад. даных пры слабым сігнале Wi‑Fi"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дазволіць/забараніць роўмінгавае сканіраванне Wi‑Fi ў залежнасці ад аб\'ёму трафіку даных у інтэрфейсе"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Памеры буфера для сродку вядзення журнала"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Выберыце памеры сродку вядзення журнала для буфераў журнала"</string>
@@ -323,38 +316,23 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Карэкцыя колеру"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Гэтая функцыя з\'яўляецца эксперыментальнай і можа паўплываць на прадукцыйнасць."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Перавызначаны <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"Засталося прыблізна <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_remaining_duration_only" msgid="845431008899029842">"Засталося каля <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Да поўнай зарадкі засталося <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Засталося <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_discharging_duration (2843747179907396142) -->
- <skip />
+ <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – засталося каля <xliff:g id="TIME">%2$s</xliff:g>"</string>
<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>
- <!-- no translation found for power_charging_duration (4676999980973411875) -->
- <skip />
+ <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі"</string>
<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>
- <!-- no translation found for power_charging_duration_ac (7341243578143555689) -->
- <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>
- <!-- no translation found for power_charging_duration_usb (3720632890882121805) -->
- <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>
- <!-- no translation found for power_charging_duration_wireless (5768338238751562058) -->
- <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>
- <string name="battery_info_status_charging_ac_short" msgid="7431401092096415502">"Зарадка"</string>
- <string name="battery_info_status_charging_usb" msgid="2207489369680923929">"Зарадка па USB"</string>
- <string name="battery_info_status_charging_usb_short" msgid="6733371990319101366">"Зарадка"</string>
- <string name="battery_info_status_charging_wireless" msgid="3574032603735446573">"Бесправадная зарадка"</string>
- <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Зарадка"</string>
+ <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ідзе зарадка"</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>
<string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Кантралюецца адміністратарам"</string>
- <string name="enabled_by_admin" msgid="2386503803463071894">"Уключана адміністратарам"</string>
- <string name="disabled_by_admin" msgid="3669999613095206948">"Адключана адміністратарам"</string>
+ <string name="enabled_by_admin" msgid="5302986023578399263">"Уключана адміністратарам"</string>
+ <string name="disabled_by_admin" msgid="8505398946020816620">"Адключана адміністратарам"</string>
<string name="home" msgid="3256884684164448244">"Галоўная старонка налад"</string>
<string-array name="battery_labels">
<item msgid="8494684293649631252">"0 %"</item>
@@ -377,4 +355,7 @@
<string name="retail_demo_reset_title" msgid="696589204029930100">"Патрабуецца пароль"</string>
<string name="active_input_method_subtypes" msgid="3596398805424733238">"Актыўныя метады ўводу"</string>
<string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Выкарыстоўваць мовы сістэмы"</string>
+ <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Не атрымалася адкрыць параметры <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
+ <string name="ime_security_warning" msgid="4135828934735934248">"Гэты метад уводу можа збіраць увесь тэкст, які ўводзіцца, у тым лiку такiя персанальныя дадзеныя, як паролі і нумары крэдытных карт. Ён выкарыстоўваецца прыкладаннем <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Выкарыстоўваць гэты метад уводу?"</string>
+ <string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Заўвага. Пасля перазагрузкі гэта праграма не зможа запусціцца, пакуль вы не разблакіруеце тэлефон"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index acc0ce0..32a9504 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -316,7 +316,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекция на цветове"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Тази функция е експериментална и може да се отрази на ефективността."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Заменено от „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
- <string name="power_remaining_duration_only" msgid="845431008899029842">"Оставащо време: Около <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_remaining_duration_only" msgid="845431008899029842">"Оставащо време: около <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Оставащо време: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – около <xliff:g id="TIME">%2$s</xliff:g> оставащо време"</string>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 58b3a47..e0b3e36 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -58,12 +58,16 @@
<item msgid="3878793616631049349">"Koristi HDCP provjeru samo za DRM sadržaj"</item>
<item msgid="45075631231212732">"Uvijek koristi HDCP provjeru"</item>
</string-array>
- <!-- no translation found for bluetooth_avrcp_versions:0 (5347678900838034763) -->
- <!-- no translation found for bluetooth_avrcp_versions:1 (2089555299377409443) -->
- <!-- no translation found for bluetooth_avrcp_versions:2 (2895327394279434278) -->
- <!-- no translation found for bluetooth_avrcp_version_values:0 (2838624067805073303) -->
- <!-- no translation found for bluetooth_avrcp_version_values:1 (1913619118958233129) -->
- <!-- no translation found for bluetooth_avrcp_version_values:2 (7142710449249088270) -->
+ <string-array name="bluetooth_avrcp_versions">
+ <item msgid="5347678900838034763">"AVRCP 1.4 (Zadano)"</item>
+ <item msgid="2089555299377409443">"AVRCP 1.5"</item>
+ <item msgid="2895327394279434278">"AVRCP 1.6"</item>
+ </string-array>
+ <string-array name="bluetooth_avrcp_version_values">
+ <item msgid="2838624067805073303">"avrcp14"</item>
+ <item msgid="1913619118958233129">"avrcp15"</item>
+ <item msgid="7142710449249088270">"avrcp16"</item>
+ </string-array>
<string-array name="bluetooth_a2dp_codec_titles">
<item msgid="7065842274271279580">"Koristi odabir sistema (Zadano)"</item>
<item msgid="7539690996561263909">"SBC"</item>
@@ -71,6 +75,8 @@
<item msgid="8910200421843557332">"aptX"</item>
<item msgid="8434403964359457768">"aptX HD"</item>
<item msgid="6751080638867012696">"LDAC"</item>
+ <item msgid="723675059572222462">"Omogućite opcionalne kodeke"</item>
+ <item msgid="3304843301758635896">"Onemogućite opcionalne kodeke"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_summaries">
<item msgid="5062108632402595000">"Koristi odabir sistema (Zadano)"</item>
@@ -79,6 +85,8 @@
<item msgid="2279916056363477395">"aptX"</item>
<item msgid="6641171061200063516">"aptX HD"</item>
<item msgid="7950781694447359344">"LDAC"</item>
+ <item msgid="2209680154067241740">"Omogućite opcionalne kodeke"</item>
+ <item msgid="741805482892725657">"Onemogućite opcionalne kodeke"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="3093023430402746802">"Koristi odabir sistema (Zadano)"</item>
@@ -120,11 +128,13 @@
<item msgid="7158319962230727476">"Optimizirano za kvalitet zvuka (990 kbps/909 kbps)"</item>
<item msgid="2921767058740704969">"Uravnotežen kvalitet zvuka i veze (660kbps/606kbps)"</item>
<item msgid="8860982705384396512">"Optimizirano za kvalitet veze (330 kbps/303 kbps)"</item>
+ <item msgid="4414060457677684127">"Maksimalan napor (Prilagodljiva brzina prijenosa)"</item>
</string-array>
<string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
<item msgid="6398189564246596868">"Optimizirano za kvalitet zvuka"</item>
<item msgid="4327143584633311908">"Uravnotežen kvalitet zvuka i veze"</item>
<item msgid="4681409244565426925">"Optimizirano za kvalitet veze"</item>
+ <item msgid="364670732877872677">"Maksimalan napor (Prilagodljiva brzina prijenosa)"</item>
</string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Isključeno"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index ce40282..6a41f74 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -32,10 +32,8 @@
<string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"Neće se automatski povezati"</string>
<string name="wifi_no_internet" msgid="3880396223819116454">"Nema pristupa internetu"</string>
<string name="saved_network" msgid="4352716707126620811">"Sačuvao <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for connected_via_network_scorer (5713793306870815341) -->
- <skip />
- <!-- no translation found for connected_via_network_scorer_default (8430960324014668989) -->
- <skip />
+ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatski povezano koristeći %1$s"</string>
+ <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatski povezano putem ocjenjivača mreže"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"Povezani preko %1$s"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"Dostupan preko %1$s"</string>
<string name="wifi_connected_no_internet" msgid="3149853966840874992">"Povezano. Nema interneta"</string>
@@ -141,7 +139,7 @@
<item msgid="5194774745031751806">"Veoma ubrzano"</item>
<item msgid="9085102246155045744">"Najbrže"</item>
</string-array>
- <string name="choose_profile" msgid="8229363046053568878">"Odaberite profil"</string>
+ <string name="choose_profile" msgid="6921016979430278661">"Odaberite profil"</string>
<string name="category_personal" msgid="1299663247844969448">"Lično"</string>
<string name="category_work" msgid="8699184680584175622">"Posao"</string>
<string name="development_settings_title" msgid="215179176067683667">"Opcije za programere"</string>
@@ -170,16 +168,12 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certifikacija bežičnog prikaza"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogućiti Wi-Fi Verbose zapisivanje"</string>
- <!-- no translation found for wifi_aggressive_handover (5309131983693661320) -->
- <skip />
+ <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresivni prijenos s Wi-Fi mreže na mob."</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopustiti Wi-Fi lutajuće skeniranje"</string>
- <!-- no translation found for mobile_data_always_on (8774857027458200434) -->
- <skip />
+ <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna mreža za prijenos podataka je uvijek aktivna"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogućite apsolutnu jačinu zvuka"</string>
- <!-- no translation found for bluetooth_select_avrcp_version_string (3750059931120293633) -->
- <skip />
- <!-- no translation found for bluetooth_select_avrcp_version_dialog_title (7277329668298705702) -->
- <skip />
+ <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP verzija"</string>
+ <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Odaberite Bluetooth AVRCP verziju"</string>
<string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio kodek"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Odaberite Bluetooth Audio kodek"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Brzina uzorkovanja za Bluetooth audio"</string>
@@ -193,8 +187,7 @@
<string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Prijenos: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaži opcije za certifikaciju Bežičnog prikaza"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećajte nivo Wi-Fi zapisivanja, pokazati po SSID RSSI Wi-Fi Picker"</string>
- <!-- no translation found for wifi_aggressive_handover_summary (7266329646559808827) -->
- <skip />
+ <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kada je omogućeno, Wi-Fi veza će u slučaju slabog signala agresivnije predavati vezu za prijenos podataka na mobilnu vezu"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Dozvoli/Zabrani Wi-Fi lutajuće skeniranje na osnovu količine podatkovnog prometa prisutnog na sučelju"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Veličine bafera za zapisnik"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Izaberite veličine za Logger prema međumemoriji evidencije"</string>
@@ -323,38 +316,23 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Ispravka boje"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Ova funkcija je eksperimentalna te može utjecati na performanse."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Zamjenjuje <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only" msgid="4400068916452346544">"Još otprilike <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_remaining_duration_only" msgid="845431008899029842">"Preostalo je otprilike još <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Do potpune napunjenosti preostalo je <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Imate još <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <!-- no translation found for power_discharging_duration (2843747179907396142) -->
- <skip />
+ <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - imate još <xliff:g id="TIME">%2$s</xliff:g>"</string>
<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>
- <!-- no translation found for power_charging_duration (4676999980973411875) -->
- <skip />
+ <string name="power_charging_duration" msgid="4676999980973411875">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> do potpune napunjenosti"</string>
<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>
- <!-- no translation found for power_charging_duration_ac (7341243578143555689) -->
- <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>
- <!-- no translation found for power_charging_duration_usb (3720632890882121805) -->
- <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>
- <!-- no translation found for power_charging_duration_wireless (5768338238751562058) -->
- <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>
- <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>
- <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>
- <string name="battery_info_status_charging_wireless_short" msgid="752569941028903610">"Punjenje"</string>
+ <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"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>
<string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Pod kontrolom administratora"</string>
- <string name="enabled_by_admin" msgid="2386503803463071894">"Omogućio administrator"</string>
- <string name="disabled_by_admin" msgid="3669999613095206948">"Onemogućio je administrator"</string>
+ <string name="enabled_by_admin" msgid="5302986023578399263">"Omogućio administrator"</string>
+ <string name="disabled_by_admin" msgid="8505398946020816620">"Onemogućio administrator"</string>
<string name="home" msgid="3256884684164448244">"Postavke početne stranice"</string>
<string-array name="battery_labels">
<item msgid="8494684293649631252">"0%"</item>
@@ -377,4 +355,7 @@
<string name="retail_demo_reset_title" msgid="696589204029930100">"Potrebna je lozinka"</string>
<string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktivne metode unosa"</string>
<string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Koristi jezik sistema"</string>
+ <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Nije uspjelo otvaranje postavki za <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
+ <string name="ime_security_warning" msgid="4135828934735934248">"Ovaj način unosa može prikupiti sav tekst koji otkucate, uključujući lične podatke kao što su lozinke i brojevi kreditnih kartica. Način omogućava aplikacija <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Da li želite koristiti ovaj način unosa?"</string>
+ <string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Napomena: Nakon ponovnog pokretanja, ova aplikacija se neće moći pokrenuti dok ne otključate telefon"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index 2b762dfa..444ffbc 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -246,7 +246,7 @@
</string-array>
<string-array name="usb_configuration_titles">
<item msgid="488237561639712799">"Kargatzen"</item>
- <item msgid="5220695614993094977">"MTP (multimedia-elementuak transferitzeko protokoloa)"</item>
+ <item msgid="5220695614993094977">"MTP (multimedia-edukia transferitzeko protokoloa)"</item>
<item msgid="2086000968159047375">"PTP (irudiak transferitzeko protokoloa)"</item>
<item msgid="7398830860950841822">"RNDIS (USB bidezko Ethernet konexioa)"</item>
<item msgid="1718924214939774352">"Audio-iturburua"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index dfd2a82..8f4aec1 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -113,7 +113,7 @@
<string name="tts_play_example_title" msgid="7094780383253097230">"Entzun adibide bat"</string>
<string name="tts_play_example_summary" msgid="8029071615047894486">"Erreproduzitu hizketa-sintesiaren demostrazio laburra"</string>
<string name="tts_install_data_title" msgid="4264378440508149986">"Instalatu ahotsaren datuak"</string>
- <string name="tts_install_data_summary" msgid="5742135732511822589">"Instalatu hizketaren sintesirako behar diren ahots-datuak"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Instalatu hizketaren sintesirako behar diren ahotsaren datuak"</string>
<string name="tts_engine_security_warning" msgid="8786238102020223650">"Hizketaren sintesi-motorrak idazten duzun testu guztia bil dezake, pasahitzak eta kreditu-txarteleko zenbakiak bezalako datu pertsonalak barne. <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> motorrak egin du eskaera. Hizketaren sintesi-motor hori erabili nahi duzu?"</string>
<string name="tts_engine_network_required" msgid="1190837151485314743">"Testua ahots bihurtzeko eginbidea erabiltzeko, hizkuntza honek sareko konexioa behar du."</string>
<string name="tts_default_sample_string" msgid="4040835213373086322">"Hizketa-sintesiaren adibide bat da hau"</string>
@@ -317,7 +317,7 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Eginbidea esperimentala da eta eragina izan dezake funtzionamenduan."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string>
<string name="power_remaining_duration_only" msgid="845431008899029842">"<xliff:g id="TIME">%1$s</xliff:g> inguru gelditzen dira"</string>
- <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> gelditzen dira guztiz kargatu arte"</string>
<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="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> inguru gelditzen dira"</string>
<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>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index e623180..2f4ac52 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -316,10 +316,8 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"રંગ સુધારણા"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"આ સુવિધા પ્રાયોગિક છે અને કામગીરી પર અસર કરી શકે છે."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> દ્વારા ઓવરરાઇડ થયું"</string>
- <!-- no translation found for power_remaining_duration_only (845431008899029842) -->
- <skip />
- <!-- no translation found for power_remaining_charging_duration_only (1421102457410268886) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="845431008899029842">"અંદાજે <xliff:g id="TIME">%1$s</xliff:g> બાકી"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"સંપૂર્ણપણે ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી"</string>
<string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> બાકી"</string>
<string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - લગભગ <xliff:g id="TIME">%2$s</xliff:g> બાકી"</string>
<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>
@@ -328,8 +326,7 @@
<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="battery_info_status_unknown" msgid="196130600938058547">"અજાણ્યું"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ચાર્જ થઈ રહ્યું છે"</string>
- <!-- no translation found for battery_info_status_charging_lower (8689770213898117994) -->
- <skip />
+ <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ચાર્જ થઈ રહ્યું છે"</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>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 701d80d..875e851 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -254,7 +254,7 @@
<string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Paksa arah tata letak layar RTL untuk semua lokal"</string>
<string name="force_hw_ui" msgid="6426383462520888732">"Paksa perenderan GPU"</string>
<string name="force_hw_ui_summary" msgid="5535991166074861515">"Paksa penggunaan GPU untuk gambar 2d"</string>
- <string name="force_msaa" msgid="7920323238677284387">"Force 4x MSAA"</string>
+ <string name="force_msaa" msgid="7920323238677284387">"Paksa 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9123553203895817537">"Aktifkan 4x MSAA dalam aplikasi OpenGL ES 2.0"</string>
<string name="show_non_rect_clip" msgid="505954950474595172">"Debug operasi klip non-kotak"</string>
<string name="track_frame_time" msgid="6146354853663863443">"Penguraian GPU profil"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index f7c95f0..3def72d 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -316,7 +316,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correzione del colore"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Questa funzione è sperimentale e potrebbe influire sulle prestazioni."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <string name="power_remaining_duration_only" msgid="845431008899029842">"Quasi scarica. Tempo rimanente: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_remaining_duration_only" msgid="845431008899029842">"Tempo approssimativo rimanente: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tempo rimanente alla carica completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<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="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - ancora circa <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index b7dbd41..e7364db 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -316,10 +316,8 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"תיקון צבע"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"תכונה זו היא ניסיונית ועשויה להשפיע על הביצועים."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"נעקף על ידי <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (845431008899029842) -->
- <skip />
- <!-- no translation found for power_remaining_charging_duration_only (1421102457410268886) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="845431008899029842">"עוד <xliff:g id="TIME">%1$s</xliff:g> בקירוב"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> עד לטעינה מלאה"</string>
<string name="power_remaining_duration_only_short" msgid="5329694252258605547">"נותרו <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - הזמן הנותר: בערך <xliff:g id="TIME">%2$s</xliff:g>"</string>
<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>
@@ -328,8 +326,7 @@
<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="battery_info_status_unknown" msgid="196130600938058547">"לא ידוע"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"טוען"</string>
- <!-- no translation found for battery_info_status_charging_lower (8689770213898117994) -->
- <skip />
+ <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"בטעינה"</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>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index f063a7b..ba098e5 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -316,7 +316,7 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Түсүн тууралоо"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Бул сынамык мүмкүнчүлүк болгондуктан, иштин майнаптуулугуна таасир этиши мүмкүн."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> менен алмаштырылган"</string>
- <string name="power_remaining_duration_only" msgid="845431008899029842">"Батарея толгонго чейин болж. убакыт: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_remaining_duration_only" msgid="845431008899029842">"Батарея түгөнгөнгө чейин калган убакыт: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Батарея толгонго чейин калган убакыт: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> калды"</string>
<string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – болжол менен <xliff:g id="TIME">%2$s</xliff:g> калды"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index eb55e0dd..89bbc71 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -316,10 +316,8 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"रंग सुधारणा"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"हे वैशिष्ट्य प्रायोगिक आहे आणि कदाचित कार्यप्रदर्शन प्रभावित करू शकते."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारे अधिलिखित"</string>
- <!-- no translation found for power_remaining_duration_only (845431008899029842) -->
- <skip />
- <!-- no translation found for power_remaining_charging_duration_only (1421102457410268886) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="845431008899029842">"सुमारे <xliff:g id="TIME">%1$s</xliff:g> शिल्लक"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"पूर्णपणे चार्ज होण्यास <xliff:g id="TIME">%1$s</xliff:g> शिल्लक"</string>
<string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> शिल्लक"</string>
<string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - सुमारे <xliff:g id="TIME">%2$s</xliff:g> शिल्लक"</string>
<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>
@@ -328,8 +326,7 @@
<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="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज होत आहे"</string>
- <!-- no translation found for battery_info_status_charging_lower (8689770213898117994) -->
- <skip />
+ <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"चार्ज होत आहे"</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>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 3a696f6..2e574dc 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -316,10 +316,8 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Fargekorrigering"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Denne funksjonen er eksperimentell og kan påvirke ytelsen."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"Overstyres av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
- <!-- no translation found for power_remaining_duration_only (845431008899029842) -->
- <skip />
- <!-- no translation found for power_remaining_charging_duration_only (1421102457410268886) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="845431008899029842">"Omtrent <xliff:g id="TIME">%1$s</xliff:g> gjenstår"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> til det er fulladet"</string>
<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="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – omtrent <xliff:g id="TIME">%2$s</xliff:g> gjenstår"</string>
<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>
@@ -328,8 +326,7 @@
<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="battery_info_status_unknown" msgid="196130600938058547">"Ukjent"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"Lader"</string>
- <!-- no translation found for battery_info_status_charging_lower (8689770213898117994) -->
- <skip />
+ <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"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>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 0015f79..35d8363 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -316,10 +316,8 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"रङ्ग सुधार"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"यो सुविधा प्रयोगात्मक छ र प्रदर्शनमा असर गर्न सक्छ।"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारा अधिरोहित"</string>
- <!-- no translation found for power_remaining_duration_only (845431008899029842) -->
- <skip />
- <!-- no translation found for power_remaining_charging_duration_only (1421102457410268886) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="845431008899029842">"लगभग <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"पूर्णरूपमा चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string>
<string name="power_remaining_duration_only_short" msgid="5329694252258605547">"बाँकी समय <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - करिब <xliff:g id="TIME">%2$s</xliff:g> बाँकी"</string>
<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>
@@ -328,8 +326,7 @@
<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="battery_info_status_unknown" msgid="196130600938058547">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"चार्ज हुँदै"</string>
- <!-- no translation found for battery_info_status_charging_lower (8689770213898117994) -->
- <skip />
+ <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"चार्ज हुँदै"</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>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 2eb611f..dc949c3 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -316,10 +316,8 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"ਰੰਗ ਸੰਸ਼ੋਧਨ"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਪ੍ਰਯੋਗਾਤਮਿਕ ਹੈ ਅਤੇ ਪ੍ਰਦਰਸ਼ਨ ਤੇ ਅਸਰ ਪਾ ਸਕਦੀ ਹੈ।"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ਦੁਆਰਾ ਓਵਰਰਾਈਡ ਕੀਤਾ"</string>
- <!-- no translation found for power_remaining_duration_only (845431008899029842) -->
- <skip />
- <!-- no translation found for power_remaining_charging_duration_only (1421102457410268886) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="845431008899029842">"ਲਗਭਗ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"ਪੂਰੀ ਤਰ੍ਹਾਂ ਚਾਰਜ ਹੋਣ ਲਈ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
<string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
<string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਲਗਭਗ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string>
<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>
@@ -328,8 +326,7 @@
<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="battery_info_status_unknown" msgid="196130600938058547">"ਅਗਿਆਤ"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ਚਾਰਜਿੰਗ"</string>
- <!-- no translation found for battery_info_status_charging_lower (8689770213898117994) -->
- <skip />
+ <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ਚਾਰਜ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</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>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 89f82af..9c5c22b 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -168,7 +168,7 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificação de display sem fios"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Ativar o registo verboso de Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Transm. agressiva de Wi‑Fi p/ rede móvel"</string>
+ <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Mudança brusca de Wi‑Fi para rede móvel"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir sempre a deteção de Wi-Fi em roaming"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string>
<string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 75501d7..a8fd5bd 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -316,10 +316,8 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"වර්ණ නිවැරදි කිරීම"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"මෙම විශේෂාංගය පරීක්ෂණාත්මක සහ ඇතැම් විට ක්රියාකාරිත්වයට බලපෑ හැක."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> මගින් ඉක්මවන ලදී"</string>
- <!-- no translation found for power_remaining_duration_only (845431008899029842) -->
- <skip />
- <!-- no translation found for power_remaining_charging_duration_only (1421102457410268886) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="845431008899029842">"<xliff:g id="TIME">%1$s</xliff:g> පමණ ඉතිරියි"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"පූර්ණව ආරෝපණය වන තෙක් <xliff:g id="TIME">%1$s</xliff:g> ඉතිරියි"</string>
<string name="power_remaining_duration_only_short" msgid="5329694252258605547">"ඉතිරි <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>ක් පමණ ඇත"</string>
<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>
@@ -328,8 +326,7 @@
<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="battery_info_status_unknown" msgid="196130600938058547">"නොදනී"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ආරෝපණය වෙමින්"</string>
- <!-- no translation found for battery_info_status_charging_lower (8689770213898117994) -->
- <skip />
+ <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ආරෝපණය වේ"</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>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 67412cf..c31f12d 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -125,7 +125,7 @@
<string name="tts_engine_settings_title" msgid="3499112142425680334">"Подешавања за <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
<string name="tts_engine_settings_button" msgid="1030512042040722285">"Покрени подешавања машине"</string>
<string name="tts_engine_preference_section_title" msgid="448294500990971413">"Жељена машина"</string>
- <string name="tts_general_section_title" msgid="4402572014604490502">"Опште"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Општа"</string>
<string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Ресетујте висину тона говора"</string>
<string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Ресетујте висину тона којом се текст изговара на подразумевану."</string>
<string-array name="tts_rate_entries">
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 4645815..e38a5c6 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -317,7 +317,7 @@
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Kipengele hiki ni cha majaribio na huenda kikaathiri utendaji wa kifaa chako."</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="845431008899029842">"Zimesalia takribani <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Imebaki <xliff:g id="TIME">%1$s</xliff:g> hadi chaji ijae"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Imebaki <xliff:g id="TIME">%1$s</xliff:g> chaji ijae"</string>
<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="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - imesalia takribani <xliff:g id="TIME">%2$s</xliff:g>"</string>
<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>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index ab38cce..1c937ed 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -316,10 +316,8 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"రంగు సవరణ"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ఈ లక్షణం ప్రయోగాత్మకమైనది మరియు పనితీరుపై ప్రభావం చూపవచ్చు."</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string>
- <!-- no translation found for power_remaining_duration_only (845431008899029842) -->
- <skip />
- <!-- no translation found for power_remaining_charging_duration_only (1421102457410268886) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="845431008899029842">"మిగిలి ఉన్న సమయం, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"పూర్తిగా ఛార్జ్ కావడానికి <xliff:g id="TIME">%1$s</xliff:g> పడుతుంది"</string>
<string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> మిగిలి ఉంది"</string>
<string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> పని చేస్తుంది"</string>
<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>
@@ -328,8 +326,7 @@
<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="battery_info_status_unknown" msgid="196130600938058547">"తెలియదు"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"ఛార్జ్ అవుతోంది"</string>
- <!-- no translation found for battery_info_status_charging_lower (8689770213898117994) -->
- <skip />
+ <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"ఛార్జ్ అవుతోంది"</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>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 11ae5f3..8c1d8f4 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -316,10 +316,8 @@
<string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"رنگ کی اصلاح"</string>
<string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"یہ خصوصیت تجرباتی ہے اور اس کی وجہ سے کاکردگی متاثر ہو سکتی ہے۔"</string>
<string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> کے ذریعہ منسوخ کردیا گیا"</string>
- <!-- no translation found for power_remaining_duration_only (845431008899029842) -->
- <skip />
- <!-- no translation found for power_remaining_charging_duration_only (1421102457410268886) -->
- <skip />
+ <string name="power_remaining_duration_only" msgid="845431008899029842">"تقریبًا <xliff:g id="TIME">%1$s</xliff:g> باقی ہے"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"پوری طرح چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی ہے"</string>
<string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> باقی ہے"</string>
<string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - تقریباً <xliff:g id="TIME">%2$s</xliff:g> باقی ہے"</string>
<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>
@@ -328,8 +326,7 @@
<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="battery_info_status_unknown" msgid="196130600938058547">"نامعلوم"</string>
<string name="battery_info_status_charging" msgid="1705179948350365604">"چارج ہو رہا ہے"</string>
- <!-- no translation found for battery_info_status_charging_lower (8689770213898117994) -->
- <skip />
+ <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"چارج ہو رہا ہے"</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>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 9d5c9cc..588ea1a 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -317,7 +317,7 @@
<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="845431008899029842">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
- <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"To‘liq quvvat olishiga <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"To‘lishiga <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
<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="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – taxminan <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string>
<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>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index db590f7..ebed18d 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -317,7 +317,7 @@
<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="845431008899029842">"剩餘約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"還需 <xliff:g id="TIME">%1$s</xliff:g>才能完全充電"</string>
+ <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g>後就能完全充電"</string>
<string name="power_remaining_duration_only_short" msgid="5329694252258605547">"尚餘 <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - 剩餘約 <xliff:g id="TIME">%2$s</xliff:g>"</string>
<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>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index ad9c769..70cac5e 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -207,7 +207,7 @@
<string name="dev_settings_warning_title" msgid="7244607768088540165">"允許開發設定?"</string>
<string name="dev_settings_warning_message" msgid="2298337781139097964">"這些設定僅供開發之用,可能導致您的裝置及裝置中的應用程式毀損或運作異常。"</string>
<string name="verify_apps_over_usb_title" msgid="4177086489869041953">"透過 USB 驗證應用程式"</string>
- <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"透過 ADB/ADT 檢查安裝的應用程式是否出現有害的行為。"</string>
+ <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"檢查透過 ADB/ADT 安裝的應用程式是否具有有害行為。"</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"只要停用藍牙絕對音量功能,即可避免在連線到遠端裝置時,發生音量過大或無法控制音量等問題。"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"本機終端機"</string>
<string name="enable_terminal_summary" msgid="67667852659359206">"啟用可提供本機命令介面存取權的終端機應用程式"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index ff310cc..82ffa68 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -423,7 +423,7 @@
<string name="wifi_display_certification">Wireless display certification</string>
<!-- Setting Checkbox title whether to enable WiFi Verbose Logging. [CHAR LIMIT=40] -->
<string name="wifi_verbose_logging">Enable Wi\u2011Fi Verbose Logging</string>
- <!-- Setting Checkbox title whether to enable WiFi Aggressive Handover. [CHAR LIMIT=40] -->
+ <!-- Setting Checkbox title whether to enable WiFi Aggressive Handover (more actively switch from wifi to mobile data). [CHAR LIMIT=40] -->
<string name="wifi_aggressive_handover">Aggressive Wi\u2011Fi to mobile handover</string>
<!-- Setting Checkbox title whether to enable WiFi Scanning in the presence of traffic. [CHAR LIMIT=80] -->
<string name="wifi_allow_scan_with_traffic">Always allow Wi\u2011Fi Roam Scans</string>
@@ -431,6 +431,8 @@
<string name="mobile_data_always_on">Mobile data always active</string>
<!-- Setting Checkbox title for disabling Bluetooth absolute volume -->
<string name="bluetooth_disable_absolute_volume">Disable absolute volume</string>
+ <!-- Setting Checkbox title for enabling Bluetooth inband ringing -->
+ <string name="bluetooth_enable_inband_ringing">Enable in-band ringing</string>
<!-- UI debug setting: Select Bluetooth AVRCP Version -->
<string name="bluetooth_select_avrcp_version_string">Bluetooth AVRCP Version</string>
@@ -512,6 +514,9 @@
<string name="verify_apps_over_usb_summary">Check apps installed via ADB/ADT for harmful behavior.</string>
<!-- Summary of checkbox for disabling Bluetooth absolute volume -->
<string name="bluetooth_disable_absolute_volume_summary">Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control.</string>
+ <!-- Summary of checkbox for enabling Bluetooth inband ringing -->
+ <string name="bluetooth_enable_inband_ringing_summary">Allow ringtones on the phone to be played on Bluetooth headsets</string>
+
<!-- Title of checkbox setting that enables the terminal app. [CHAR LIMIT=32] -->
<string name="enable_terminal_title">Local terminal</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java b/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
index 5b2541c..2d8defa 100644
--- a/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
@@ -25,22 +25,21 @@
import android.os.Bundle;
import android.os.SystemClock;
import android.text.format.Formatter;
-import android.util.Log;
import android.util.SparseIntArray;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settingslib.graph.UsageView;
public class BatteryInfo {
- public String mChargeLabelString;
- public int mBatteryLevel;
- public boolean mDischarging = true;
+ public String chargeLabelString;
+ public int batteryLevel;
+ public boolean discharging = true;
public long remainingTimeUs = 0;
public String batteryPercentString;
public String remainingLabel;
public String statusLabel;
- private BatteryStats mStats;
private boolean mCharging;
+ private BatteryStats mStats;
private long timePeriod;
public interface Callback {
@@ -132,10 +131,11 @@
BatteryStats stats, long elapsedRealtimeUs, boolean shortString) {
BatteryInfo info = new BatteryInfo();
info.mStats = stats;
- info.mBatteryLevel = Utils.getBatteryLevel(batteryBroadcast);
- info.batteryPercentString = Utils.formatPercentage(info.mBatteryLevel);
+ info.batteryLevel = Utils.getBatteryLevel(batteryBroadcast);
+ info.batteryPercentString = Utils.formatPercentage(info.batteryLevel);
info.mCharging = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
final Resources resources = context.getResources();
+
info.statusLabel = Utils.getBatteryStatus(resources, batteryBroadcast);
if (!info.mCharging) {
final long drainTime = stats.computeBatteryTimeRemaining(elapsedRealtimeUs);
@@ -147,20 +147,20 @@
shortString ? R.string.power_remaining_duration_only_short
: R.string.power_remaining_duration_only,
timeString);
- info.mChargeLabelString = resources.getString(
+ info.chargeLabelString = resources.getString(
shortString ? R.string.power_discharging_duration_short
: R.string.power_discharging_duration,
info.batteryPercentString, timeString);
} else {
info.remainingLabel = null;
- info.mChargeLabelString = info.batteryPercentString;
+ info.chargeLabelString = info.batteryPercentString;
}
} else {
final long chargeTime = stats.computeChargeTimeRemaining(elapsedRealtimeUs);
final int status = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS,
BatteryManager.BATTERY_STATUS_UNKNOWN);
+ info.discharging = false;
if (chargeTime > 0 && status != BatteryManager.BATTERY_STATUS_FULL) {
- info.mDischarging = false;
info.remainingTimeUs = chargeTime;
String timeString = Formatter.formatShortElapsedTime(context,
chargeTime / 1000);
@@ -168,13 +168,13 @@
: R.string.power_charging_duration;
info.remainingLabel = resources.getString(
R.string.power_remaining_charging_duration_only, timeString);
- info.mChargeLabelString = resources.getString(resId, info.batteryPercentString,
- timeString);
+ info.chargeLabelString = resources.getString(
+ resId, info.batteryPercentString, timeString);
} else {
final String chargeStatusLabel = resources.getString(
R.string.battery_info_status_charging_lower);
info.remainingLabel = null;
- info.mChargeLabelString = resources.getString(
+ info.chargeLabelString = resources.getString(
R.string.power_charging, info.batteryPercentString, chargeStatusLabel);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 78ad34a..0ab296e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -186,6 +186,11 @@
TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
float alpha = ta.getFloat(0, 0);
ta.recycle();
+ return applyAlpha(alpha, inputColor);
+ }
+
+ @ColorInt
+ public static int applyAlpha(float alpha, int inputColor) {
alpha *= Color.alpha(inputColor);
return Color.argb((int) (alpha), Color.red(inputColor), Color.green(inputColor),
Color.blue(inputColor));
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 8833fb8c..8a86c13 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -984,18 +984,27 @@
mCurComputingSizeUserId = UserHandle.getUserId(entry.info.uid);
mBackgroundHandler.post(() -> {
- final StorageStats stats = mStats.queryStatsForPackage(
- mCurComputingSizeUuid, mCurComputingSizePkg,
- UserHandle.of(mCurComputingSizeUserId));
- final PackageStats legacyStats = new PackageStats(
- mCurComputingSizePkg, mCurComputingSizeUserId);
- legacyStats.codeSize = stats.getCodeBytes();
- legacyStats.dataSize = stats.getDataBytes();
- legacyStats.cacheSize = stats.getCacheBytes();
try {
- mStatsObserver.onGetStatsCompleted(legacyStats, true);
- } catch (RemoteException ignored) {
+ final StorageStats stats = mStats.queryStatsForPackage(
+ mCurComputingSizeUuid, mCurComputingSizePkg,
+ UserHandle.of(mCurComputingSizeUserId));
+ final PackageStats legacyStats = new PackageStats(
+ mCurComputingSizePkg, mCurComputingSizeUserId);
+ legacyStats.codeSize = stats.getCodeBytes();
+ legacyStats.dataSize = stats.getDataBytes();
+ legacyStats.cacheSize = stats.getCacheBytes();
+ try {
+ mStatsObserver.onGetStatsCompleted(legacyStats, true);
+ } catch (RemoteException ignored) {
+ }
+ } catch (IllegalStateException e) {
+ Log.e(TAG,"An exception occurred while fetching app size", e);
+ try {
+ mStatsObserver.onGetStatsCompleted(null, false);
+ } catch (RemoteException ignored) {
+ }
}
+
});
}
if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_SIZES releasing: now computing");
@@ -1493,7 +1502,8 @@
@Override
public boolean filterApp(AppEntry entry) {
- return (entry.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
+ return !AppUtils.isInstant(entry.info)
+ && (entry.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
}
};
@@ -1601,19 +1611,36 @@
}
};
- public static final AppFilter FILTER_OTHER_APPS = new AppFilter() {
+ public static final AppFilter FILTER_MOVIES = new AppFilter() {
@Override
public void init() {
}
@Override
public boolean filterApp(AppEntry entry) {
- boolean isCategorized;
+ boolean isMovieApp;
synchronized(entry) {
- isCategorized = entry.info.category == ApplicationInfo.CATEGORY_AUDIO ||
- entry.info.category == ApplicationInfo.CATEGORY_GAME;
+ isMovieApp = entry.info.category == ApplicationInfo.CATEGORY_VIDEO;
}
- return !isCategorized;
+ return isMovieApp;
}
};
+
+ public static final AppFilter FILTER_OTHER_APPS =
+ new AppFilter() {
+ @Override
+ public void init() {}
+
+ @Override
+ public boolean filterApp(AppEntry entry) {
+ boolean isCategorized;
+ synchronized (entry) {
+ isCategorized =
+ FILTER_AUDIO.filterApp(entry)
+ || FILTER_GAMES.filterApp(entry)
+ || FILTER_MOVIES.filterApp(entry);
+ }
+ return !isCategorized;
+ }
+ };
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
index 953dda2..60e10a1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
@@ -151,8 +151,15 @@
final MeasurementDetails details = new MeasurementDetails();
if (mVolume == null) return details;
- details.totalSize = mStats.getTotalBytes(mVolume.fsUuid);
- details.availSize = mStats.getFreeBytes(mVolume.fsUuid);
+ try {
+ details.totalSize = mStats.getTotalBytes(mVolume.fsUuid);
+ details.availSize = mStats.getFreeBytes(mVolume.fsUuid);
+ } catch (IllegalStateException e) {
+ // The storage volume became null while we were measuring it.
+ Log.w(TAG, e);
+ return details;
+ }
+
final long finishTotal = SystemClock.elapsedRealtime();
Log.d(TAG, "Measured total storage in " + (finishTotal - start) + "ms");
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
index 61ca13d..9d6505b 100755
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
@@ -40,9 +40,15 @@
public static final String TAG = BatteryMeterDrawableBase.class.getSimpleName();
protected final Context mContext;
+ protected final Paint mFramePaint;
+ protected final Paint mBatteryPaint;
+ protected final Paint mWarningTextPaint;
+ protected final Paint mTextPaint;
+ protected final Paint mBoltPaint;
+ protected final Paint mPlusPaint;
private int mLevel = -1;
- private boolean mPluggedIn;
+ private boolean mCharging;
private boolean mPowerSaveEnabled;
private boolean mShowPercent;
@@ -59,8 +65,6 @@
private float mButtonHeightFraction;
private float mSubpixelSmoothingLeft;
private float mSubpixelSmoothingRight;
- private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint,
- mPlusPaint;
private float mTextHeight, mWarningTextHeight;
private int mIconTint = Color.WHITE;
private float mOldDarkIntensity = -1f;
@@ -180,16 +184,24 @@
postInvalidate();
}
- public void setPluggedIn(boolean val) {
- mPluggedIn = val;
+ public void setCharging(boolean val) {
+ mCharging = val;
postInvalidate();
}
+ public boolean getCharging() {
+ return mCharging;
+ }
+
public void setBatteryLevel(int val) {
mLevel = val;
postInvalidate();
}
+ public int getBatteryLevel() {
+ return mLevel;
+ }
+
public void setPowerSave(boolean val) {
mPowerSaveEnabled = val;
postInvalidate();
@@ -314,7 +326,7 @@
mFrame.bottom -= mSubpixelSmoothingRight;
// set the battery charging color
- mBatteryPaint.setColor(mPluggedIn ? mChargeColor : getColorForLevel(level));
+ mBatteryPaint.setColor(mCharging ? mChargeColor : getColorForLevel(level));
if (level >= FULL) {
drawFrac = 1f;
@@ -337,7 +349,7 @@
mShapePath.lineTo(mButtonFrame.left, mFrame.top);
mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top);
- if (mPluggedIn) {
+ if (mCharging) {
// define the bolt shape
final float bl = mFrame.left + mFrame.width() / 4f;
final float bt = mFrame.top + mFrame.height() / 6f;
@@ -408,7 +420,7 @@
boolean pctOpaque = false;
float pctX = 0, pctY = 0;
String pctText = null;
- if (!mPluggedIn && !mPowerSaveEnabled && level > mCriticalLevel && mShowPercent) {
+ if (!mCharging && !mPowerSaveEnabled && level > mCriticalLevel && mShowPercent) {
mTextPaint.setColor(getColorForLevel(level));
mTextPaint.setTextSize(height *
(SINGLE_DIGIT_PERCENT ? 0.75f
@@ -436,7 +448,7 @@
mShapePath.op(mClipPath, Path.Op.INTERSECT);
c.drawPath(mShapePath, mBatteryPaint);
- if (!mPluggedIn && !mPowerSaveEnabled) {
+ if (!mCharging && !mPowerSaveEnabled) {
if (level <= mCriticalLevel) {
// draw the warning text
final float x = mWidth * 0.5f;
@@ -467,4 +479,8 @@
public int getOpacity() {
return 0;
}
+
+ public int getCriticalLevel() {
+ return mCriticalLevel;
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java b/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java
index c6a45bc..e2c05a1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java
@@ -35,15 +35,15 @@
public UsageView(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.usage_view, this);
- mUsageGraph = (UsageGraph) findViewById(R.id.usage_graph);
+ mUsageGraph = findViewById(R.id.usage_graph);
mLabels = new TextView[] {
- (TextView) findViewById(R.id.label_bottom),
- (TextView) findViewById(R.id.label_middle),
- (TextView) findViewById(R.id.label_top),
+ findViewById(R.id.label_bottom),
+ findViewById(R.id.label_middle),
+ findViewById(R.id.label_top),
};
mBottomLabels = new TextView[] {
- (TextView) findViewById(R.id.label_start),
- (TextView) findViewById(R.id.label_end),
+ findViewById(R.id.label_start),
+ findViewById(R.id.label_end),
};
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.UsageView, 0, 0);
if (a.hasValue(R.styleable.UsageView_sideLabels)) {
@@ -64,15 +64,15 @@
if (a.hasValue(R.styleable.UsageView_android_gravity)) {
int gravity = a.getInt(R.styleable.UsageView_android_gravity, 0);
if (gravity == Gravity.END) {
- LinearLayout layout = (LinearLayout) findViewById(R.id.graph_label_group);
- LinearLayout labels = (LinearLayout) findViewById(R.id.label_group);
+ LinearLayout layout = findViewById(R.id.graph_label_group);
+ LinearLayout labels = findViewById(R.id.label_group);
// Swap the children order.
layout.removeView(labels);
layout.addView(labels);
// Set gravity.
labels.setGravity(Gravity.END);
// Swap the bottom space order.
- LinearLayout bottomLabels = (LinearLayout) findViewById(R.id.bottom_label_group);
+ LinearLayout bottomLabels = findViewById(R.id.bottom_label_group);
View bottomSpace = bottomLabels.findViewById(R.id.bottom_label_space);
bottomLabels.removeView(bottomSpace);
bottomLabels.addView(bottomSpace);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 901848a..9e9bc93 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -985,25 +985,32 @@
return false;
}
+ /** Attempt to update the AccessPoint and return true if an update occurred. */
public boolean update(WifiConfiguration config, WifiInfo info, NetworkInfo networkInfo) {
- boolean reorder = false;
+ boolean updated = false;
+ final int oldLevel = getLevel();
if (info != null && isInfoForThisAccessPoint(config, info)) {
- reorder = (mInfo == null);
- mRssi = info.getRssi();
- mInfo = info;
- mNetworkInfo = networkInfo;
- if (mAccessPointListener != null) {
- mAccessPointListener.onAccessPointChanged(this);
+ updated = (mInfo == null);
+ if (mRssi != info.getRssi()) {
+ mRssi = info.getRssi();
+ updated = true;
}
+ mInfo = info;
+ // TODO(b/37289220): compare NetworkInfo states and set updated = true if necessary
+ mNetworkInfo = networkInfo;
} else if (mInfo != null) {
- reorder = true;
+ updated = true;
mInfo = null;
mNetworkInfo = null;
- if (mAccessPointListener != null) {
- mAccessPointListener.onAccessPointChanged(this);
+ }
+ if (updated && mAccessPointListener != null) {
+ mAccessPointListener.onAccessPointChanged(this);
+
+ if (oldLevel != getLevel() /* current level */) {
+ mAccessPointListener.onLevelChanged(this);
}
}
- return reorder;
+ return updated;
}
void update(WifiConfiguration config) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index fc8c42c..f277165 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -203,6 +203,7 @@
mFilter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
mFilter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
mNetworkRequest = new NetworkRequest.Builder()
.clearCapabilities()
@@ -640,20 +641,24 @@
(System.currentTimeMillis() - before) + "ms.");
}
- boolean reorder = false;
+ boolean updated = false;
+ boolean reorder = false; // Only reorder if connected AP was changed
for (int i = mInternalAccessPoints.size() - 1; i >= 0; --i) {
AccessPoint ap = mInternalAccessPoints.get(i);
+ boolean previouslyConnected = ap.isActive();
if (ap.update(connectionConfig, mLastInfo, mLastNetworkInfo)) {
- reorder = true;
+ updated = true;
+ if (previouslyConnected != ap.isActive()) reorder = true;
}
if (ap.update(mScoreCache, mNetworkScoringUiEnabled)) {
reorder = true;
+ updated = true;
}
}
- if (reorder) {
- Collections.sort(mInternalAccessPoints);
- mMainHandler.scheduleAPCopyingAndCloseWriteLock();
- }
+
+ if (reorder) Collections.sort(mInternalAccessPoints);
+
+ if (updated) mMainHandler.scheduleAPCopyingAndCloseWriteLock();
}
/**
@@ -718,6 +723,8 @@
mWorkHandler.obtainMessage(WorkHandler.MSG_UPDATE_NETWORK_INFO, info)
.sendToTarget();
mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
+ } else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
+ mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_NETWORK_INFO);
}
}
};
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
index 6a029f0..fed18fa 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
@@ -174,6 +174,13 @@
}
@Test
+ public void testOtherAppsRejectsLegacyGame() {
+ mEntry.info.flags = ApplicationInfo.FLAG_IS_GAME;
+
+ assertThat(ApplicationsState.FILTER_OTHER_APPS.filterApp(mEntry)).isFalse();
+ }
+
+ @Test
public void testInstantFilterAcceptsInstantApp() {
when(mEntry.info.isInstantApp()).thenReturn(true);
assertThat(ApplicationsState.FILTER_INSTANT.filterApp(mEntry)).isTrue();
@@ -194,10 +201,40 @@
}
@Test
+ public void testFilterWithDomainUrls() {
+ mEntry.info.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
+ // should included updated system apps
+ when(mEntry.info.isInstantApp()).thenReturn(false);
+ assertThat(ApplicationsState.FILTER_WITH_DOMAIN_URLS.filterApp(mEntry))
+ .isTrue();
+ mEntry.info.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
+ assertThat(ApplicationsState.FILTER_WITH_DOMAIN_URLS.filterApp(mEntry))
+ .isFalse();
+ mEntry.info.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
+ when(mEntry.info.isInstantApp()).thenReturn(true);
+ assertThat(ApplicationsState.FILTER_WITH_DOMAIN_URLS.filterApp(mEntry))
+ .isFalse();
+ }
+
+ @Test
public void testDisabledFilterRejectsInstantApp() {
mEntry.info.enabled = false;
assertThat(ApplicationsState.FILTER_DISABLED.filterApp(mEntry)).isTrue();
when(mEntry.info.isInstantApp()).thenReturn(true);
assertThat(ApplicationsState.FILTER_DISABLED.filterApp(mEntry)).isFalse();
}
+
+ @Test
+ public void testVideoFilterAcceptsCategorizedVideo() {
+ mEntry.info.category = ApplicationInfo.CATEGORY_VIDEO;
+
+ assertThat(ApplicationsState.FILTER_MOVIES.filterApp(mEntry)).isTrue();
+ }
+
+ @Test
+ public void testVideosFilterRejectsNotVideo() {
+ mEntry.info.category = ApplicationInfo.CATEGORY_GAME;
+
+ assertThat(ApplicationsState.FILTER_MOVIES.filterApp(mEntry)).isFalse();
+ }
}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
index 4de2c12..83667ea 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
@@ -55,12 +55,12 @@
final int levels[] = { 0, 1, 5, 10, 25, 50, 75, 90, 95, 99, 100 };
final boolean bools[] = { false, true };
for (int l : levels) {
- for (boolean plugged : bools) {
+ for (boolean charging : bools) {
for (boolean saver : bools) {
for (boolean percent : bools) {
mBatteryDrawable.setBatteryLevel(l);
mBatteryDrawable.setPowerSave(saver);
- mBatteryDrawable.setPluggedIn(plugged);
+ mBatteryDrawable.setCharging(charging);
mBatteryDrawable.setShowPercent(percent);
mBatteryDrawable.draw(canvas);
}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
index 85b04c8..820231e 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
@@ -159,14 +159,14 @@
for (String pkg : defaultImes) {
final ResolveInfo ri = createResolveInfoForSystemApp(pkg);
final InputMethodInfo inputMethodInfo = new InputMethodInfo(
- ri, false, null, null, 0, true, true, false);
+ ri, false, null, null, 0, true, true);
inputMethods.add(inputMethodInfo);
addInstalledApp(ri);
}
for (String pkg : otherImes) {
final ResolveInfo ri = createResolveInfoForSystemApp(pkg);
final InputMethodInfo inputMethodInfo = new InputMethodInfo(
- ri, false, null, null, 0, false, true, false);
+ ri, false, null, null, 0, false, true);
inputMethods.add(inputMethodInfo);
addInstalledApp(ri);
}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index b71915f..f9e695d 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -23,6 +23,7 @@
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
@@ -100,6 +101,16 @@
private static final byte SCORE_2 = 15;
private static final int BADGE_2 = NetworkBadging.BADGING_HD;
+ private static final int CONNECTED_NETWORK_ID = 123;
+ private static final int CONNECTED_RSSI = -50;
+ private static final WifiInfo CONNECTED_AP_1_INFO = new WifiInfo();
+ static {
+ CONNECTED_AP_1_INFO.setSSID(WifiSsid.createFromAsciiEncoded(SSID_1));
+ CONNECTED_AP_1_INFO.setBSSID(BSSID_1);
+ CONNECTED_AP_1_INFO.setNetworkId(CONNECTED_NETWORK_ID);
+ CONNECTED_AP_1_INFO.setRssi(CONNECTED_RSSI);
+ }
+
@Captor ArgumentCaptor<WifiNetworkScoreCache> mScoreCacheCaptor;
@Mock private ConnectivityManager mockConnectivityManager;
@Mock private NetworkScoreManager mockNetworkScoreManager;
@@ -312,18 +323,12 @@
private WifiTracker createTrackerWithScanResultsAndAccessPoint1Connected()
throws InterruptedException {
- int networkId = 123;
-
- WifiInfo wifiInfo = new WifiInfo();
- wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(SSID_1));
- wifiInfo.setBSSID(BSSID_1);
- wifiInfo.setNetworkId(networkId);
- when(mockWifiManager.getConnectionInfo()).thenReturn(wifiInfo);
+ when(mockWifiManager.getConnectionInfo()).thenReturn(CONNECTED_AP_1_INFO);
WifiConfiguration configuration = new WifiConfiguration();
configuration.SSID = SSID_1;
configuration.BSSID = BSSID_1;
- configuration.networkId = networkId;
+ configuration.networkId = CONNECTED_NETWORK_ID;
when(mockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(configuration));
NetworkInfo networkInfo = new NetworkInfo(
@@ -445,7 +450,8 @@
}
@Test
- public void scoreCacheUpdateScoresShouldTriggerOnAccessPointsChanged() throws InterruptedException {
+ public void scoreCacheUpdateScoresShouldTriggerOnAccessPointsChanged()
+ throws InterruptedException {
WifiTracker tracker = createMockedWifiTracker();
startTracking(tracker);
sendScanResultsAndProcess(tracker);
@@ -463,7 +469,7 @@
@Test
public void scoreCacheUpdateScoresShouldChangeSortOrder() throws InterruptedException {
- WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
+ WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
List<AccessPoint> aps = tracker.getAccessPoints();
assertTrue(aps.size() == 2);
assertEquals(aps.get(0).getSsidStr(), SSID_1);
@@ -636,4 +642,28 @@
tracker.forceUpdate();
verify(mockWifiManager).getMatchingWifiConfig(any(ScanResult.class));
}
-}
+
+ @Test
+ public void rssiChangeBroadcastShouldUpdateConnectedAp() throws Exception {
+ WifiTracker tracker = createTrackerWithScanResultsAndAccessPoint1Connected();
+ assertThat(tracker.getAccessPoints().get(0).isActive()).isTrue();
+
+ WifiConfiguration configuration = new WifiConfiguration();
+ configuration.SSID = SSID_1;
+ configuration.BSSID = BSSID_1;
+ configuration.networkId = CONNECTED_NETWORK_ID;
+ when(mockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(configuration));
+
+ int newRssi = CONNECTED_RSSI + 10;
+ WifiInfo info = new WifiInfo(CONNECTED_AP_1_INFO);
+ info.setRssi(newRssi);
+ when(mockWifiManager.getConnectionInfo()).thenReturn(info);
+
+ mAccessPointsChangedLatch = new CountDownLatch(1);
+ tracker.mReceiver.onReceive(mContext, new Intent(WifiManager.RSSI_CHANGED_ACTION));
+ assertTrue(mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
+
+ verify(mockWifiManager, atLeast(2)).getConnectionInfo();
+ assertThat(tracker.getAccessPoints().get(0).getRssi()).isEqualTo(newRssi);
+ }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/BatteryInfoTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/BatteryInfoTest.java
index 962c4e7..69efc9e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/BatteryInfoTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/BatteryInfoTest.java
@@ -32,6 +32,7 @@
import org.robolectric.annotation.Config;
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.eq;
@@ -44,10 +45,12 @@
private static final String STATUS_FULL = "Full";
private static final String STATUS_CHARGING_NO_TIME = "Charging";
private static final String STATUS_CHARGING_TIME = "Charging - 2h left";
+ private static final int PLUGGED_IN = 1;
private static final long REMAINING_TIME_NULL = -1;
private static final long REMAINING_TIME = 2;
private Intent mDisChargingBatteryBroadcast;
private Intent mChargingBatteryBroadcast;
+
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private BatteryStats mBatteryStats;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
@@ -95,7 +98,7 @@
BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast,
mBatteryStats, SystemClock.elapsedRealtime() * 1000, false);
- assertThat(info.mChargeLabelString).isEqualTo(STATUS_CHARGING_TIME);
+ assertThat(info.chargeLabelString).isEqualTo(STATUS_CHARGING_TIME);
}
@Test
@@ -104,6 +107,14 @@
BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast,
mBatteryStats, SystemClock.elapsedRealtime() * 1000, false);
- assertThat(info.mChargeLabelString).isEqualTo(STATUS_CHARGING_NO_TIME);
+ assertThat(info.chargeLabelString).isEqualTo(STATUS_CHARGING_NO_TIME);
+ }
+
+ @Test
+ public void testGetBatteryInfo_pluggedIn_dischargingFalse() {
+ BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast,
+ mBatteryStats, SystemClock.elapsedRealtime() * 1000, true);
+
+ assertThat(info.discharging).isEqualTo(false);
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 4a54c0e..bac694f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1435,8 +1435,8 @@
Settings.Secure.DEMO_USER_SETUP_COMPLETE,
SecureSettingsProto.DEMO_USER_SETUP_COMPLETE);
dumpSetting(s, p,
- Settings.Secure.WEB_ACTION_ENABLED,
- SecureSettingsProto.WEB_ACTION_ENABLED);
+ Settings.Secure.INSTANT_APPS_ENABLED,
+ SecureSettingsProto.INSTANT_APPS_ENABLED);
dumpSetting(s, p,
Settings.Secure.DEVICE_PAIRED,
SecureSettingsProto.DEVICE_PAIRED);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 0c4c699..e6d9a9a 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -71,6 +71,7 @@
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.MOVE_PACKAGE" />
<uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
+ <uses-permission android:name="android.permission.CLEAR_APP_CACHE" />
<uses-permission android:name="android.permission.DELETE_CACHE_FILES" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
diff --git a/packages/Shell/res/values-b+sr+Latn/strings.xml b/packages/Shell/res/values-b+sr+Latn/strings.xml
index 5809bfc..805aed6 100644
--- a/packages/Shell/res/values-b+sr+Latn/strings.xml
+++ b/packages/Shell/res/values-b+sr+Latn/strings.xml
@@ -23,7 +23,9 @@
<string name="bugreport_updating_title" msgid="4423539949559634214">"Dodaju se detalji u izveštaj o grešci"</string>
<string name="bugreport_updating_wait" msgid="3322151947853929470">"Sačekajte..."</string>
<string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"Izveštaj o grešci će se uskoro pojaviti na telefonu"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Izaberite da biste delili izveštaj o grešci"</string>
<string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Dodirnite da biste delili izveštaj o grešci"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Izaberite da biste delili izveštaj o grešci bez snimka ekrana ili sačekajte da se napravi snimak ekrana"</string>
<string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Dodirnite za deljenje izveštaja o grešci bez snimka ekrana ili sačekajte da se napravi snimak ekrana"</string>
<string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Dodirnite za deljenje izveštaja o grešci bez snimka ekrana ili sačekajte da se napravi snimak ekrana"</string>
<string name="bugreport_confirm" msgid="5917407234515812495">"Izveštaji o greškama sadrže podatke iz različitih sistemskih datoteka evidencije, koji obuhvataju lične i privatne podatke (poput korišćenja aplikacija i podataka o lokaciji). Delite izveštaje o greškama samo sa aplikacijama i ljudima u koje imate poverenja."</string>
diff --git a/packages/Shell/res/values-be/strings.xml b/packages/Shell/res/values-be/strings.xml
index f69317c..bea1c30 100644
--- a/packages/Shell/res/values-be/strings.xml
+++ b/packages/Shell/res/values-be/strings.xml
@@ -23,7 +23,9 @@
<string name="bugreport_updating_title" msgid="4423539949559634214">"Дадаванне падрабязнасцей да справаздачы пра памылкі"</string>
<string name="bugreport_updating_wait" msgid="3322151947853929470">"Калі ласка, пачакайце..."</string>
<string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"Паведамленне пра памылку хутка з\'явіцца на тэлефоне"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Выберыце, каб абагуліць справаздачу пра памылку"</string>
<string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Дакраніцеся, каб абагуліць сваю справаздачу пра памылку"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Выберыце, каб абагуліць справаздачу пра памылку без здымка экрана, або чакайце атрымання здымка"</string>
<string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Краніце, каб абагуліць справаздачу пра памылку без здымка экрана, або чакайце атрымання здымка."</string>
<string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Краніце, каб абагуліць справаздачу пра памылку без здымка экрана, або чакайце атрымання здымка."</string>
<string name="bugreport_confirm" msgid="5917407234515812495">"Справаздачы пра памылкі ўтрымліваюць даныя з розных файлаў журналаў сістэмы, якія могуць уключаць даныя, што вы лічыце канфідэнцыяльнымі (напрыклад, пра выкарыстанне праграм і даныя аб месцазнаходжанні). Абагульвайце справаздачы пра памылкі толькі з тымі людзьмі і праграмамі, якім вы давяраеце."</string>
diff --git a/packages/Shell/res/values-bs/strings.xml b/packages/Shell/res/values-bs/strings.xml
index 8815e94..fab8063 100644
--- a/packages/Shell/res/values-bs/strings.xml
+++ b/packages/Shell/res/values-bs/strings.xml
@@ -23,7 +23,9 @@
<string name="bugreport_updating_title" msgid="4423539949559634214">"Dodavanje detalja u izvještaj o greškama"</string>
<string name="bugreport_updating_wait" msgid="3322151947853929470">"Pričekajte..."</string>
<string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"Izvještaj o greškama će se ubrzo pojaviti na ekranu"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Odaberite da podijelite izvještaj o greškama"</string>
<string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Dodirnite da biste podijelili izvještaj o grešci"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Odaberite da podijelite izvještaj o greškama bez snimka ekrana ili sačekajte da snimak bude gotov"</string>
<string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Dodirnite da podijelite izveštaj o greškama bez snimka ekrana ili sačekajte da snimak bude gotov"</string>
<string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Dodirnite da podijelite izveštaj o greškama bez snimka ekrana ili sačekajte da snimak bude gotov"</string>
<string name="bugreport_confirm" msgid="5917407234515812495">"Izvještaji o greškama sadrže podatke iz raznih zapisnika sistema koji mogu sadržavati lične i privatne informacije koje smatrate osjetljivima (poput podataka o upotrebi aplikacije ili podataka o lokaciji). Izvještaje o greškama dijelite samo sa aplikacijama i osobama kojima vjerujete."</string>
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 53c5b1b..5ee0c64 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -35,6 +35,7 @@
android-support-v7-preference \
android-support-v7-appcompat \
android-support-v7-mediarouter \
+ android-support-v7-palette \
android-support-v14-preference \
android-support-v17-leanback
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
index 8dde357..4a7d0fd 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
@@ -37,7 +37,7 @@
public interface NotificationMenuRowPlugin extends Plugin {
public static final String ACTION = "com.android.systemui.action.PLUGIN_NOTIFICATION_MENU_ROW";
- public static final int VERSION = 1;
+ public static final int VERSION = 2;
@ProvidesInterface(version = OnMenuEventListener.VERSION)
public interface OnMenuEventListener {
@@ -89,6 +89,8 @@
public void onHeightUpdate();
+ public void onNotificationUpdated();
+
public boolean onTouchEvent(View view, MotionEvent ev, float velocity);
public default boolean useDefaultMenuItems() {
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_emergency_carrier_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_emergency_carrier_area.xml
index 3ea22e9..39cba74 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_emergency_carrier_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_emergency_carrier_area.xml
@@ -32,10 +32,8 @@
android:id="@+id/carrier_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ style="@style/Keyguard.TextView"
android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="@dimen/kg_status_line_font_size"
- android:textColor="?android:attr/textColorSecondary"
android:visibility="gone"
androidprv:allCaps="@bool/kg_use_all_caps" />
@@ -46,10 +44,7 @@
android:layout_weight="1"
android:layout_marginTop="@dimen/eca_overlap"
android:text="@*android:string/lockscreen_emergency_call"
- style="?android:attr/buttonBarButtonStyle"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="@dimen/kg_status_line_font_size"
- android:textColor="?android:attr/textColorSecondary"
+ style="@style/Keyguard.TextView.EmergencyButton"
android:textAllCaps="@bool/kg_use_all_caps" />
</com.android.keyguard.EmergencyCarrierArea>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_message_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_message_area.xml
index 46aa39d..e1bf6cb 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_message_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_message_area.xml
@@ -23,11 +23,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
+ style="@style/Keyguard.TextView"
android:id="@+id/keyguard_message_area"
android:singleLine="true"
android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearance"
- android:textSize="@dimen/kg_status_line_font_size"
- android:textColor="?android:attr/textColorSecondary"
android:focusable="true" />
diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
index c7cfe88..b28a0cc 100644
--- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
@@ -116,7 +116,7 @@
<string name="kg_prompt_reason_switch_profiles_pattern" msgid="3398054847288438444">"Treba da unesete šablon kada prelazite sa jednog profila na drugi"</string>
<string name="kg_prompt_reason_switch_profiles_pin" msgid="7426368139226961699">"Treba da unesete PIN kada prelazite sa jednog profila na drugi"</string>
<string name="kg_prompt_reason_switch_profiles_password" msgid="8383831046318421845">"Treba da unesete lozinku kada prelazite sa jednog profila na drugi"</string>
- <string name="kg_prompt_reason_device_admin" msgid="2438626748767361010">"Administrator uređaja je zaključao uređaj"</string>
+ <string name="kg_prompt_reason_device_admin" msgid="3452168247888906179">"Administrator je zaključao uređaj"</string>
<string name="kg_prompt_reason_user_request" msgid="8236951765212462286">"Uređaj je ručno zaključan"</string>
<plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="71299470072448533">
<item quantity="one">Niste otključali uređaj <xliff:g id="NUMBER_1">%d</xliff:g> sat. Potvrdite šablon.</item>
diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml
index e1dfc04..89caf90 100644
--- a/packages/SystemUI/res-keyguard/values-be/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-be/strings.xml
@@ -118,7 +118,7 @@
<string name="kg_prompt_reason_switch_profiles_pattern" msgid="3398054847288438444">"Пры пераключэнні профіляў патрабуецца ўзор"</string>
<string name="kg_prompt_reason_switch_profiles_pin" msgid="7426368139226961699">"Пры пераключэнні профіляў патрабуецца PIN-код"</string>
<string name="kg_prompt_reason_switch_profiles_password" msgid="8383831046318421845">"Пры пераключэнні профіляў патрабуецца пароль"</string>
- <string name="kg_prompt_reason_device_admin" msgid="2438626748767361010">"Адміністратар прылады заблакіраваў яе"</string>
+ <string name="kg_prompt_reason_device_admin" msgid="3452168247888906179">"Прылада заблакіравана адміністратарам"</string>
<string name="kg_prompt_reason_user_request" msgid="8236951765212462286">"Прылада была заблакіравана ўручную"</string>
<plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="71299470072448533">
<item quantity="one">Прылада не была разблакіравана на працягу <xliff:g id="NUMBER_1">%d</xliff:g> гадзіны. Увядзіце ўзор.</item>
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index 04256f1..86f81bc 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -62,8 +62,8 @@
<string name="kg_sim_pin_instructions_multi" msgid="1586316574649150223">"Unesite PIN kôd za SIM karticu operatera \"<xliff:g id="CARRIER">%1$s</xliff:g>\""</string>
<string name="kg_pin_instructions" msgid="4069609316644030034">"Unesite PIN kôd"</string>
<string name="kg_password_instructions" msgid="136952397352976538">"Unesite lozinku"</string>
- <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM kartica je sada onemogućena. Unesite PUK kôd da nastavite. Obratite se operateru za detalje."</string>
- <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"Operater SIM kartice \"<xliff:g id="CARRIER">%1$s</xliff:g>\" sada je onemogućen. Unesite PUK kôd da nastavite. Za više detalja obratite se operateru."</string>
+ <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM kartica je sada onemogućena. Unesite PUK kôd da nastavite. Za više informacija obratite se operateru."</string>
+ <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"Operater SIM kartice \"<xliff:g id="CARRIER">%1$s</xliff:g>\" sada je onemogućen. Unesite PUK kôd da nastavite. Za više informacija obratite se operateru."</string>
<string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"Unesite željeni PIN kôd"</string>
<string name="kg_enter_confirm_pin_hint" msgid="3089485999116759671">"Potvrdite željeni PIN kôd"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"Otključavanje SIM kartice…"</string>
@@ -116,7 +116,7 @@
<string name="kg_prompt_reason_switch_profiles_pattern" msgid="3398054847288438444">"Potreban je uzorak nakon prelaska na drugi profil"</string>
<string name="kg_prompt_reason_switch_profiles_pin" msgid="7426368139226961699">"Potreban je PIN kôd nakon prelaska na drugi profil"</string>
<string name="kg_prompt_reason_switch_profiles_password" msgid="8383831046318421845">"Potrebna je lozinka nakon prelaska na drugi profil"</string>
- <string name="kg_prompt_reason_device_admin" msgid="2438626748767361010">"Administrator je zaključao uređaj."</string>
+ <string name="kg_prompt_reason_device_admin" msgid="3452168247888906179">"Uređaj je zaključao administrator"</string>
<string name="kg_prompt_reason_user_request" msgid="8236951765212462286">"Uređaj je ručno zaključan"</string>
<plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="71299470072448533">
<item quantity="one">Uređaj nije otključavan <xliff:g id="NUMBER_1">%d</xliff:g> sat. Potvrdite uzorak.</item>
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index dede537..53a559f 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -19,6 +19,15 @@
<resources>
<!-- Keyguard PIN pad styles -->
+ <style name="Keyguard.TextView" parent="@android:style/Widget.DeviceDefault.TextView">
+ <item name="android:textColor">@*android:color/primary_device_default_light</item>
+ <item name="android:textSize">@dimen/kg_status_line_font_size</item>
+ </style>
+ <style name="Keyguard.TextView.EmergencyButton" parent="@android:style/DeviceDefault.ButtonBar">
+ <item name="android:textColor">@*android:color/primary_device_default_light</item>
+ <item name="android:textSize">@dimen/kg_status_line_font_size</item>
+ <item name="android:background">@null</item>
+ </style>
<style name="Widget.TextView.NumPadKey" parent="@android:style/Widget.TextView">
<item name="android:singleLine">true</item>
<item name="android:gravity">center_horizontal|center_vertical</item>
diff --git a/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png
index 6737c80..32f1ed7 100644
--- a/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png
index d9e33eb..33826a6 100644
--- a/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png
index 64daf20..c1157f4 100644
--- a/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png
index 49e0499..8d58a7e 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png
index 0e6ca16..6c04d1a 100644
--- a/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png
+++ b/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_activity_down.xml b/packages/SystemUI/res/drawable/ic_activity_down.xml
new file mode 100644
index 0000000..526c987
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_activity_down.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="5dp"
+ android:height="17.0dp"
+ android:viewportWidth="7.1"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M3.6000004,13.2l-3.6,0.0 3.6,7.3 0.0,0.0 0.0,0.0 0.0,0.0 0.0,0.0 3.5,-7.3z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_activity_up.xml b/packages/SystemUI/res/drawable/ic_activity_up.xml
new file mode 100644
index 0000000..8d18beb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_activity_up.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="5dp"
+ android:height="17.0dp"
+ android:viewportWidth="7.1"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M3.6000004,10.8l3.5,0.0 -3.5,-7.3 0.0,0.0 0.0,0.0 0.0,0.0 0.0,0.0 -3.6,7.3z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_data_off.xml b/packages/SystemUI/res/drawable/ic_data_off.xml
new file mode 100644
index 0000000..b97ddae
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_data_off.xml
@@ -0,0 +1,27 @@
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M21.6,21.6L10.8,10.9L2.1,2.1L0.8,3.4l3.3,3.3C3.1,8.2 2.5,10.0 2.5,12.0c0.0,5.2 4.3,9.5 9.5,9.5c2.0,0.0 3.8,-0.6 5.3,-1.6l3.0,3.0L21.6,21.6zM9.6,12.2l0.7,0.7L9.6,12.9L9.6,12.2zM13.9,18.6c-0.2,0.2 -0.5,0.2 -0.6,0.0l-2.4,-3.7l1.5,0.0l2.4,2.4L13.9,18.6z"
+ android:fillColor="#ffffff"/>
+ <path
+ android:pathData="M12.0,2.5c-2.0,0.0 -3.8,0.6 -5.3,1.6l2.5,2.5L10.0,5.4c0.2,-0.2 0.5,-0.2 0.6,0.0L13.0,9.1l-1.4,0.0l2.0,2.0l0.6,0.0l0.0,0.6l5.6,5.6c1.0,-1.5 1.6,-3.3 1.6,-5.3C21.5,6.8 17.2,2.5 12.0,2.5z"
+ android:fillColor="#ffffff"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_data_on.xml b/packages/SystemUI/res/drawable/ic_data_on.xml
new file mode 100644
index 0000000..a65dc79
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_data_on.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M12.0,12.0m-9.5,0.0a9.5,9.5 0.0,1.0 1.0,19.0 0.0a9.5,9.5 0.0,1.0 1.0,-19.0 0.0
+ M10.6,5.4c-0.2,-0.2 -0.5,-0.2 -0.6,0.0L7.6,9.1l2.0,0.0l0.0,3.8L11.0,12.900001L11.0,9.1l2.0,0.0L10.6,5.4z
+ M13.3,18.6c0.2,0.2 0.5,0.2 0.6,0.0l2.4,-3.7l-2.0,0.0l0.0,-3.8l-1.4,0.0l0.0,3.8l-2.0,0.0L13.3,18.6z"
+ android:fillColor="#ffffff"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_data_unavailable.xml b/packages/SystemUI/res/drawable/ic_data_unavailable.xml
new file mode 100644
index 0000000..27a7697
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_data_unavailable.xml
@@ -0,0 +1,32 @@
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ M12.0,12.0m-9.5,0.0a9.5,9.5 0.0,1.0 1.0,19.0 0.0a9.5,9.5 0.0,1.0 1.0,-19.0 0.0
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M12.0,2.5c-5.246705,0.0 -9.5,4.253295 -9.5,9.5 0.0,5.246705 4.253295,9.5 9.5,9.5 2.771732,0.0 5.263364,-1.200342 7.0,-3.09375l0.0,-0.21875 0.0,-7.5 0.0,-1.0 1.0,0.0 1.1875,0.0C20.148497,5.5674677 16.442669,2.5 12.0,2.5zm9.1875,7.1875c-14.125,9.541667 -7.0625,4.770833 0.0,0.0z
+ M10.6,5.4C10.4,5.2 10.1,5.2 10.0,5.4L7.6,9.1l2.0,0.0l0.0,3.8L11.0,12.900001L11.0,9.1l2.0,0.0L10.6,5.4z
+ M13.3,18.6c0.2,0.2 0.5,0.2 0.6,0.0l2.4,-3.7l-2.0,0.0l0.0,-3.8l-1.4,0.0l0.0,3.8l-2.0,0.0l2.4,3.7z
+ M21.7,24.0c-0.5,0.0 -0.8,-0.1 -1.1,-0.4c-0.3,-0.3 -0.4,-0.6 -0.4,-1.0c0.0,-0.4 0.1,-0.8 0.4,-1.0c0.3,-0.3 0.7,-0.4 1.1,-0.4s0.8,0.1 1.1,0.4c0.3,0.3 0.4,0.6 0.4,1.0c0.0,0.4 -0.1,0.7 -0.4,1.0
+ C22.6,23.8 22.2,24 21.7,24z
+ M20.4,19.7l0.0,-8.5L23.0,11.2l0.0,8.5L20.4,19.7z
+ "
+ android:fillType="evenOdd"
+ android:fillColor="#231F20"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml
index 8ea9e06..0bdbc5f 100644
--- a/packages/SystemUI/res/drawable/qs_background_primary.xml
+++ b/packages/SystemUI/res/drawable/qs_background_primary.xml
@@ -15,6 +15,6 @@
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android">
<shape>
- <solid android:color="?android:attr/colorPrimary"/>
+ <solid android:color="?android:attr/colorPrimaryDark"/>
</shape>
</inset>
diff --git a/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml b/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml
index 0b2bd22..e27bc7a 100644
--- a/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml
+++ b/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml
@@ -14,8 +14,8 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
+ android:width="18.0dp"
+ android:height="18.0dp"
android:viewportWidth="48.0"
android:viewportHeight="48.0">
diff --git a/packages/SystemUI/res/layout/mobile_signal_group.xml b/packages/SystemUI/res/layout/mobile_signal_group.xml
index d988acc..33effba 100644
--- a/packages/SystemUI/res/layout/mobile_signal_group.xml
+++ b/packages/SystemUI/res/layout/mobile_signal_group.xml
@@ -16,48 +16,67 @@
** limitations under the License.
*/
-->
-<FrameLayout
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/mobile_combo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:orientation="horizontal"
>
- <com.android.systemui.statusbar.AnimatedImageView
- android:theme="@style/DualToneLightTheme"
- android:id="@+id/mobile_signal"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- systemui:hasOverlappingRendering="false"
- />
- <com.android.systemui.statusbar.AnimatedImageView
- android:theme="@style/DualToneDarkTheme"
- android:id="@+id/mobile_signal_dark"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:alpha="0.0"
- systemui:hasOverlappingRendering="false"
- />
- <ImageView
- android:id="@+id/mobile_type"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- />
- <ImageView
- android:id="@+id/mobile_roaming"
- android:layout_width="wrap_content"
+ <FrameLayout
android:layout_height="17dp"
- android:paddingStart="22dp"
- android:paddingTop="1.5dp"
- android:paddingBottom="3dp"
- android:scaleType="fitCenter"
- android:src="@drawable/stat_sys_roaming"
- android:contentDescription="@string/accessibility_data_connection_roaming"
- android:visibility="gone" />
- <ImageView
- android:id="@+id/mobile_inout"
- android:layout_height="wrap_content"
+ android:layout_width="wrap_content">
+ <ImageView
+ android:id="@+id/mobile_in"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:src="@drawable/ic_activity_down"
+ android:visibility="gone"
+ android:paddingEnd="2dp"
+ />
+ <ImageView
+ android:id="@+id/mobile_out"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:src="@drawable/ic_activity_up"
+ android:paddingEnd="2dp"
+ android:visibility="gone"
+ />
+ </FrameLayout>
+ <FrameLayout
android:layout_width="wrap_content"
- android:visibility="gone"
- />
-</FrameLayout>
+ android:layout_height="wrap_content">
+ <com.android.systemui.statusbar.AnimatedImageView
+ android:theme="@style/DualToneLightTheme"
+ android:id="@+id/mobile_signal"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ systemui:hasOverlappingRendering="false"
+ />
+ <com.android.systemui.statusbar.AnimatedImageView
+ android:theme="@style/DualToneDarkTheme"
+ android:id="@+id/mobile_signal_dark"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:alpha="0.0"
+ systemui:hasOverlappingRendering="false"
+ />
+ <ImageView
+ android:id="@+id/mobile_type"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ />
+ <ImageView
+ android:id="@+id/mobile_roaming"
+ android:layout_width="wrap_content"
+ android:layout_height="17dp"
+ android:paddingStart="22dp"
+ android:paddingTop="1.5dp"
+ android:paddingBottom="3dp"
+ android:scaleType="fitCenter"
+ android:src="@drawable/stat_sys_roaming"
+ android:contentDescription="@string/accessibility_data_connection_roaming"
+ android:visibility="gone" />
+ </FrameLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/pip_dismiss_view.xml b/packages/SystemUI/res/layout/pip_dismiss_view.xml
index 34228d9..058f59f 100644
--- a/packages/SystemUI/res/layout/pip_dismiss_view.xml
+++ b/packages/SystemUI/res/layout/pip_dismiss_view.xml
@@ -27,6 +27,10 @@
android:layout_gravity="bottom|center_horizontal"
android:text="@string/pip_phone_dismiss_hint"
android:textColor="#FFFFFFFF"
- android:textSize="14sp" />
+ android:textSize="14sp"
+ android:shadowColor="@android:color/black"
+ android:shadowDx="-2"
+ android:shadowDy="2"
+ android:shadowRadius="0.01" />
</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/pip_menu_activity.xml b/packages/SystemUI/res/layout/pip_menu_activity.xml
index 44ced17..8c66bab 100644
--- a/packages/SystemUI/res/layout/pip_menu_activity.xml
+++ b/packages/SystemUI/res/layout/pip_menu_activity.xml
@@ -26,16 +26,6 @@
android:layout_height="match_parent"
android:forceHasOverlappingRendering="false">
- <ImageView
- android:id="@+id/dismiss"
- android:layout_width="@dimen/pip_action_size"
- android:layout_height="@dimen/pip_action_size"
- android:layout_gravity="top|end"
- android:padding="@dimen/pip_action_padding"
- android:contentDescription="@string/pip_phone_close"
- android:src="@drawable/ic_close_white"
- android:background="?android:selectableItemBackgroundBorderless" />
-
<!-- The margins for this container is calculated in the code depending on whether the
actions_container is visible. -->
<FrameLayout
@@ -67,4 +57,15 @@
android:showDividers="middle" />
</FrameLayout>
</FrameLayout>
+
+ <ImageView
+ android:id="@+id/dismiss"
+ android:layout_width="@dimen/pip_action_size"
+ android:layout_height="@dimen/pip_action_size"
+ android:layout_gravity="top|end"
+ android:padding="@dimen/pip_action_padding"
+ android:contentDescription="@string/pip_phone_close"
+ android:src="@drawable/ic_close_white"
+ android:background="?android:selectableItemBackgroundBorderless" />
+
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/qs_divider.xml b/packages/SystemUI/res/layout/qs_divider.xml
index 660e4af..39d48ea 100644
--- a/packages/SystemUI/res/layout/qs_divider.xml
+++ b/packages/SystemUI/res/layout/qs_divider.xml
@@ -16,6 +16,5 @@
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="1dp"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="16dp"
+ android:alpha=".12"
android:background="?android:attr/colorForeground" />
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index 64caefd..9b53a97 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -21,7 +21,7 @@
android:clipChildren="false"
android:clipToPadding="false"
android:minHeight="48dp"
- android:paddingTop="8dp">
+ android:paddingTop="12dp">
<LinearLayout
android:id="@+id/label_group"
android:layout_width="wrap_content"
@@ -31,6 +31,10 @@
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="horizontal">
+ <Space
+ android:id="@+id/expand_space"
+ android:layout_width="22dp"
+ android:layout_height="0dp" />
<TextView
android:id="@+id/tile_label"
@@ -44,14 +48,6 @@
android:textAppearance="@style/TextAppearance.QS.TileLabel"
android:textColor="?android:attr/textColorPrimary"/>
- <ImageView
- android:id="@+id/expand_indicator"
- android:layout_marginStart="4dp"
- android:layout_width="12dp"
- android:layout_height="match_parent"
- android:src="@drawable/qs_dual_tile_caret"
- android:tint="?android:attr/textColorPrimary" />
-
<ImageView android:id="@+id/restricted_padlock"
android:layout_width="@dimen/qs_tile_text_size"
android:layout_height="match_parent"
@@ -60,6 +56,14 @@
android:layout_marginLeft="@dimen/restricted_padlock_pading"
android:scaleType="centerInside"
android:visibility="gone" />
+
+ <ImageView
+ android:id="@+id/expand_indicator"
+ android:layout_marginStart="4dp"
+ android:layout_width="18dp"
+ android:layout_height="match_parent"
+ android:src="@drawable/qs_dual_tile_caret"
+ android:tint="?android:attr/textColorPrimary" />
</LinearLayout>
<TextView
@@ -85,6 +89,7 @@
android:layout_alignStart="@id/label_group"
android:layout_alignEnd="@id/label_group"
android:layout_below="@id/label_group"
+ android:visibility="gone"
android:alpha="?android:attr/disabledAlpha"
android:background="?android:attr/colorForeground"/>
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml
new file mode 100644
index 0000000..f3a6d44
--- /dev/null
+++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<!-- Note all width/height dimensions are switched here to handle landspace
+ rather than duplicating them all.
+ This layout matches the structure of navigation_bar.xml (rot90) and
+ will need to be kept up to sync with changes there.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/screen_pinning_buttons"
+ android:layout_height="match_parent"
+ android:layout_width="@dimen/screen_pinning_request_button_height"
+ android:background="?android:attr/colorAccent"
+ android:orientation="vertical">
+
+ <View
+ android:layout_height="@dimen/screen_pinning_request_side_width"
+ android:layout_width="match_parent"
+ android:layout_weight="0"
+ android:visibility="invisible" />
+
+ <FrameLayout
+ android:id="@+id/screen_pinning_back_group"
+ android:layout_height="@dimen/screen_pinning_request_button_width"
+ android:layout_width="@dimen/screen_pinning_request_button_height"
+ android:layout_weight="0"
+ android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent">
+
+ <ImageView
+ android:id="@+id/screen_pinning_back_bg_light"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:scaleType="matrix"
+ android:layout_marginLeft="@dimen/screen_pinning_request_seascape_padding_negative"
+ android:src="@drawable/screen_pinning_light_bg_circ" />
+
+ <ImageView
+ android:id="@+id/screen_pinning_back_bg"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:scaleType="matrix"
+ android:layout_marginLeft="@dimen/screen_pinning_request_seascape_button_offset"
+ android:paddingRight="@dimen/screen_pinning_request_inner_padding"
+ android:paddingTop="@dimen/screen_pinning_request_inner_padding"
+ android:paddingBottom="@dimen/screen_pinning_request_inner_padding"
+ android:src="@drawable/screen_pinning_bg_circ" />
+
+ <ImageView
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:scaleType="center"
+ android:paddingRight="@dimen/screen_pinning_request_nav_icon_padding"
+ android:paddingTop="@dimen/screen_pinning_request_nav_side_padding"
+ android:paddingBottom="@dimen/screen_pinning_request_nav_side_padding"
+ android:src="@drawable/ic_sysbar_back" />
+ </FrameLayout>
+
+ <View
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:layout_weight="1"
+ android:visibility="invisible" />
+
+ <FrameLayout
+ android:id="@+id/screen_pinning_home_group"
+ android:layout_height="@dimen/screen_pinning_request_button_width"
+ android:layout_width="@dimen/screen_pinning_request_button_height"
+ android:layout_weight="0" >
+
+ <ImageView
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:scaleType="center"
+ android:paddingRight="@dimen/screen_pinning_request_nav_icon_padding"
+ android:paddingTop="@dimen/screen_pinning_request_nav_side_padding"
+ android:paddingBottom="@dimen/screen_pinning_request_nav_side_padding"
+ android:src="@drawable/ic_sysbar_home" />
+ </FrameLayout>
+
+ <View
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:layout_weight="1"
+ android:visibility="invisible" />
+
+ <FrameLayout
+ android:id="@+id/screen_pinning_recents_group"
+ android:layout_height="@dimen/screen_pinning_request_button_width"
+ android:layout_width="@dimen/screen_pinning_request_button_height"
+ android:layout_weight="0"
+ android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent">
+
+ <ImageView
+ android:id="@+id/screen_pinning_recents_bg_light"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:scaleType="matrix"
+ android:layout_marginLeft="@dimen/screen_pinning_request_seascape_padding_negative"
+ android:src="@drawable/screen_pinning_light_bg_circ" />
+
+ <ImageView
+ android:id="@+id/screen_pinning_recents_bg"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:scaleType="matrix"
+ android:layout_marginLeft="@dimen/screen_pinning_request_seascape_button_offset"
+ android:paddingRight="@dimen/screen_pinning_request_inner_padding"
+ android:paddingTop="@dimen/screen_pinning_request_inner_padding"
+ android:paddingBottom="@dimen/screen_pinning_request_inner_padding"
+ android:src="@drawable/screen_pinning_bg_circ" />
+
+ <ImageView
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:scaleType="center"
+ android:paddingRight="@dimen/screen_pinning_request_nav_icon_padding"
+ android:paddingTop="@dimen/screen_pinning_request_nav_side_padding"
+ android:paddingBottom="@dimen/screen_pinning_request_nav_side_padding"
+ android:src="@drawable/ic_sysbar_recent" />
+ </FrameLayout>
+
+ <View
+ android:layout_height="@dimen/screen_pinning_request_side_width"
+ android:layout_width="match_parent"
+ android:layout_weight="0"
+ android:visibility="invisible" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_sea_phone.xml b/packages/SystemUI/res/layout/screen_pinning_request_sea_phone.xml
new file mode 100644
index 0000000..770cead
--- /dev/null
+++ b/packages/SystemUI/res/layout/screen_pinning_request_sea_phone.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="@dimen/screen_pinning_request_width"
+ android:layout_width="wrap_content"
+ android:gravity="left|center_vertical"
+ android:orientation="horizontal"
+ android:theme="@android:style/Theme.DeviceDefault.Light">
+
+ <include
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/screen_pinning_request_width"
+ layout="@layout/screen_pinning_request_buttons_sea" />
+
+ <include
+ android:layout_width="360dp"
+ android:layout_height="@dimen/screen_pinning_request_width"
+ layout="@layout/screen_pinning_request_text_area" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index 4d03f0f..da7e4d7 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -53,6 +53,26 @@
/>
</FrameLayout>
<FrameLayout
+ android:layout_height="17dp"
+ android:layout_width="wrap_content">
+ <ImageView
+ android:id="@+id/wifi_in"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:src="@drawable/ic_activity_down"
+ android:visibility="gone"
+ android:paddingEnd="2dp"
+ />
+ <ImageView
+ android:id="@+id/wifi_out"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:src="@drawable/ic_activity_up"
+ android:paddingEnd="2dp"
+ android:visibility="gone"
+ />
+ </FrameLayout>
+ <FrameLayout
android:id="@+id/wifi_combo"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index c0be676..8707840 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -18,104 +18,155 @@
<com.android.systemui.volume.ZenModePanel xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/zen_mode_panel"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:clipChildren="false"
- android:orientation="vertical" >
-
- <com.android.systemui.volume.SegmentedButtons
- android:id="@+id/zen_buttons"
- android:background="@drawable/segmented_buttons_background"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="16dp"
- android:layout_marginTop="8dp"
- android:layout_marginBottom="8dp" />
-
- <RelativeLayout
- android:id="@+id/zen_introduction"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="16dp"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- android:background="@drawable/zen_introduction_message_background"
- android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent.Light">
-
- <ImageView
- android:id="@+id/zen_introduction_confirm"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_marginEnd="8dp"
- android:layout_alignParentEnd="true"
- android:background="@drawable/btn_borderless_rect"
- android:clickable="true"
- android:contentDescription="@string/accessibility_desc_close"
- android:scaleType="center"
- android:src="@drawable/ic_close"
- android:tint="@android:color/white" />
-
- <TextView
- android:id="@+id/zen_introduction_message"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:layout_marginStart="24dp"
- android:textDirection="locale"
- android:lineSpacingMultiplier="1.20029"
- android:layout_toStartOf="@id/zen_introduction_confirm"
- android:textAppearance="@style/TextAppearance.QS.Introduction" />
-
- <TextView
- android:id="@+id/zen_introduction_customize"
- style="@style/QSBorderlessButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentEnd="true"
- android:layout_marginEnd="12dp"
- android:layout_below="@id/zen_introduction_message"
- android:clickable="true"
- android:focusable="true"
- android:text="@string/zen_priority_customize_button"
- android:textAppearance="@style/TextAppearance.QS.DetailButton.White" />
-
- <View
- android:layout_width="0dp"
- android:layout_height="16dp"
- android:layout_below="@id/zen_introduction_message"
- android:layout_alignParentEnd="true" />
-
- </RelativeLayout>
+ android:layout_height="match_parent"
+ android:clipChildren="false" >
<LinearLayout
- android:id="@+id/zen_conditions"
+ android:id="@+id/edit_container"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:layout_marginEnd="4dp"
- android:layout_marginStart="4dp"
- android:paddingBottom="@dimen/zen_mode_condition_detail_bottom_padding"
- android:orientation="horizontal" >
+ android:layout_height="match_parent"
+ android:background="?android:attr/colorPrimary"
+ android:clipChildren="false"
+ android:orientation="vertical">
+
+ <com.android.systemui.volume.SegmentedButtons
+ android:id="@+id/zen_buttons"
+ android:background="@drawable/segmented_buttons_background"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp" />
+
+ <RelativeLayout
+ android:id="@+id/zen_introduction"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:background="@drawable/zen_introduction_message_background"
+ android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent.Light">
+
+ <ImageView
+ android:id="@+id/zen_introduction_confirm"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_marginEnd="8dp"
+ android:layout_alignParentEnd="true"
+ android:background="@drawable/btn_borderless_rect"
+ android:clickable="true"
+ android:contentDescription="@string/accessibility_desc_close"
+ android:scaleType="center"
+ android:src="@drawable/ic_close"
+ android:tint="@android:color/white" />
+
+ <TextView
+ android:id="@+id/zen_introduction_message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="12dp"
+ android:layout_marginStart="24dp"
+ android:textDirection="locale"
+ android:lineSpacingMultiplier="1.20029"
+ android:layout_toStartOf="@id/zen_introduction_confirm"
+ android:textAppearance="@style/TextAppearance.QS.Introduction" />
+
+ <TextView
+ android:id="@+id/zen_introduction_customize"
+ style="@style/QSBorderlessButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_marginEnd="12dp"
+ android:layout_below="@id/zen_introduction_message"
+ android:clickable="true"
+ android:focusable="true"
+ android:text="@string/zen_priority_customize_button"
+ android:textAppearance="@style/TextAppearance.QS.DetailButton.White" />
+
+ <View
+ android:layout_width="0dp"
+ android:layout_height="16dp"
+ android:layout_below="@id/zen_introduction_message"
+ android:layout_alignParentEnd="true" />
+
+ </RelativeLayout>
+
+ <LinearLayout
+ android:id="@+id/zen_conditions"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_marginEnd="4dp"
+ android:layout_marginStart="4dp"
+ android:paddingBottom="@dimen/zen_mode_condition_detail_bottom_padding"
+ android:orientation="horizontal" >
<RadioGroup
- android:id="@+id/zen_radio_buttons"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
+ android:id="@+id/zen_radio_buttons"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
<LinearLayout
- android:id="@+id/zen_radio_buttons_content"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"/>
+ android:id="@+id/zen_radio_buttons_content"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical"/>
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/zen_alarm_warning"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="18dp"
+ android:layout_marginEnd="16dp"
+ android:textDirection="locale"
+ android:lineSpacingMultiplier="1.20029"
+ android:textAppearance="@style/TextAppearance.QS.Warning" />
</LinearLayout>
- <TextView
- android:id="@+id/zen_alarm_warning"
+ <LinearLayout
+ android:id="@android:id/empty"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="18dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:background="?android:attr/colorPrimary"
+ android:gravity="center"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="56dp"
+ android:layout_height="56dp"
+ android:alpha="?android:attr/disabledAlpha"
+ android:tint="?android:attr/colorForeground" />
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dp"
+ android:textAppearance="@style/TextAppearance.QS.DetailEmpty"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/auto_rule"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="?android:attr/colorPrimary"
+ android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
- android:textDirection="locale"
- android:lineSpacingMultiplier="1.20029"
- android:textAppearance="@style/TextAppearance.QS.Warning" />
+ android:layout_marginTop="16dp"
+ android:layout_marginBottom="8dp"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary"/>
+
+ </LinearLayout>
</com.android.systemui.volume.ZenModePanel>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 8b5fab1..5859838 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Battery laai tans, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> persent."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Stelselinstellings"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Kennisgewings"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Kennisgewingoorloophouer"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Sien alle kennisgewings"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Verwyder kennisgewing"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS geaktiveer."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS soek ligging."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Alle kategorieë"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Meer instellings"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Pasmaak: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Klaar"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"kennisgewingkontroles"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is af"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is af"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Moenie steur nie is af"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"\'n Outomatiese reël (<xliff:g id="ID_1">%s</xliff:g>) het Moenie steur nie aangeskakel. Hou huidige instellings?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"\'n Program (<xliff:g id="ID_1">%s</xliff:g>) het Moenie steur nie aangeskakel. Hou huidige instellings?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"\'n Outomatiese reël of \'n program het Moenie steur nie aangeskakel. Hou huidige instellings?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Tot <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Hou"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Vervang"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index fba8bc4..97b8317 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ባትሪ ኃይል በመሙላት ላይ፣ <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> በመቶ።"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"የስርዓት ቅንብሮች"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"ማሳወቂያዎች"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"የማሳወቂያ ትርፍ ፍሰት መያዣ"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"ሁሉንም ማሳወቂያዎች ይመልከቱ"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"ማሳወቂያ አጽዳ"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ነቅቷል።"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS በማግኘት ላይ።"</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"ሁሉም ምድቦች"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ተጨማሪ ቅንብሮች"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"ያብጁ፦ <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"ተከናውኗል"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"የማሳወቂያ መቆጣጠሪያዎች"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ጠፍቷል"</string>
<string name="bt_is_off" msgid="2640685272289706392">"ብሉቱዝ ጠፍቷል"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"አትረብሽ ጠፍቷል"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"አትረብሽ በአንድ ራስ-ሰር ደንብ (<xliff:g id="ID_1">%s</xliff:g>) በርቷል። የአሁኖቹ ቅንብሮች ይቀመጡ?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"አትረብሽ በአንድ መተግበሪያ (<xliff:g id="ID_1">%s</xliff:g>) በርቷል። የአሁኖቹ ቅንብሮች ይቀመጡ?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"አትረብሽ በአንድ ራስ-ሰር ደንብ ወይም መተግበሪያ በርቷል። የአሁኖቹ ቅንብሮች ይቀመጡ?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"እስከ <xliff:g id="ID_1">%s</xliff:g> ድረስ"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"አቆይ"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"ተካ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index ec35335..f646dfa 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -168,7 +168,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"جارٍ شحن البطارية، <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> بالمائة."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"إعدادات النظام."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"الإشعارات."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"حاوية التدفق الزائد للإشعارات"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"الاطلاع على جميع الإشعارات"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"محو الإشعار."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"تم تمكين GPS."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"الحصول على GPS."</string>
@@ -576,8 +576,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"كل الفئات"</string>
<string name="notification_more_settings" msgid="816306283396553571">"المزيد من الإعدادات"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"تخصيص: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"تم"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"عناصر التحكم في الإشعارات"</string>
@@ -759,9 +758,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"تم إيقاف شبكة Wi-Fi"</string>
<string name="bt_is_off" msgid="2640685272289706392">"تم إيقاف البلوتوث."</string>
<string name="dnd_is_off" msgid="6167780215212497572">"تم إيقاف وضع \"الرجاء عدم الإزعاج\""</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"تم تشغيل وضع \"الرجاء عدم الإزعاج\" بواسطة قاعدة تلقائية (<xliff:g id="ID_1">%s</xliff:g>). هل تريد الإبقاء على الإعدادات الحالية؟"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"تم تشغيل وضع \"الرجاء عدم الإزعاج\" بواسطة تطبيق (<xliff:g id="ID_1">%s</xliff:g>). هل تريد الإبقاء على الإعدادات الحالية؟"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"تم تشغيل وضع \"الرجاء عدم الإزعاج\" بواسطة قاعدة تلقائية أو تطبيق. هل تريد الإبقاء على الإعدادات الحالية؟"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"حتى <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"الإبقاء على الإعدادات"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"استبدال"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 5c62018..3223aa7 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Batareya doldurulur, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> faiz."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Sistem parametrləri"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Bildirişlər."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Bildiriş daşması konteyneri"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Bütün bildirişlərə baxın"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Bildirişi təmizlə."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS aktivdir."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS əldə edilir."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Bütün Kateqoriyalar"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Daha çox ayar"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Fərdiləşdirin: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Hazırdır"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"bildiriş nəzarəti"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi deaktivdir"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth deaktivdir"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"\"Narahat Etməyin\" deaktivdir"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"\"Narahat etməyin\" rejimi (<xliff:g id="ID_1">%s</xliff:g>) avtomatik qaydası tərəfindən aktiv edildi. Cari ayarlar saxlanılsın?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"\"Narahat etməyin\" (<xliff:g id="ID_1">%s</xliff:g>) tətbiqi tərəfindən aktiv edildi. Cari ayarlar saxlanılsın?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"\"Narahat etməyin\" rejimi avtomatik qayda və ya tətbiq tərəfindən aktiv edildi. Cari ayarlar saxlanılsın?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> vaxtına qədər"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Saxlayın"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Əvəz edin"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 0b44eb5..1a1883c 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -76,7 +76,7 @@
<string name="screenshot_failed_title" msgid="705781116746922771">"Nije moguće napraviti snimak ekrana."</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Došlo je do problema pri čuvanju snimka ekrana."</string>
<string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Čuvanje snimka ekrana nije uspelo zbog ograničenog memorijskog prostora."</string>
- <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikacija ili organizacija ne dozvoljavaju pravljenje snimaka ekrana."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Aplikacija ili organizacija ne dozvoljavaju pravljenje snimaka ekrana"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prenosa datoteka"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Priključi kao medija plejer (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Priključi kao kameru (PTP)"</string>
@@ -91,7 +91,7 @@
<string name="accessibility_phone_button" msgid="6738112589538563574">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="487611083884852965">"Glasovna pomoć"</string>
<string name="accessibility_unlock_button" msgid="128158454631118828">"Otključajte"</string>
- <string name="accessibility_unlock_button_fingerprint" msgid="8214125623493923751">"Dugme za otključavanje, čeka se na otisak prsta"</string>
+ <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"Čeka se otisak prsta"</string>
<string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Otključaj bez korišćenja otiska prsta"</string>
<string name="unlock_label" msgid="8779712358041029439">"otključaj"</string>
<string name="phone_label" msgid="2320074140205331708">"otvori telefon"</string>
@@ -165,7 +165,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Baterija se puni, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procenata."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Sistemska podešavanja."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Obaveštenja."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Kontejner preklopnog menija za obaveštenja"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Pogledajte sva obaveštenja"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Obriši obaveštenje."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS je omogućen."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Učitavanje GPS-a."</string>
@@ -237,8 +237,7 @@
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Ušteda podataka je isključena."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Ušteda podataka je uključena."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Osvetljenost ekrana"</string>
- <!-- no translation found for accessibility_ambient_display_charging (9084521679384069087) -->
- <skip />
+ <string name="accessibility_ambient_display_charging" msgid="9084521679384069087">"Puni se"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G podaci su pauzirani"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G podaci su pauzirani"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobilni podaci su pauzirani"</string>
@@ -279,7 +278,7 @@
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Osvetljenost"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatska rotacija"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Automatsko rotiranje ekrana"</string>
- <string name="accessibility_quick_settings_rotation_value" msgid="1428962304214992318">"Podesi na <xliff:g id="ID_1">%s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_rotation_value" msgid="8187398200140760213">"Režim <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotacija je zaključana"</string>
<string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"Vertikalni prikaz"</string>
<string name="quick_settings_rotation_locked_landscape_label" msgid="8553157770061178719">"Horizontalni prikaz"</string>
@@ -337,7 +336,6 @@
<string name="recents_launch_error_message" msgid="2969287838120550506">"Pokretanje aplikacije <xliff:g id="APP">%s</xliff:g> nije uspelo."</string>
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"Aplikacija <xliff:g id="APP">%s</xliff:g> je onemogućena u bezbednom režimu."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Obriši sve"</string>
- <string name="recents_incompatible_app_message" msgid="5075812958564082451">"Aplikacija ne podržava podeljeni ekran"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Prevucite ovde da biste koristili razdeljeni ekran"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podeli horizontalno"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podeli vertikalno"</string>
@@ -363,7 +361,7 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Manje hitna obaveštenja su u nastavku"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Dodirnite ponovo da biste otvorili"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Prevucite nagore da biste otključali"</string>
- <string name="do_disclosure_generic" msgid="8498005633306135779">"Ovim uređajem se upravlja"</string>
+ <string name="do_disclosure_generic" msgid="5615898451805157556">"Ovim uređajem upravlja organizacija"</string>
<string name="do_disclosure_with_name" msgid="5640615509915445501">"Ovim uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Prevucite od ikone za telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Prevucite od ikone za glasovnu pomoć"</string>
@@ -416,13 +414,40 @@
<string name="profile_owned_footer" msgid="8021888108553696069">"Profil se možda nadgleda"</string>
<string name="vpn_footer" msgid="2388611096129106812">"Mreža se možda nadgleda"</string>
<string name="branded_vpn_footer" msgid="2168111859226496230">"Mreža se možda nadgleda"</string>
+ <string name="quick_settings_disclosure_management_monitoring" msgid="6645176135063957394">"Organizacija upravlja ovim uređajem i može da nadgleda mrežni saobraćaj"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="370622174777570853">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> upravlja ovim uređajem i može da nadgleda mrežni saobraćaj"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="1085137869053332307">"Uređajem upravlja organizacija i povezan je sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="6290456493852584017">"Uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i povezan je sa aplikacijom <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="3294967280853150271">"Uređajem upravlja organizacija"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="1059403025094542908">"Ovim uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="3698767349925266482">"Uređajem upravlja organizacija i povezan je sa VPN-ovima"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="7777821385318891527">"Uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i povezan je sa VPN-ovima"</string>
+ <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="5125463987558278215">"Organizacija može da prati mrežni saobraćaj na profilu za Work"</string>
+ <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8973606847896650284">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> može da nadgleda mrežni saobraćaj na profilu za Work"</string>
+ <string name="quick_settings_disclosure_monitoring" msgid="679658227269205728">"Mreža se možda nadgleda"</string>
+ <string name="quick_settings_disclosure_vpns" msgid="8170318392053156330">"Uređaj je povezan sa VPN-ovima"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="3494535754792751741">"Profil za Work je povezan sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="4467456202486569906">"Lični profil je povezan sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="6943724064780847080">"Uređaj je povezan sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7121079311903859610">"Nadgledanje uređaja"</string>
<string name="monitoring_title_profile_owned" msgid="6790109874733501487">"Nadgledanje profila"</string>
<string name="monitoring_title" msgid="169206259253048106">"Nadgledanje mreže"</string>
<string name="monitoring_subtitle_vpn" msgid="876537538087857300">"VPN"</string>
- <string name="monitoring_subtitle_network_logging" msgid="5569072711320784030">"Evidentiranje mreže"</string>
+ <string name="monitoring_subtitle_network_logging" msgid="3341264304793193386">"Evidentiranje mreže"</string>
+ <string name="monitoring_subtitle_ca_certificate" msgid="3874151893894355988">"CA sertifikati"</string>
<string name="disable_vpn" msgid="4435534311510272506">"Onemogući VPN"</string>
<string name="disconnect_vpn" msgid="1324915059568548655">"Prekini vezu sa VPN-om"</string>
+ <string name="monitoring_button_view_policies" msgid="100913612638514424">"Prikaži smernice"</string>
+ <string name="monitoring_description_named_management" msgid="4872859182820011954">"Uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nAdministrator može da nadgleda podešavanja, korporativni pristup, aplikacije, podatke povezane sa uređajem i informacije o lokaciji uređaja, kao i da upravlja njima.\n\nViše informacija potražite od administratora."</string>
+ <string name="monitoring_description_management" msgid="3115563193381106341">"Uređajem upravlja organizacija.\n\nAdministrator može da nadgleda podešavanja, korporativni pristup, aplikacije, podatke povezane sa uređajem i informacije o lokaciji uređaja, kao i da upravlja njima.\n\nViše informacija potražite od administratora."</string>
+ <string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"Organizacija je na ovom uređaju instalirala autoritet za izdavanje sertifikata. Bezbedni mrežni saobraćaj može da se prati ili menja."</string>
+ <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"Organizacija je na profilu za Work instalirala autoritet za izdavanje sertifikata. Bezbedni mrežni saobraćaj može da se prati ili menja."</string>
+ <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"Na ovom uređaju je instaliran autoritet za izdavanje sertifikata. Bezbedni mrežni saobraćaj može da se prati ili menja."</string>
+ <string name="monitoring_description_management_network_logging" msgid="7184005419733060736">"Administrator je uključio evidentiranje mreže, koje prati saobraćaj na uređaju."</string>
+ <string name="monitoring_description_named_vpn" msgid="639013857356724268">"Povezani ste sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može da nadgleda aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
+ <string name="monitoring_description_two_named_vpns" msgid="4479748971871539316">"Povezani ste sa aplikacijama <xliff:g id="VPN_APP_0">%1$s</xliff:g> i <xliff:g id="VPN_APP_1">%2$s</xliff:g>, koje mogu da nadgledaju aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
+ <string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"Profil za Work je povezan sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može da nadgleda aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
+ <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"Lični profil je povezan sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može da nadgleda aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
<string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Uređajem upravlja <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>."</string>
<string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> koristi <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> za upravljanje uređajem."</string>
<string name="monitoring_description_do_body" msgid="3639594537660975895">"Administrator može da nadgleda podešavanja, korporativni pristup, aplikacije, podatke povezane sa uređajem i informacije o lokaciji uređaja, kao i da upravlja njima."</string>
@@ -431,15 +456,17 @@
<string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Povezani ste sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može da nadgleda aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
<string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Otvorite podešavanja VPN-a"</string>
+ <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string>
+ <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Otvorite pouzdane akreditive"</string>
<string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administrator je uključio evidentiranje mreže, koje prati saobraćaj na uređaju.\n\nKontaktirajte administratora za više informacija."</string>
<string name="monitoring_description_vpn" msgid="4445150119515393526">"Dali ste dozvolu aplikaciji da podešava VPN vezu.\n\nTa aplikacija može da nadgleda aktivnosti na uređaju i mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> upravlja profilom za Work.\n\nAdministrator može da prati aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove.\n\nKontaktirajte administratora za više informacija.\n\nPovezani ste i sa VPN-om, koji može da prati aktivnosti na mreži."</string>
<string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
- <string name="monitoring_description_app" msgid="6259179342284742878">"Povezani ste sa aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može da nadgleda aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
+ <string name="monitoring_description_app" msgid="1828472472674709532">"Povezani ste sa aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može da nadgleda aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
<string name="monitoring_description_app_personal" msgid="484599052118316268">"Povezani ste sa aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može da nadgleda aktivnosti na ličnoj mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Povezani ste sa aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može da nadgleda aktivnosti na ličnoj mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
- <string name="monitoring_description_app_work" msgid="7777228449969022305">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> upravlja profilom za Work. On je povezan sa aplikacijom <xliff:g id="APPLICATION">%2$s</xliff:g>, koja može da prati aktivnosti na poslovnoj mreži, uključujući imejlove, aplikacije i veb-sajtove.\n\nKontaktirajte administratora za više informacija."</string>
- <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Profilom za Work upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Povezan je sa aplikacijom <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, koja može da nadgleda aktivnosti na poslovnoj mreži, uključujući imejlove, aplikacije i veb-sajtove.\n\nPovezani ste i sa aplikacijom <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, koja može da nadgleda aktivnosti na ličnoj mreži."</string>
+ <string name="monitoring_description_app_work" msgid="4612997849787922906">"Profilom za Work upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Povezan je sa aplikacijom <xliff:g id="APPLICATION">%2$s</xliff:g>, koja može da nadgleda aktivnosti na poslovnoj mreži, uključujući imejlove, aplikacije i veb-sajtove.\n\nViše informacija potražite od administratora."</string>
+ <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Profilom za Work upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Povezan je sa aplikacijom <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, koja može da nadgleda aktivnosti na poslovnoj mreži, uključujući imejlove, aplikacije i veb-sajtove.\n\nPovezani ste i sa aplikacijom <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, koja može da nadgleda aktivnosti na ličnoj mreži."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Uređaj će ostati zaključan dok ga ne otključate ručno"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Brže dobijajte obaveštenja"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Pregledajte ih pre otključavanja"</string>
@@ -470,10 +497,8 @@
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Dodirnite da biste uključili zvuk."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Dodirnite da biste podesili na vibraciju. Zvuk usluga pristupačnosti će možda biti isključen."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Dodirnite da biste isključili zvuk. Zvuk usluga pristupačnosti će možda biti isključen."</string>
- <!-- no translation found for volume_stream_content_description_vibrate_a11y (6427727603978431301) -->
- <skip />
- <!-- no translation found for volume_stream_content_description_mute_a11y (8995013018414535494) -->
- <skip />
+ <string name="volume_stream_content_description_vibrate_a11y" msgid="6427727603978431301">"%1$s. Dodirnite da biste podesili na vibraciju."</string>
+ <string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Dodirnite da biste isključili zvuk."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Kontrole za jačinu zvuka (%s) su prikazane. Prevucite nagore da biste ih odbacili."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Kontrole za jačinu zvuka su sakrivene"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Tjuner za korisnički interfejs sistema"</string>
@@ -524,13 +549,22 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Pomoću naprednih kontrola za obaveštenja možete da podesite nivo važnosti od 0. do 5. za obaveštenja aplikacije. \n\n"<b>"5. nivo"</b>" \n– Prikazuju se u vrhu liste obaveštenja \n- Dozvoli prekid režima celog ekrana \n– Uvek zaviruj \n\n"<b>"4. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Uvek zaviruj \n\n"<b>"3. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Nikada ne zaviruj \n\n"<b>"2. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Nikada ne zaviruj \n– Nikada ne proizvodi zvuk ili vibraciju \n\n"<b>"1. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Nikada ne zaviruj \n– Nikada ne proizvodi zvuk ili vibraciju \n– Sakrij na zaključanom ekranu i statusnoj traci \n– Prikazuju se u dnu liste obaveštenja \n\n"<b>"0. nivo"</b>" \n– Blokiraj sva obaveštenja iz aplikacije"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Obaveštenja"</string>
<string name="notification_channel_disabled" msgid="5805874247999578073">"Više nećete da dobijate ova obaveštenja."</string>
- <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
- <item quantity="one">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije iz ove aplikacije</item>
- <item quantity="few">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije iz ove aplikacije</item>
- <item quantity="other">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorija iz ove aplikacije</item>
+ <string name="notification_num_channels" msgid="2048144408999179471">"Kategorija obaveštenja: <xliff:g id="NUMBER">%d</xliff:g>"</string>
+ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ova aplikacija nema kategorije obaveštenja"</string>
+ <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
+ <item quantity="one">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije obaveštenja za ovu aplikaciju</item>
+ <item quantity="few">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije obaveštenja za ovu aplikaciju</item>
+ <item quantity="other">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorija obaveštenja za ovu aplikaciju</item>
+ </plurals>
+ <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
+ <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
+ <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> i još <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
+ <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> i još <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
+ <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> i još <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Sve kategorije"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Još podešavanja"</string>
+ <string name="notification_app_settings" msgid="3743278649182392015">"Prilagodite: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"kontrole obaveštenja"</string>
@@ -538,7 +572,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuta"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minuta"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 sat"</string>
- <string name="snooze_option_dont_snooze" msgid="655446566007801922">"Ne odlaži"</string>
+ <string name="snooze_option_dont_snooze" msgid="2252098379349499668">"Otkaži"</string>
<string name="snooze_undo" msgid="6074877317002985129">"OPOZOVI"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Odloženo je za <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Potrošnja baterije"</string>
@@ -680,6 +714,10 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Proširi"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Umanji"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Zatvori"</string>
+ <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Prevucite nadole da biste odbili"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Meni Slika u slici"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> je slika u slici"</string>
+ <string name="pip_notification_message" msgid="4171698133469539591">"Ako ne želite da <xliff:g id="NAME">%s</xliff:g> koristi ovu funkciju, dodirnite da biste otvorili podešavanja i isključili je."</string>
<string name="high_temp_title" msgid="4589508026407318374">"Telefon se zagrejao"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Neke funkcije su ograničene dok se telefon ne ohladi"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Telefon će automatski pokušati da se ohladi. I dalje ćete moći da koristite telefon, ali će sporije reagovati.\n\nKada se telefon ohladi, normalno će raditi."</string>
@@ -702,9 +740,19 @@
<string name="notification_channel_general" msgid="4525309436693914482">"Opšte poruke"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Memorijski prostor"</string>
<string name="instant_apps" msgid="6647570248119804907">"Instant aplikacije"</string>
- <!-- no translation found for pip_menu_title (3328510504196964712) -->
- <skip />
<string name="instant_apps_message" msgid="8116608994995104836">"Instant aplikacije ne zahtevaju instalaciju."</string>
<string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
<string name="mobile_data" msgid="7094582042819250762">"Mobilni podaci"</string>
+ <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je isključen"</string>
+ <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je isključen"</string>
+ <string name="dnd_is_off" msgid="6167780215212497572">"Režim Ne uznemiravaj je isključen"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
+ <string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
+ <string name="qs_dnd_keep" msgid="1825009164681928736">"Zadrži"</string>
+ <string name="qs_dnd_replace" msgid="8019520786644276623">"Zameni"</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
index 8b01a83..67cdbd8 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
@@ -27,7 +27,4 @@
<string name="pip_onboarding_title" msgid="7850436557670253991">"Slika u slici"</string>
<string name="pip_onboarding_description" msgid="4028124563309465267">"Na ovaj način će video biti prikazan dok ne pustite neki drugi. Pritisnite i zadržite "<b>"POČETNA"</b>" da biste ga kontrolisali."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Važi"</string>
- <string name="recents_tv_dismiss" msgid="3555093879593377731">"Odbaci"</string>
- <string-array name="recents_tv_blacklist_array">
- </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 0796cff..59aa605 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -77,7 +77,7 @@
<string name="screenshot_failed_title" msgid="705781116746922771">"Не атрымалася зрабiць скрыншот."</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Падчас захавання скрыншота адбылася памылка."</string>
<string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Немагчыма захаваць здымак экрана, бо мала месца ў памяці."</string>
- <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Рабіць здымкі экрана не дазваляе праграма ці ваша арганізацыя."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Рабіць здымкі экрана не дазваляе праграма ці ваша арганізацыя"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Парам. перадачы файлаў па USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Падлучыць як медыяпрайгравальнік (ССП)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Падлучыць як камеру (PTP)"</string>
@@ -92,7 +92,7 @@
<string name="accessibility_phone_button" msgid="6738112589538563574">"Тэлефон"</string>
<string name="accessibility_voice_assist_button" msgid="487611083884852965">"Галасавая дапамога"</string>
<string name="accessibility_unlock_button" msgid="128158454631118828">"Разблакiраваць"</string>
- <string name="accessibility_unlock_button_fingerprint" msgid="8214125623493923751">"Кнопка разблакіроўкі, чаканне адбітка пальца"</string>
+ <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"Чаканне ўводу даных адбітка пальца"</string>
<string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Разблакіроўка без выкарыстання адбітка пальца"</string>
<string name="unlock_label" msgid="8779712358041029439">"разблакiраваць"</string>
<string name="phone_label" msgid="2320074140205331708">"адкрыць тэлефон"</string>
@@ -168,7 +168,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Зарадка акумулятара, працэнтаў: <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Сістэмныя налады."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Апавяшчэнні."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Кантэйнер для апавяшчэнняў пры перапаўненні"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Паказаць усе апавяшчэнні"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Выдаліць апавяшчэнне."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS уключаны."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Атрыманне GPS."</string>
@@ -240,8 +240,7 @@
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Эканомія трафіку адключана."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Эканомія трафіку ўключана."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Яркасць дысплэя"</string>
- <!-- no translation found for accessibility_ambient_display_charging (9084521679384069087) -->
- <skip />
+ <string name="accessibility_ambient_display_charging" msgid="9084521679384069087">"Ідзе зарадка"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Перадача даных 2G-3G прыпынена"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Перадача даных 4G прыпынена"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Мабільная перадача даных прыпынена"</string>
@@ -283,7 +282,7 @@
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Яркасць"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Аўтапаварот"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Аўтаматычны паварот экрана"</string>
- <string name="accessibility_quick_settings_rotation_value" msgid="1428962304214992318">"Усталявана на <xliff:g id="ID_1">%s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_rotation_value" msgid="8187398200140760213">"Рэжым <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Паварот заблакіраваны"</string>
<string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"Кніжная арыентацыя"</string>
<string name="quick_settings_rotation_locked_landscape_label" msgid="8553157770061178719">"Альбомная арыентацыя"</string>
@@ -341,7 +340,6 @@
<string name="recents_launch_error_message" msgid="2969287838120550506">"Не атрымалася запусціць <xliff:g id="APP">%s</xliff:g>."</string>
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> адключана ў бяспечным рэжыме."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Ачысціць усё"</string>
- <string name="recents_incompatible_app_message" msgid="5075812958564082451">"Праграма не падтрымлівае функцыю дзялення экрана"</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Перацягніце сюды, каб перайсці ў рэжым падзеленага экрана"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Падзяліць гарызантальна"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Падзяліць вертыкальна"</string>
@@ -367,7 +365,7 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Менш тэрміновыя апавяшчэнні ніжэй"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Дакраніцеся яшчэ раз, каб адкрыць"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Правядзіце пальцам уверх, каб разблакіраваць"</string>
- <string name="do_disclosure_generic" msgid="8498005633306135779">"Гэта прылада знаходзіцца пад кіраваннем"</string>
+ <string name="do_disclosure_generic" msgid="5615898451805157556">"Гэта прылада знаходзіцца пад кіраваннем вашай арганізацыі"</string>
<string name="do_disclosure_with_name" msgid="5640615509915445501">"Гэта прылада знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Тэлефон: правядзіце пальцам ад значка"</string>
<string name="voice_hint" msgid="8939888732119726665">"Галасавая дапамога: правядзіце пальцам ад значка"</string>
@@ -420,13 +418,40 @@
<string name="profile_owned_footer" msgid="8021888108553696069">"За профілем могуць назіраць"</string>
<string name="vpn_footer" msgid="2388611096129106812">"За сеткай могуць назіраць"</string>
<string name="branded_vpn_footer" msgid="2168111859226496230">"За сеткай могуць назіраць"</string>
+ <string name="quick_settings_disclosure_management_monitoring" msgid="6645176135063957394">"Ваша арганізацыя кіруе гэтай прыладай і можа сачыць за сеткавым трафікам"</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="370622174777570853">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> кіруе гэтай прыладай і можа сачыць за сеткавым трафікам"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="1085137869053332307">"Прылада знаходзіцца пад кіраваннем вашай арганізацыі і падключана да праграмы <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="6290456493852584017">"Прылада знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> і падключана да праграмы <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="3294967280853150271">"Прылада знаходзіцца пад кіраваннем вашай арганізацыі"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="1059403025094542908">"Гэта прылада знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="3698767349925266482">"Прылада знаходзіцца пад кіраваннем вашай арганізацыі і падключана да сетак VPN"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="7777821385318891527">"Прылада знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> і падключана да сетак VPN"</string>
+ <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="5125463987558278215">"Ваша арганізацыя можа сачыць за сеткавым трафікам у вашым працоўным профілі"</string>
+ <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8973606847896650284">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> можа сачыць за сеткавым трафікам у вашым працоўным профілі"</string>
+ <string name="quick_settings_disclosure_monitoring" msgid="679658227269205728">"За сеткай могуць сачыць"</string>
+ <string name="quick_settings_disclosure_vpns" msgid="8170318392053156330">"Прылада падключана да сетак VPN"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="3494535754792751741">"Працоўны профіль падключаны да праграмы <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="4467456202486569906">"Асабісты профіль падключаны да праграмы <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="6943724064780847080">"Прылада падключана да праграмы <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7121079311903859610">"Маніторынг прылад"</string>
<string name="monitoring_title_profile_owned" msgid="6790109874733501487">"Маніторынг профіляў"</string>
<string name="monitoring_title" msgid="169206259253048106">"Маніторынг сеткі"</string>
<string name="monitoring_subtitle_vpn" msgid="876537538087857300">"VPN"</string>
- <string name="monitoring_subtitle_network_logging" msgid="5569072711320784030">"Журнал сеткі"</string>
+ <string name="monitoring_subtitle_network_logging" msgid="3341264304793193386">"Журнал сеткі"</string>
+ <string name="monitoring_subtitle_ca_certificate" msgid="3874151893894355988">"Сертыфікаты ЦС"</string>
<string name="disable_vpn" msgid="4435534311510272506">"Адключыць VPN"</string>
<string name="disconnect_vpn" msgid="1324915059568548655">"Адлучыць VPN"</string>
+ <string name="monitoring_button_view_policies" msgid="100913612638514424">"Праглядзець палітыку"</string>
+ <string name="monitoring_description_named_management" msgid="4872859182820011954">"Ваша прылада знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nУ вашага адміністратара ёсць магчымасць маніторынгу і адміністравання налад, карпаратыўнага доступу, праграм, даных, звязаных з гэтай прыладай, і адпаведных геаданых.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара."</string>
+ <string name="monitoring_description_management" msgid="3115563193381106341">"Ваша прылада знаходзіцца пад кіраваннем вашай арганізацыі.\n\nУ вашага адміністратара ёсць магчымасць маніторынгу і адміністравання налад, карпаратыўнага доступу, праграм, даных, звязаных з гэтай прыладай, і адпаведных геаданых.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара."</string>
+ <string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"Ваша арганізацыя ўсталявала на гэтай прыладзе цэнтр сертыфікацыі. Ваш абаронены сеткавы трафік могуць праглядваць ці змяняць."</string>
+ <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"Ваша арганізацыя ўсталявала ў вашым працоўным профілі цэнтр сертыфікацыі. Ваш абаронены сеткавы трафік могуць праглядваць ці змяняць."</string>
+ <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"На гэтай прыладзе ўсталяваны цэнтр сертыфікацыі. Ваш абаронены сеткавы трафік могуць праглядваць ці змяняць."</string>
+ <string name="monitoring_description_management_network_logging" msgid="7184005419733060736">"Ваш адміністратар уключыў вядзенне журнала сеткі, з дапамогай якога адсочваецца трафік на вашай прыладзе."</string>
+ <string name="monitoring_description_named_vpn" msgid="639013857356724268">"Вы падключаны да праграмы <xliff:g id="VPN_APP">%1$s</xliff:g>, якая можа сачыць за вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
+ <string name="monitoring_description_two_named_vpns" msgid="4479748971871539316">"Вы падключаны да праграм <xliff:g id="VPN_APP_0">%1$s</xliff:g> і <xliff:g id="VPN_APP_1">%2$s</xliff:g>, якія могуць сачыць за вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
+ <string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"Ваш працоўны профіль падключаны да праграмы <xliff:g id="VPN_APP">%1$s</xliff:g>, якая можа сачыць за вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
+ <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"Ваш асабісты профіль падключаны да праграмы <xliff:g id="VPN_APP">%1$s</xliff:g>, якая можа сачыць за вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
<string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Ваша прылада знаходзіцца пад кіраваннем <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>."</string>
<string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> выкарыстоўвае <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> для кіравання вашай прыладай."</string>
<string name="monitoring_description_do_body" msgid="3639594537660975895">"Адміністратар кантралюе налады, праграмы, карпаратыўны доступ, звязаныя з прыладай даныя і перадачу геаданых."</string>
@@ -435,15 +460,17 @@
<string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Вы падключаны да праграмы <xliff:g id="VPN_APP">%1$s</xliff:g>, якая можа сачыць за вашай сеткавай дзейнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" ,"</string>
<string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Адкрыйце налады VPN"</string>
+ <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string>
+ <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Адкрыць давераныя ўліковыя даныя"</string>
<string name="monitoring_description_network_logging" msgid="7223505523384076027">"Ваш адміністратар уключыў вядзенне журнала сеткі, з дапамогай якога адсочваецца трафік на вашай прыладзе.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара."</string>
<string name="monitoring_description_vpn" msgid="4445150119515393526">"Вы далі праграме дазвол на наладжванне злучэння VPN.\n\nГэта праграма можа сачыць за актыўнасцю вашай прылады і вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Ваш працоўны профіль знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nВаш адміністратар можа сачыць за вашай сеткавай дзейнасцю, уключаючы электронную пошту, праграмы і вэб-сайты.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара.\n\nВы таксама падключаны да сеткі VPN, якая можа сачыць за вашай сеткавай дзейнасцю."</string>
<string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
- <string name="monitoring_description_app" msgid="6259179342284742878">"Вы падлучаны да праграмы <xliff:g id="APPLICATION">%1$s</xliff:g>, якая можа сачыць за вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
+ <string name="monitoring_description_app" msgid="1828472472674709532">"Вы падключаны да праграмы <xliff:g id="APPLICATION">%1$s</xliff:g>, якая можа сачыць за вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
<string name="monitoring_description_app_personal" msgid="484599052118316268">"Вы падлучаны да праграмы <xliff:g id="APPLICATION">%1$s</xliff:g>, якая сачыць за вашай асабістай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Вы падключаны да праграмы <xliff:g id="APPLICATION">%1$s</xliff:g>, якая можа сачыць за вашай асабістай сеткавай дзейнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
- <string name="monitoring_description_app_work" msgid="7777228449969022305">"Ваш працоўны профіль знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ён падключаны да праграмы <xliff:g id="APPLICATION">%2$s</xliff:g>, якая можа сачыць за вашай сеткавай дзейнасцю, уключаючы электронную пошту, праграмы і вэб-сайты.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара."</string>
- <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Ваш працоўны профіль знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ён падлучаны да праграмы <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, якая можа сачыць за вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты.\n\nВы таксама падлучаны да праграмы <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, якая можа сачыць за вашай асабістай сеткавай актыўнасцю."</string>
+ <string name="monitoring_description_app_work" msgid="4612997849787922906">"Ваш працоўны профіль знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ён падключаны да праграмы <xliff:g id="APPLICATION">%2$s</xliff:g>, якая можа сачыць за вашай працоўнай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара."</string>
+ <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Ваш працоўны профіль знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ён падключаны да праграмы <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, якая можа сачыць за вашай працоўнай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты.\n\nВы таксама падключаны да праграмы <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, якая можа сачыць за вашай асабістай сеткавай актыўнасцю."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Прылада будзе заставацца заблакіраванай, пакуль вы не разблакіруеце яе ўручную"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Атрымлівайце апавяшчэнні хутчэй"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Праглядайце іх перад разблакіроўкай"</string>
@@ -474,10 +501,8 @@
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Дакраніцеся, каб уключыць гук."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Дакраніцеся, каб уключыць вібрацыю. Можа быць адключаны гук службаў спецыяльных магчымасцей."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Дакраніцеся, каб адключыць гук. Можа быць адключаны гук службаў спецыяльных магчымасцей."</string>
- <!-- no translation found for volume_stream_content_description_vibrate_a11y (6427727603978431301) -->
- <skip />
- <!-- no translation found for volume_stream_content_description_mute_a11y (8995013018414535494) -->
- <skip />
+ <string name="volume_stream_content_description_vibrate_a11y" msgid="6427727603978431301">"%1$s. Дакраніцеся, каб уключыць вібрацыю."</string>
+ <string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Дакраніцеся, каб адключыць гук"</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Паказваецца наступная колькасць рэгулятараў гучнасці: %s. Правядзіце пальцам уверх, каб закрыць іх."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Рэгулятары гучнасці схаваны"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Наладка сістэмнага інтэрфейсу карыстальніка"</string>
@@ -528,14 +553,24 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"З дапамогай пашыранага кіравання апавяшчэннямі вы можаце задаваць узровень важнасці апавяшчэнняў праграмы ад 0 да 5. \n\n"<b>"Узровень 5"</b>" \n- Паказваць уверсе спіса апавяшчэнняў \n- Дазваляць перапыняць рэжым поўнага экрана \n- Заўсёды дазваляць кароткі паказ \n\n"<b>"Узровень 4"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Заўсёды дазваляць кароткі паказ \n\n"<b>"Узровень 3"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Ніколі не дазваляць кароткі паказ \n\n"<b>"Узровень 2"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Ніколі не дазваляць кароткі паказ \n- Ніколі не прайграваць гук і не вібрыраваць \n\n"<b>"Узровень 1"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Ніколі не дазваляць кароткі паказ \n- Ніколі не прайграваць гук і не вібрыраваць \n- Хаваць з экрана блакіроўкі і панэлі стану \n- Паказваць унізе спіса апавяшчэнняў \n\n"<b>"Узровень 0"</b>" \n- Блакіраваць усе апавяшчэнні ад праграмы"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Апавяшчэнні"</string>
<string name="notification_channel_disabled" msgid="5805874247999578073">"Вы больш не будзеце атрымліваць гэтыя апавяшчэнні."</string>
- <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
- <item quantity="one">1 з <xliff:g id="NUMBER_1">%d</xliff:g> катэгорыі ў гэтай праграме</item>
- <item quantity="few">1 з <xliff:g id="NUMBER_1">%d</xliff:g> катэгорый у гэтай праграме</item>
- <item quantity="many">1 з <xliff:g id="NUMBER_1">%d</xliff:g> катэгорый у гэтай праграме</item>
- <item quantity="other">1 з <xliff:g id="NUMBER_1">%d</xliff:g> катэгорыі ў гэтай праграме</item>
+ <string name="notification_num_channels" msgid="2048144408999179471">"Катэгорый апавяшчэнняў: <xliff:g id="NUMBER">%d</xliff:g>"</string>
+ <string name="notification_default_channel_desc" msgid="2506053815870808359">"У гэтай праграме няма катэгорый апавяшчэнняў"</string>
+ <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
+ <item quantity="one">1 з <xliff:g id="NUMBER_1">%d</xliff:g> катэгорыі апавяшчэнняў у гэтай праграме</item>
+ <item quantity="few">1 з <xliff:g id="NUMBER_1">%d</xliff:g> катэгорый апавяшчэнняў у гэтай праграме</item>
+ <item quantity="many">1 з <xliff:g id="NUMBER_1">%d</xliff:g> катэгорый апавяшчэнняў у гэтай праграме</item>
+ <item quantity="other">1 з <xliff:g id="NUMBER_1">%d</xliff:g> катэгорыі апавяшчэнняў у гэтай праграме</item>
+ </plurals>
+ <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
+ <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
+ <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> і яшчэ <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
+ <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> і яшчэ <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
+ <item quantity="many"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> і яшчэ <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
+ <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> і яшчэ <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Усе катэгорыі"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Дадатковыя налады"</string>
+ <string name="notification_app_settings" msgid="3743278649182392015">"Персаналізаваць: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Гатова"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"кіраванне апавяшчэннямі"</string>
@@ -543,7 +578,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 хвілін"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 хвілін"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 гадзіна"</string>
- <string name="snooze_option_dont_snooze" msgid="655446566007801922">"Не адкладваць"</string>
+ <string name="snooze_option_dont_snooze" msgid="2252098379349499668">"Скасаваць"</string>
<string name="snooze_undo" msgid="6074877317002985129">"АДРАБІЦЬ"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Адкладзена на <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Выкарыстанне зараду"</string>
@@ -685,6 +720,10 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Разгарнуць"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Згарнуць"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Закрыць"</string>
+ <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Перацягніце ўніз, каб адхіліць"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Меню \"Відарыс у відарысе\""</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> з’яўляецца відарысам у відарысе"</string>
+ <string name="pip_notification_message" msgid="4171698133469539591">"Калі вы не хочаце, каб праграма <xliff:g id="NAME">%s</xliff:g> выкарыстоўвала гэту функцыю, дакраніцеся, каб адкрыць налады і адключыць яе."</string>
<string name="high_temp_title" msgid="4589508026407318374">"Тэлефон награваецца"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Некаторыя функцыі абмежаваны, пакуль тэлефон астывае"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Ваш тэлефон аўтаматычна паспрабуе астыць. Вы можаце па-ранейшаму карыстацца сваім тэлефонам, але ён можа працаваць больш павольна.\n\nПасля таго як ваш тэлефон астыне, ён будзе працаваць у звычайным рэжыме."</string>
@@ -707,9 +746,19 @@
<string name="notification_channel_general" msgid="4525309436693914482">"Агульныя паведамленні"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Захоўванне"</string>
<string name="instant_apps" msgid="6647570248119804907">"Імгненныя праграмы"</string>
- <!-- no translation found for pip_menu_title (3328510504196964712) -->
- <skip />
<string name="instant_apps_message" msgid="8116608994995104836">"Імгненныя праграмы не патрабуюць усталёўкі."</string>
<string name="app_info" msgid="6856026610594615344">"Інфармацыя пра праграму"</string>
<string name="mobile_data" msgid="7094582042819250762">"Маб. перадача даных"</string>
+ <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi выключаны"</string>
+ <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth выключаны"</string>
+ <string name="dnd_is_off" msgid="6167780215212497572">"Рэжым \"Не турбаваць\" выключаны"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
+ <string name="qs_dnd_until" msgid="3469471136280079874">"Да <xliff:g id="ID_1">%s</xliff:g>"</string>
+ <string name="qs_dnd_keep" msgid="1825009164681928736">"Пакінуць"</string>
+ <string name="qs_dnd_replace" msgid="8019520786644276623">"Замяніць"</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings_tv.xml b/packages/SystemUI/res/values-be/strings_tv.xml
index 4b871a6..88635fe 100644
--- a/packages/SystemUI/res/values-be/strings_tv.xml
+++ b/packages/SystemUI/res/values-be/strings_tv.xml
@@ -27,7 +27,4 @@
<string name="pip_onboarding_title" msgid="7850436557670253991">"Відарыс у відарысе"</string>
<string name="pip_onboarding_description" msgid="4028124563309465267">"Гэта дазваляе захоўваць ваша відэа ў полі зроку, пакуль вы не пачняце прайграванне іншага. Націсніце і ўтрымлівайце "<b>"HOME"</b>" для кіравання."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Зразумела"</string>
- <string name="recents_tv_dismiss" msgid="3555093879593377731">"Адхіліць"</string>
- <string-array name="recents_tv_blacklist_array">
- </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 0a5a195..a9bcf11b 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Батерията се зарежда – <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> процента."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Системни настройки."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Известия."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Контейнер за препълване за известията"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Вижте всички известия"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Изчистване на известието."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS е активиран."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS се придобива."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Всички категории"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Още настройки"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Персонализиране: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> от <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"контроли за известията"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Функцията за Wi‑Fi е изключена"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Функцията за Bluetooth е изключена"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Режимът „Не безпокойте“ е изключен"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Режимът „Не безпокойте“ бе включен от автоматично правило (<xliff:g id="ID_1">%s</xliff:g>). Искате ли да запазите текущите настройки?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Режимът „Не безпокойте“ бе включен от приложение (<xliff:g id="ID_1">%s</xliff:g>). Искате ли да запазите текущите настройки?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Режимът „Не безпокойте“ бе включен от автоматично правило или от приложение. Искате ли да запазите текущите настройки?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"До <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Запазване"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Замяна"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 8c82509..c0f6f51 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -164,7 +164,8 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ব্যাটারি চার্জ হচ্ছে, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> শতাংশ৷"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"সিস্টেম সেটিংস৷"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"বিজ্ঞপ্তিগুলি৷"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"বিজ্ঞপ্তি ওভারফ্লো কন্টেনার"</string>
+ <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
+ <skip />
<string name="accessibility_remove_notification" msgid="3603099514902182350">"বিজ্ঞপ্তি সাফ করুন৷"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS সক্ষম করা হয়েছে৷"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS অর্জন করা হচ্ছে৷"</string>
@@ -560,8 +561,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"সকল বিভাগ"</string>
<string name="notification_more_settings" msgid="816306283396553571">"আরো সেটিংস"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"কাস্টমাইজ করুন: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"সম্পন্ন"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"বিজ্ঞপ্তির নিয়ন্ত্রণগুলি"</string>
@@ -743,9 +743,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"ওয়াই ফাই বন্ধ আছে"</string>
<string name="bt_is_off" msgid="2640685272289706392">"ব্লুটুথ বন্ধ আছে"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"বিরক্ত করবেন না বিকল্পটি বন্ধ আছে"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"বিরক্ত করবেন না বিকল্পটি একটি স্বয়ংক্রিয় নিয়ম (<xliff:g id="ID_1">%s</xliff:g>) এর দ্বারা চালু করা হয়েছে। বর্তমান সেটিংস রাখতে চান?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"বিরক্ত করবেন না বিকল্পটি একটি অ্যাপ (<xliff:g id="ID_1">%s</xliff:g>) এর দ্বারা চালু করা হয়েছে। বর্তমান সেটিংস রাখতে চান?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"বিরক্ত করবেন না বিকল্পটি একটি স্বয়ংক্রিয় নিয়ম বা অ্যাপের দ্বারা চালু করা হয়েছে। বর্তমান সেটিংস রাখতে চান?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> পর্যন্ত"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"রাখুন"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"বদলে দিন"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 27390b9..2ea22ec 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -76,7 +76,7 @@
<string name="screenshot_failed_title" msgid="705781116746922771">"Došlo je do greške prilikom snimanja ekrana."</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Došlo je do problema prilikom spašavanja snimka ekrana."</string>
<string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snimak ekrana se ne može sačuvati zbog manjka prostora za pohranu."</string>
- <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikacija ili vaša organizacija ne dopuštaju pravljenje snimaka ekrana."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Ova aplikacija ili vaša organizacija ne dozvoljavaju snimanje ekrana"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prijenosa fajlova"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Reproduciranje medijskih sadržaja (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"Priključiti kao kameru (PTP)"</string>
@@ -91,7 +91,7 @@
<string name="accessibility_phone_button" msgid="6738112589538563574">"Telefon"</string>
<string name="accessibility_voice_assist_button" msgid="487611083884852965">"Glasovna pomoć"</string>
<string name="accessibility_unlock_button" msgid="128158454631118828">"Otključaj"</string>
- <string name="accessibility_unlock_button_fingerprint" msgid="8214125623493923751">"Dugme za otključavanje, čeka se na otisak prsta"</string>
+ <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"Čeka se otisak prsta"</string>
<string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"Otključaj bez korištenja otiska prsta"</string>
<string name="unlock_label" msgid="8779712358041029439">"otključaj"</string>
<string name="phone_label" msgid="2320074140205331708">"otvori telefon"</string>
@@ -165,7 +165,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Punjenje baterije, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procenata."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Postavke sistema."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Obavještenja."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Spremnik za prelijevanje obavještenja"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Vidite sva obavještenja"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Ukloniti obavještenje."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS omogućen."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Uspostavljanje GPS veze."</string>
@@ -237,13 +237,12 @@
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Ušteda podataka je isključena."</string>
<string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Ušteda podataka je uključena."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Osvjetljenje ekrana"</string>
- <!-- no translation found for accessibility_ambient_display_charging (9084521679384069087) -->
- <skip />
+ <string name="accessibility_ambient_display_charging" msgid="9084521679384069087">"Punjenje"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G prijenos podataka je pauzirano"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G prijenos podataka je pauzirano"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="4651001290947318931">"Mobilni podaci su pauzirani"</string>
<string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Prijenos podataka je pauziran"</string>
- <string name="data_usage_disabled_dialog" msgid="1841738975235283398">"Dostigli ste ograničenje za prijenos podataka koje ste postavili. Više ne koristite mobilne podatke.\n\nUkoliko nastavite koristiti mobilne podatke, mogući su troškovi za prijenos podataka."</string>
+ <string name="data_usage_disabled_dialog" msgid="1841738975235283398">"Dostigli ste ograničenje za prijenos podataka koje ste postavili. Više ne koristite mobilne podatke.\n\nUkoliko nastavite koristiti mobilne podatke, mogu nastati troškovi prijenosa podataka."</string>
<string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Nastavi"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Niste povezani na internet"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi veza aktivna"</string>
@@ -279,7 +278,7 @@
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Osvjetljenje"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatsko rotiranje"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"Automatsko rotiranje ekrana"</string>
- <string name="accessibility_quick_settings_rotation_value" msgid="1428962304214992318">"Postaviti način rada: <xliff:g id="ID_1">%s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_rotation_value" msgid="8187398200140760213">"Način rada <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotiranje je zaključano"</string>
<string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"Uspravno"</string>
<string name="quick_settings_rotation_locked_landscape_label" msgid="8553157770061178719">"Vodoravno"</string>
@@ -337,7 +336,6 @@
<string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacija <xliff:g id="APP">%s</xliff:g> nije pokrenuta."</string>
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> je onemogućena u sigurnom načinu rada."</string>
<string name="recents_stack_action_button_label" msgid="6593727103310426253">"Obriši sve"</string>
- <string name="recents_incompatible_app_message" msgid="5075812958564082451">"Aplikacija ne podržava dijeljenje ekrana."</string>
<string name="recents_drag_hint_message" msgid="2649739267073203985">"Povucite ovdje za korištenje podijeljenog ekrana"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podjela po horizontali"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podjela po vertikali"</string>
@@ -363,7 +361,7 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Prikaži manje važna obavještenja ispod"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Dodirnite ponovo da otvorite"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Prevucite prema gore da otključate"</string>
- <string name="do_disclosure_generic" msgid="8498005633306135779">"Ovim uređajem upravlja"</string>
+ <string name="do_disclosure_generic" msgid="5615898451805157556">"Ovim uređajem upravlja vaša organizacija"</string>
<string name="do_disclosure_with_name" msgid="5640615509915445501">"Ovim uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
<string name="phone_hint" msgid="4872890986869209950">"Prevucite preko ikone da otvorite telefon"</string>
<string name="voice_hint" msgid="8939888732119726665">"Prevucite preko ikone za glasovnu pomoć"</string>
@@ -416,13 +414,40 @@
<string name="profile_owned_footer" msgid="8021888108553696069">"Profil može biti nadziran"</string>
<string name="vpn_footer" msgid="2388611096129106812">"Mreža može biti nadzirana"</string>
<string name="branded_vpn_footer" msgid="2168111859226496230">"Mreža može biti nadzirana"</string>
+ <string name="quick_settings_disclosure_management_monitoring" msgid="6645176135063957394">"Vaša organizacija upravlja ovim uređajem i može pratiti mrežni promet."</string>
+ <string name="quick_settings_disclosure_named_management_monitoring" msgid="370622174777570853">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> upravlja ovim uređajem i može pratiti vaš mrežni promet"</string>
+ <string name="quick_settings_disclosure_management_named_vpn" msgid="1085137869053332307">"Uređajem upravlja vaša organizacija i povezan je s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_management_named_vpn" msgid="6290456493852584017">"Uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i povezan je s aplikacijom <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_management" msgid="3294967280853150271">"Uređajem upravlja vaša organizacija"</string>
+ <string name="quick_settings_disclosure_named_management" msgid="1059403025094542908">"Ovim uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>."</string>
+ <string name="quick_settings_disclosure_management_vpns" msgid="3698767349925266482">"Uređajem upravlja vaša organizacija i povezan je s VPN-ovima"</string>
+ <string name="quick_settings_disclosure_named_management_vpns" msgid="7777821385318891527">"Uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> i povezan je s VPN-ovima"</string>
+ <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="5125463987558278215">"Vaša organizacija može pratiti mrežni promet na vašem profilu."</string>
+ <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8973606847896650284">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> može pratiti mrežni promet na vašem radnom profilu"</string>
+ <string name="quick_settings_disclosure_monitoring" msgid="679658227269205728">"Mreža može biti nadzirana"</string>
+ <string name="quick_settings_disclosure_vpns" msgid="8170318392053156330">"Uređaj je povezan s VPN-ovima"</string>
+ <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="3494535754792751741">"Radni profil je povezan s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="4467456202486569906">"Lični profil je povezan s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
+ <string name="quick_settings_disclosure_named_vpn" msgid="6943724064780847080">"Uređaj je povezan s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
<string name="monitoring_title_device_owned" msgid="7121079311903859610">"Praćenje uređaja"</string>
<string name="monitoring_title_profile_owned" msgid="6790109874733501487">"Praćenje profila"</string>
<string name="monitoring_title" msgid="169206259253048106">"Praćenje mreže"</string>
<string name="monitoring_subtitle_vpn" msgid="876537538087857300">"VPN mreža"</string>
- <string name="monitoring_subtitle_network_logging" msgid="5569072711320784030">"Zapisivanje na mreži"</string>
+ <string name="monitoring_subtitle_network_logging" msgid="3341264304793193386">"Zapisivanje na mreži"</string>
+ <string name="monitoring_subtitle_ca_certificate" msgid="3874151893894355988">"CA certifikati"</string>
<string name="disable_vpn" msgid="4435534311510272506">"Isključi VPN"</string>
<string name="disconnect_vpn" msgid="1324915059568548655">"Prekini VPN vezu"</string>
+ <string name="monitoring_button_view_policies" msgid="100913612638514424">"Prikaži pravila"</string>
+ <string name="monitoring_description_named_management" msgid="4872859182820011954">"Vašim uređajem upravlja <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nVaš administrator može pratiti i upravljati postavkama, korporativnim pristupom, aplikacijama, podacima povezanim s vašim uređajem i informacijama o lokaciji vašeg uređaja.\n\nZa više informacija, obratite se svom administratoru.\""</string>
+ <string name="monitoring_description_management" msgid="3115563193381106341">"Vašim uređajem upravlja vaša organizacija.\n\nVaš administrator može pratiti i upravljati postavkama, korporativnim pristupom, aplikacijama, podacima povezanim s vašim uređajem i informacijama o lokaciji vašeg uređaja.\n\nZa više informacija, obratite se svom administratoru.\""</string>
+ <string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"Vaša organizacija je instalirala CA certifikat na ovom uređaju. Vaš promet preko sigurne mreže može se pratiti."</string>
+ <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"Vaša organizacija je instalirala CA certifikat na vašem radnom profilu. Vaš promet preko sigurne mreže može se pratiti."</string>
+ <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"CA certifikat je instaliran na ovom uređaju. Vaš promet preko sigurne mreže može se pratiti."</string>
+ <string name="monitoring_description_management_network_logging" msgid="7184005419733060736">"Vaš administrator je uključio zapisivanje na mreži, čime se prati promet na vašem uređaju."</string>
+ <string name="monitoring_description_named_vpn" msgid="639013857356724268">"Povezani ste s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može pratiti vašu aktivnost na mreži, uključujući e-poruke i web lokacije."</string>
+ <string name="monitoring_description_two_named_vpns" msgid="4479748971871539316">"Povezani ste s aplikacijama <xliff:g id="VPN_APP_0">%1$s</xliff:g> i <xliff:g id="VPN_APP_1">%2$s</xliff:g>, koje mogu pratiti vašu aktivnost na mreži, uključujući e-poruke, aplikacije i web lokacije."</string>
+ <string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"Vaš radni profil je povezan s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može pratiti vašu aktivnost na mreži, uključujući e-poruke i web lokacije."</string>
+ <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"Vaš lični profil je povezan s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može pratiti vašu aktivnost na mreži, uključujući e-poruke, aplikacije i web lokacije."</string>
<string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Vašim uređajem upravlja aplikacija <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>."</string>
<string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> koristi aplikaciju <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> za upravljanje vašim uređajem."</string>
<string name="monitoring_description_do_body" msgid="3639594537660975895">"Vaš administrator može pratiti postavke, korporativni pristup, aplikacije, podatke povezane s vašim uređajem i informacije o lokaciji vašeg uređaja."</string>
@@ -431,15 +456,17 @@
<string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Povezani ste s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može pratiti vašu aktivnost na mreži, uključujući e-poruke i web lokacije."</string>
<string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
<string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Postavke otvorene VPN mreže"</string>
+ <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string>
+ <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Otvorite pouzdane akreditive"</string>
<string name="monitoring_description_network_logging" msgid="7223505523384076027">"Vaš administrator je uključio zapisivanje na mreži, čime se prati saobraćaj na vašem uređaju.\n\nZa više informacija, obratite se administratoru."</string>
<string name="monitoring_description_vpn" msgid="4445150119515393526">"Jednoj aplikaciji ste dali odobrenje da uspostavi VPN vezu.\n\nTa aplikacija može pratiti vašu aktivnost na uređaju i mreži, uključujući e-poštu, aplikacije i web-lokacije."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Vašim radnim profilom upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nVaš administrator može pratiti vašu aktivnost na radnoj mreži, uključujući e-poruke, aplikacije i web lokacije.\n\nZa više informacija, obratite se administratoru.\n\nPovezani ste i na VPN, koji može pratiti vašu aktivnost na mreži."</string>
<string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
- <string name="monitoring_description_app" msgid="6259179342284742878">"Povezani ste sa aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može pratiti vašu aktivnost na mreži, uključujući e-mailove, aplikacije i web-lokacije."</string>
+ <string name="monitoring_description_app" msgid="1828472472674709532">"Povezani ste s aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može pratiti vašu aktivnost na mreži, uključujući e-poruke, aplikacije i web lokacije."</string>
<string name="monitoring_description_app_personal" msgid="484599052118316268">"Povezani ste sa aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može pratiti vašu aktivnost na privatnoj mreži, uključujući e-mailove, aplikacije i web-lokacije."</string>
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Povezani ste na aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može pratiti vaše privatne aktivnosti na mreži, uključujući e-poštu, aplikacije i web stranice."</string>
- <string name="monitoring_description_app_work" msgid="7777228449969022305">"Vašim radnim profilom upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Povezan je s aplikacijom <xliff:g id="APPLICATION">%2$s</xliff:g>, koja može pratiti vašu aktivnost na radnoj mreži, uključujući e-poruke, aplikacije i web lokacije.\n\nZa više informacija, obratite se svom administratoru."</string>
- <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Profilom za posao upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Povezan je sa aplikacijom <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, koja može pratiti vašu aktivnost na radnoj mreži, uključujući e-poštu, aplikacije i web-lokacije.\n\nPovezani ste i sa aplikacijom <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, koja može pratiti vašu aktivnost na privatnoj mreži."</string>
+ <string name="monitoring_description_app_work" msgid="4612997849787922906">"Vašim radnim profilom upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil je povezan s aplikacijom <xliff:g id="APPLICATION">%2$s</xliff:g>, koja može pratiti vašu aktivnost na radnoj mreži, uključujući e-poruke, aplikacije i web lokacije.\n\nZa više informacija, obratite se svom administratoru."</string>
+ <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Radnim profilom upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil je povezan s aplikacijom <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, koja može pratiti vašu aktivnost na radnoj mreži, uključujući e-poruke, aplikacije i web lokacije.\n\nPovezani ste i sa aplikacijom <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, koja može pratiti vašu aktivnost na privatnoj mreži."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Uređaj će ostati zaključan dok ga ručno ne otključate"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Brže primaj obavještenja"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Vidi ih prije otključavanja"</string>
@@ -472,10 +499,8 @@
<skip />
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Dodirnite za postavljanje vibracije. Zvukovi usluga pristupačnosti mogu biti isključeni."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Dodirnite da isključite zvuk. Zvukovi usluga pristupačnosti mogu biti isključeni."</string>
- <!-- no translation found for volume_stream_content_description_vibrate_a11y (6427727603978431301) -->
- <skip />
- <!-- no translation found for volume_stream_content_description_mute_a11y (8995013018414535494) -->
- <skip />
+ <string name="volume_stream_content_description_vibrate_a11y" msgid="6427727603978431301">"%1$s. Dodirnite da postavite vibraciju."</string>
+ <string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s. Dodirnite da isključite zvuk."</string>
<string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"Prikazane kontrole jačine zvuka za: %s. Prevucite prema gore za odbacivanje."</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"Kontrole jačine zvuka sakrivene"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Podešavač za korisničko sučelje sistema"</string>
@@ -526,13 +551,22 @@
<string name="power_notification_controls_description" msgid="4372459941671353358">"Uz kontrolu obavještenja o napajanju, možete postaviti nivo značaja obavještenja iz aplikacije, i to od nivoa 0 do 5. \n\n"<b>"Nivo 5"</b>" \n- Prikaži na vrhu liste obavještenja \n- Dopusti prekid prikaza cijelog ekrana \n- Uvijek izviruj \n\n"<b>"Nvio 4"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Uvijek izviruj \n\n"<b>"Nivo 3"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikad ne izviruj \n\n"<b>"Nivo 2"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikad ne izviruj \n- Nikada ne puštaj zvuk ili vibraciju \n\n"<b>"Nivo 1"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikada ne izviruj \n- Nikada ne puštaj zvuk ili vibraciju \n- Sakrij sa ekrana za zaključavanje i statusne trake \n- Prikaži na dnu liste obavještenja \n\n"<b>"Nivo 0"</b>" \n- Blokiraj sva obavještenja iz aplikacije"</string>
<string name="notification_header_default_channel" msgid="7506845022070889909">"Obavještenja"</string>
<string name="notification_channel_disabled" msgid="5805874247999578073">"Nećete više primati ova obavještenja."</string>
- <plurals name="notification_num_channels_desc" formatted="false" msgid="8808748716499517938">
- <item quantity="one">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije iz ove aplikacije</item>
- <item quantity="few">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije iz ove aplikacije</item>
- <item quantity="other">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorija iz ove aplikacije</item>
+ <string name="notification_num_channels" msgid="2048144408999179471">"Kategorije obavještenja: <xliff:g id="NUMBER">%d</xliff:g>"</string>
+ <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ova aplikacija nema kategorije obavještenja"</string>
+ <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
+ <item quantity="one">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije obavještenja iz ove aplikacije</item>
+ <item quantity="few">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorije obavještenja iz ove aplikacije</item>
+ <item quantity="other">1 od <xliff:g id="NUMBER_1">%d</xliff:g> kategorija obavještenja iz ove aplikacije</item>
+ </plurals>
+ <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
+ <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
+ <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, i još <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
+ <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, i još <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
+ <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, i još <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Sve kategorije"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Više postavki"</string>
+ <string name="notification_app_settings" msgid="3743278649182392015">"Prilagodite: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"kontrole obavještenja"</string>
@@ -540,7 +574,7 @@
<string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuta"</string>
<string name="snooze_option_30_min" msgid="867081342535195788">"30 minuta"</string>
<string name="snooze_option_1_hour" msgid="1098086401880077154">"1 sat"</string>
- <string name="snooze_option_dont_snooze" msgid="655446566007801922">"Ne odgađaj"</string>
+ <string name="snooze_option_dont_snooze" msgid="2252098379349499668">"Otkaži"</string>
<string name="snooze_undo" msgid="6074877317002985129">"OPOZOVI"</string>
<string name="snoozed_for_time" msgid="2390718332980204462">"Odgođeno za <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Upotreba baterije"</string>
@@ -682,6 +716,10 @@
<string name="pip_phone_expand" msgid="5889780005575693909">"Proširi"</string>
<string name="pip_phone_minimize" msgid="1079119422589131792">"Umanji"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Zatvori"</string>
+ <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Povucite prema dolje da odbacite"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Meni za način rada Slika u slici"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> je u načinu priakza Slika u slici"</string>
+ <string name="pip_notification_message" msgid="4171698133469539591">"Ako ne želite da <xliff:g id="NAME">%s</xliff:g> koristi ovu funkciju, dodirnite da otvorite postavke i isključite je."</string>
<string name="high_temp_title" msgid="4589508026407318374">"Telefon se pregrijava"</string>
<string name="high_temp_notif_message" msgid="5642466103153429279">"Neke funkcije su ograničene dok se telefon hladi"</string>
<string name="high_temp_dialog_message" msgid="6840700639374113553">"Vaš telefon će se automatski pokušati ohladiti. I dalje možete koristi telefon, ali će možda raditi sporije.\n\nNakon što se ohladi, telefon će normalno raditi."</string>
@@ -704,9 +742,19 @@
<string name="notification_channel_general" msgid="4525309436693914482">"Općenite poruke"</string>
<string name="notification_channel_storage" msgid="3077205683020695313">"Pohrana"</string>
<string name="instant_apps" msgid="6647570248119804907">"Instant-aplikacije"</string>
- <!-- no translation found for pip_menu_title (3328510504196964712) -->
- <skip />
<string name="instant_apps_message" msgid="8116608994995104836">"Za instant aplikacije nije potrebna instalacija"</string>
<string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
<string name="mobile_data" msgid="7094582042819250762">"Mobilni podaci"</string>
+ <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi veza je isključena"</string>
+ <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je isključen"</string>
+ <string name="dnd_is_off" msgid="6167780215212497572">"Opcija Ne ometaj je isključena"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
+ <string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
+ <string name="qs_dnd_keep" msgid="1825009164681928736">"Zadrži"</string>
+ <string name="qs_dnd_replace" msgid="8019520786644276623">"Zamijeni"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings_tv.xml b/packages/SystemUI/res/values-bs/strings_tv.xml
index 40347dc..20b5bd6 100644
--- a/packages/SystemUI/res/values-bs/strings_tv.xml
+++ b/packages/SystemUI/res/values-bs/strings_tv.xml
@@ -27,7 +27,4 @@
<string name="pip_onboarding_title" msgid="7850436557670253991">"Slika u slici"</string>
<string name="pip_onboarding_description" msgid="4028124563309465267">"Ovim videozapis ostaje prikazan sve dok pokrenete sljedeći. Pritisnite i držite "<b>" POČETAK "</b>" za kontrole PIP-a."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Jasno mi je"</string>
- <string name="recents_tv_dismiss" msgid="3555093879593377731">"Odbaci"</string>
- <string-array name="recents_tv_blacklist_array">
- </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index af531a2..1b211d2 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"La bateria s\'està carregant, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Configuració del sistema."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificacions."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Contenidor de notificacions addicional"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Mostra totes les notificacions"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Esborra la notificació."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS activat."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"S\'està adquirint el GPS."</string>
@@ -466,7 +466,7 @@
<string name="monitoring_description_app_work" msgid="4612997849787922906">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> gestiona el teu perfil professional. El perfil està connectat a <xliff:g id="APPLICATION">%2$s</xliff:g>, que pot supervisar la teva activitat a la xarxa de treball, com ara els correus electrònics, les aplicacions i els llocs web.\n\nPer obtenir més informació, contacta amb l\'administrador."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> gestiona el teu perfil professional. El perfil està connectat a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que pot supervisar la teva activitat a la xarxa de treball, com ara els correus electrònics, les aplicacions i els llocs web.\n\nTambé estàs connectat a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que pot supervisar la teva activitat personal a la xarxa."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"El dispositiu continuarà bloquejat fins que no el desbloquegis manualment."</string>
- <string name="hidden_notifications_title" msgid="7139628534207443290">"Obtén notificacions més ràpidament"</string>
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Rep notificacions més ràpidament"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Mostra-les abans de desbloquejar"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"No"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Configura"</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Totes les categories"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Més opcions"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Personalitza: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Fet"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"controls de notificació"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"La Wi-Fi està desactivada"</string>
<string name="bt_is_off" msgid="2640685272289706392">"El Bluetooth està desactivat"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"El mode No molestis està desactivat"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Una regla automàtica (<xliff:g id="ID_1">%s</xliff:g>) ha activat el mode No molestis. Vols conservar la configuració actual?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Una aplicació (<xliff:g id="ID_1">%s</xliff:g>) ha activat el mode No molestis. Vols conservar la configuració actual?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Una regla automàtica o una aplicació han activat el mode No molestis. Vols conservar la configuració actual?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Fins a les <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Conserva"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Substitueix"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index a0f4a01b..68cb7e8 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -168,7 +168,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Systémová nastavení."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Oznámení."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Kontejner pro ikonu přetečení s oznámením"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Zobrazit všechna oznámení"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Vymazat oznámení."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS je povoleno."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Zaměřování GPS."</string>
@@ -570,8 +570,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Všechny kategorie"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Další nastavení"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Přizpůsobit: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Hotovo"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"Nastavení oznámení"</string>
@@ -753,9 +752,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je vypnuta"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je vypnuto"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Režim Nerušit je vypnut"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Režim Nerušit byl zapnut automatickým pravidlem (<xliff:g id="ID_1">%s</xliff:g>). Ponechat aktuální nastavení?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Režim Nerušit byl zapnut aplikací (<xliff:g id="ID_1">%s</xliff:g>). Ponechat aktuální nastavení?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Režim Nerušit byl zapnut automatickým pravidlem nebo aplikací. Ponechat aktuální nastavení?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Zachovat"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Nahradit"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 7c8de39..e304b54 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Batteriet oplades. <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procent."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Systemindstillinger."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Underretninger."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Overløbsbeholder for underretninger"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Se alle underretninger"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Ryd underretning."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS aktiveret."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS samler data."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Alle kategorier"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Flere indstillinger"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Tilpas: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Udfør"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"kontrolelementer til underretninger"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi er slået fra"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth er slået fra"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Forstyr ikke er slået fra"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Forstyr ikke blev aktiveret af en automatisk regel (<xliff:g id="ID_1">%s</xliff:g>). Vil du beholde de nuværende indstillinger?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Forstyr ikke blev aktiveret af en app (<xliff:g id="ID_1">%s</xliff:g>). Vil du beholde de nuværende indstillinger?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Forstyr ikke blev aktiveret af en automatisk regel eller en app. Vil du beholde de nuværende indstillinger?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Indtil <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Behold"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Erstat"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 25e68bb..9780181 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -166,7 +166,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Systemeinstellungen"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Benachrichtigungen"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Überlaufcontainer für Benachrichtigungen"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Alle Benachrichtigungen ansehen"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Benachrichtigung löschen"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS aktiviert"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS-Signal abrufen"</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Alle Kategorien"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Weitere Einstellungen"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Anpassen: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Fertig"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> – <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"Benachrichtigungseinstellungen"</string>
@@ -745,9 +744,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"WLAN ist deaktiviert"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ist deaktiviert"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"\"Nicht stören\" ist deaktiviert"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"\"Nicht stören\" wurde von einer automatischen Regel aktiviert (<xliff:g id="ID_1">%s</xliff:g>). Aktuelle Einstellungen beibehalten?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"\"Nicht stören\" wurde von einer App aktiviert (<xliff:g id="ID_1">%s</xliff:g>). Aktuelle Einstellungen beibehalten?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"\"Nicht stören\" wurde von einer automatischen Regel oder einer App aktiviert. Aktuelle Einstellungen beibehalten?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Bis <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Beibehalten"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Ersetzen"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index e36b22d..710c455 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Φόρτιση μπαταρίας, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> τοις εκατό."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Ρυθμίσεις συστήματος."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Ειδοποιήσεις."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Κοντέινερ υπερχείλισης ειδοποίησης"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Δείτε όλες τις ειδοποιήσεις"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Διαγραφή ειδοποίησης."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"Το GPS ενεργοποιήθηκε."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Προσδιορισμός GPS."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Όλες οι κατηγορίες"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Περισσότερες ρυθμίσεις"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Προσαρμογή: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Τέλος"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"στοιχεία ελέγχου ειδοποιήσεων"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Το Wi-Fi είναι ανενεργό"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Το Bluetooth είναι ανενεργό"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Η λειτουργία \"Μην ενοχλείτε\" είναι ανενεργή"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Η λειτουργία \"Μην ενοχλείτε\" ενεργοποιήθηκε από έναν αυτόματο κανόνα (<xliff:g id="ID_1">%s</xliff:g>). Διατήρηση τρεχουσών ρυθμίσεων;"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Η λειτουργία \"Μην ενοχλείτε\" ενεργοποιήθηκε από μια εφαρμογή (<xliff:g id="ID_1">%s</xliff:g>). Διατήρηση τρεχουσών ρυθμίσεων;"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Η λειτουργία \"Μην ενοχλείτε\" ενεργοποιήθηκε από έναν αυτόματο κανόνα ή μια εφαρμογή. Διατήρηση τρεχουσών ρυθμίσεων;"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Έως τις <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Διατήρηση"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Αντικατάσταση"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 462a6e3..723be15 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Battery charging, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> percent."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"System settings"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifications."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Notification overflow container"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"See all notifications"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Clear notification."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS enabled."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS acquiring."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"All Categories"</string>
<string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Customise: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Done"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"notification controls"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is off"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Do Not Disturb is off"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Do Not Disturb was turned on by an automatic rule (<xliff:g id="ID_1">%s</xliff:g>). Keep current settings?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Do Not Disturb was turned on by an app (<xliff:g id="ID_1">%s</xliff:g>). Keep current settings?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Do Not Disturb was turned on by an automatic rule or app. Keep current settings?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Until <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Keep"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Replace"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 462a6e3..723be15 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Battery charging, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> percent."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"System settings"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifications."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Notification overflow container"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"See all notifications"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Clear notification."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS enabled."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS acquiring."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"All Categories"</string>
<string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Customise: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Done"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"notification controls"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is off"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Do Not Disturb is off"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Do Not Disturb was turned on by an automatic rule (<xliff:g id="ID_1">%s</xliff:g>). Keep current settings?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Do Not Disturb was turned on by an app (<xliff:g id="ID_1">%s</xliff:g>). Keep current settings?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Do Not Disturb was turned on by an automatic rule or app. Keep current settings?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Until <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Keep"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Replace"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 462a6e3..723be15 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Battery charging, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> percent."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"System settings"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifications."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Notification overflow container"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"See all notifications"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Clear notification."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS enabled."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS acquiring."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"All Categories"</string>
<string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Customise: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Done"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"notification controls"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is off"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Do Not Disturb is off"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Do Not Disturb was turned on by an automatic rule (<xliff:g id="ID_1">%s</xliff:g>). Keep current settings?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Do Not Disturb was turned on by an app (<xliff:g id="ID_1">%s</xliff:g>). Keep current settings?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Do Not Disturb was turned on by an automatic rule or app. Keep current settings?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Until <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Keep"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Replace"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 18fedb1..16e2549 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -166,7 +166,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Configuración del sistema"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificaciones"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Contenedor del flujo de notificaciones"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Ver todas las notificaciones"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Eliminar notificación"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS habilitado"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Adquisición de GPS"</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Todas las categorías"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Más opciones de configuración"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Personalizar: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Listo"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"controles de notificación"</string>
@@ -744,11 +743,14 @@
<string name="mobile_data" msgid="7094582042819250762">"Datos móviles"</string>
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desactivado"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desactivado"</string>
- <string name="dnd_is_off" msgid="6167780215212497572">"No molestar desactivado"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Una regla automática activó No molestar (<xliff:g id="ID_1">%s</xliff:g>). ¿Deseas mantener la configuración actual?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Una app (<xliff:g id="ID_1">%s</xliff:g>) activó No molestar. ¿Deseas mantener la configuración actual?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Una app o regla automática activó No molestar. ¿Deseas mantener la configuración actual?"</string>
- <string name="qs_dnd_until" msgid="3469471136280079874">"Hasta las <xliff:g id="ID_1">%s</xliff:g>"</string>
+ <string name="dnd_is_off" msgid="6167780215212497572">"No interrumpir desactivado"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
+ <string name="qs_dnd_until" msgid="3469471136280079874">"Hasta la(s) <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Mantener"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Reemplazar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 0a72eac..2c21bae 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -166,7 +166,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Ajustes del sistema"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificaciones"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Contenedor adicional de notificaciones"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Ver todas las notificaciones"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Borrar notificación"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS habilitado"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Obteniendo ubicación..."</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Todas las categorías"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Más ajustes"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Personalizar: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Listo"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"Controles de las notificaciones"</string>
@@ -745,9 +744,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desactivado"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desactivado"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"No molestar está desactivado"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Una regla automática (<xliff:g id="ID_1">%s</xliff:g>) ha activado No molestar. ¿Quieres conservar esta configuración?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Una aplicación (<xliff:g id="ID_1">%s</xliff:g>) ha activado No molestar. ¿Quieres conservar esta configuración?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Una aplicación o una regla automática han activado No molestar. ¿Quieres conservar esta configuración?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Hasta <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Conservar"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Reemplazar"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index b29af77..fbe6dfc 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -166,7 +166,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Süsteemiseaded"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Märguanded"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Märguande ületäite konteiner"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Kõikide märguannete kuvamine"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Märguande eemaldamine."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS on lubatud."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS-signaali otsimine."</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Kõik kategooriad"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Rohkem seadeid"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Kohandamine: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Valmis"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"märguannete juhtnupud"</string>
@@ -745,9 +744,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"WiFi on välja lülitatud"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth on välja lülitatud"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Funktsioon Mitte segada on välja lülitatud"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Automaatne reegel lülitas funktsiooni Mitte segada sisse (<xliff:g id="ID_1">%s</xliff:g>). Kas jätta praegused seaded aktiivseks?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Rakendus lülitas funktsiooni Mitte segada sisse (<xliff:g id="ID_1">%s</xliff:g>). Kas jätta praegused seaded aktiivseks?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Automaatne reegel või rakendus lülitas funktsiooni Mitte segada sisse. Kas jätta praegused seaded aktiivseks?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Kuni ajani <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Säilita"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Asenda"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 105079d..c802e8a 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -166,7 +166,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Sistemaren ezarpenak."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Jakinarazpenak."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Gehiegizko jakinarazpenen edukitzailea"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Ikusi jakinarazpen guztiak"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Garbitu jakinarazpena."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS aktibatuta."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS seinalea lortzen."</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Kategoria guztiak"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Ezarpen gehiago"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Pertsonalizatu: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Eginda"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"jakinarazpena kontrolatzeko aukerak"</string>
@@ -745,9 +744,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi konexioa desaktibatuta dago"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth konexioa desaktibatuta dago"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"\"Ez molestatu\" modua desaktibatuta dago"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"\"Ez molestatu\" modua aktibatu du arau automatiko batek (<xliff:g id="ID_1">%s</xliff:g>). Uneko ezarpenak mantendu nahi dituzu?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"\"Ez molestatu\" modua aktibatu du aplikazio batek (<xliff:g id="ID_1">%s</xliff:g>). Uneko ezarpenak mantendu nahi dituzu?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"\"Ez molestatu\" modua aktibatu du arau automatiko edo aplikazio batek. Uneko ezarpenak mantendu nahi dituzu?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> arte"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Utzi bere horretan"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Ordeztu"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 35e2a0c..9c35ddc 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"در حال شارژ باتری، <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> درصد"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"تنظیمات سیستم."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"اعلانها."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"محتوی سرریز اعلان"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"دیدن همه اعلانها"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"پاک کردن اعلان"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS فعال شد."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"دستیابی به GPS."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"همه دستهها"</string>
<string name="notification_more_settings" msgid="816306283396553571">"تنظیمات بیشتر"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"سفارشی کردن: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"تمام"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"کنترلهای اعلان"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi خاموش است"</string>
<string name="bt_is_off" msgid="2640685272289706392">"بلوتوث خاموش است"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"«مزاحم نشوید» خاموش است"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"قانون خودکاری (<xliff:g id="ID_1">%s</xliff:g>) حالت «مزاحم نشوید» را روشن کرده است. تنظیمات کنونی حفظ شود؟"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"برنامهای (<xliff:g id="ID_1">%s</xliff:g>) حالت «مزاحم نشوید» را روشن کرده است. تنظیمات کنونی حفظ شود؟"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"قانون خودکار یا برنامهای حالت «مزاحم نشوید» را روشن کرده است. تنظیمات کنونی حفظ شود؟"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"تا <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"حفظ شود"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"جایگزین کردن"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index ca55556..a949b8b 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Akku latautuu: <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> prosenttia"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Järjestelmän asetukset"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Ilmoitukset"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Ilmoitusten ylivuototila"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Näytä kaikki ilmoitukset"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Tyhjennä ilmoitus"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS käytössä."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Haetaan GPS-signaalia."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Kaikki luokat"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Lisäasetukset"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Muokkaa: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Valmis"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"Ilmoitusten hallinta"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi on pois käytöstä"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ei ole käytössä"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Älä häiritse ‑tila on pois käytöstä"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Automaattinen sääntö otti käyttöön Älä häiritse ‑tilan (<xliff:g id="ID_1">%s</xliff:g>). Pidetäänkö nykyiset asetukset?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Sovellus otti käyttöön Älä häiritse ‑tilan (<xliff:g id="ID_1">%s</xliff:g>). Pidetäänkö nykyiset asetukset?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Automaattinen sääntö tai sovellus otti käyttöön Älä häiritse ‑tilan. Pidetäänkö nykyiset asetukset?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> asti"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Säilytä"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Korvaa"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index a9e7883..ffbd493 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -166,7 +166,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Paramètres système"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifications"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Conteneur de dépassement des notifications"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Afficher toutes les notifications"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Supprimer la notification"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS activé"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Acquisition de données GPS"</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Toutes les catégories"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Personnaliser : <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"paramètres des notifications"</string>
@@ -745,9 +744,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Le Wi-Fi est désactivé"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Le Bluetooth est désactivé"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Le mode Ne pas déranger est désactivé"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Le mode Ne pas déranger a été activé par une règle automatique (<xliff:g id="ID_1">%s</xliff:g>). Garder les paramètres actuels?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Le mode Ne pas déranger a été activé par une application (<xliff:g id="ID_1">%s</xliff:g>). Garder les paramètres actuels?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Le mode Ne pas déranger a été activé par une règle automatique ou une application. Garder les paramètres actuels?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Jusqu\'à <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Garder"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Remplacer"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 1bcf6b4..d7f7115 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -166,7 +166,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Paramètres système"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifications"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Conteneur de dépassement des notifications"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Afficher toutes les notifications"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Supprimer la notification"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS activé"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Acquisition de données GPS"</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Toutes les catégories"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Personnaliser : <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> : <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"paramètres des notifications"</string>
@@ -745,9 +744,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi désactivé"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth désactivé"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Mode \"Ne pas déranger\" désactivé"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Le mode \"Ne pas déranger\" a été activé par une règle automatique (<xliff:g id="ID_1">%s</xliff:g>). Conserver les paramètres actuels ?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Le mode \"Ne pas déranger\" a été activé par une application (<xliff:g id="ID_1">%s</xliff:g>). Conserver les paramètres actuels ?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Le mode \"Ne pas déranger\" a été activé par une règle automatique ou une application. Conserver les paramètres actuels ?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Jusqu\'à <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Conserver"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Remplacer"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index eb856c9..ec65726 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -166,7 +166,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Configuración do sistema"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificacións"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Contedor de rebordamento de notificacións"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Ver todas as notificacións"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Eliminar notificación."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS activado"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Obtendo GPS."</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Todas as categorías"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Máis opcións"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Personalizar: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Feito"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"controis de notificacións"</string>
@@ -744,10 +743,13 @@
<string name="mobile_data" msgid="7094582042819250762">"Datos móbiles"</string>
<string name="wifi_is_off" msgid="1838559392210456893">"A wifi está desactivada"</string>
<string name="bt_is_off" msgid="2640685272289706392">"O Bluetooth está desactivado"</string>
- <string name="dnd_is_off" msgid="6167780215212497572">"Non molestar está desactivado"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Unha norma automática (<xliff:g id="ID_1">%s</xliff:g>) activou Non molestar. Queres manter a configuración actual?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Unha aplicación (<xliff:g id="ID_1">%s</xliff:g>) activou Non molestar. Queres manter a configuración actual?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Unha aplicación ou norma automática activou Non molestar. Queres manter a configuración actual?"</string>
+ <string name="dnd_is_off" msgid="6167780215212497572">"O modo Non molestar está desactivado"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Ata: <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Manter"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Substituír"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index e186285..3c3681d 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -164,7 +164,8 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"બૅટરી ચાર્જ થઈ રહી છે, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ટકા."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"સિસ્ટમ સેટિંગ્સ."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"સૂચનાઓ."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"સૂચના ઓવરફ્લો કંટેનર"</string>
+ <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
+ <skip />
<string name="accessibility_remove_notification" msgid="3603099514902182350">"સૂચના સાફ કરો."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS સક્ષમ."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS મેળવી રહ્યું છે."</string>
@@ -560,8 +561,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"બધી કૅટેગરી"</string>
<string name="notification_more_settings" msgid="816306283396553571">"વધુ સેટિંગ્સ"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"કસ્ટમાઇઝ કરો: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"થઈ ગયું"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"સૂચના નિયંત્રણો"</string>
@@ -740,22 +740,16 @@
<string name="instant_apps_message" msgid="8116608994995104836">"ઝટપટ ઍપ્લિકેશનો માટે ઇન્સ્ટૉલેશનની જરૂર નથી."</string>
<string name="app_info" msgid="6856026610594615344">"ઍપ્લિકેશન માહિતી"</string>
<string name="mobile_data" msgid="7094582042819250762">"મોબાઇલ ડેટા"</string>
- <!-- no translation found for wifi_is_off (1838559392210456893) -->
+ <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi બંધ છે"</string>
+ <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth બંધ છે"</string>
+ <string name="dnd_is_off" msgid="6167780215212497572">"ખલેલ પાડશો નહીં બંધ છે"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
<skip />
- <!-- no translation found for bt_is_off (2640685272289706392) -->
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
<skip />
- <!-- no translation found for dnd_is_off (6167780215212497572) -->
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
<skip />
- <!-- no translation found for qs_dnd_prompt_auto_rule (1570808639425342) -->
- <skip />
- <!-- no translation found for qs_dnd_prompt_app (1131614608680529190) -->
- <skip />
- <!-- no translation found for qs_dnd_prompt_auto_rule_app (3685659782196144067) -->
- <skip />
- <!-- no translation found for qs_dnd_until (3469471136280079874) -->
- <skip />
- <!-- no translation found for qs_dnd_keep (1825009164681928736) -->
- <skip />
- <!-- no translation found for qs_dnd_replace (8019520786644276623) -->
- <skip />
+ <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> સુધી"</string>
+ <string name="qs_dnd_keep" msgid="1825009164681928736">"રાખો"</string>
+ <string name="qs_dnd_replace" msgid="8019520786644276623">"બદલો"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index c41c06f..e4c1071 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"बैटरी चार्ज हो रही है, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> प्रतिशत."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"सिस्टम सेटिंग."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"सूचनाएं."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"नोटिफ़िकेशन ओवरफ़्लो कंटेनर"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"सभी नोटिफ़िकेशन देखें"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"नोटिफिकेशन साफ़ करें"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS सक्षम."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS प्राप्त करना."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"सभी श्रेणियां"</string>
<string name="notification_more_settings" msgid="816306283396553571">"और सेटिंग"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"कस्टमाइज़ करें: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"हो गया"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"नोटिफ़िकेशन नियंत्रण"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"वाई-फ़ाई बंद है"</string>
<string name="bt_is_off" msgid="2640685272289706392">"ब्लूटूथ बंद है"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"परेशान न करें बंद है"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"एक ऑटोमैटिक नियम (<xliff:g id="ID_1">%s</xliff:g>) ने परेशान न करें को चालू कर दिया था. क्या अभी वाली सेटिंग बनाए रखें?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"एक ऐप्लिकेशन (<xliff:g id="ID_1">%s</xliff:g>) ने परेशान न करें को चालू कर दिया था. क्या अभी वाली सेटिंग बनाए रखें?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"एक ऑटोमैटिक नियम या ऐप्लिकेशन ने परेशान न करें को चालू कर दिया था. क्या अभी वाली सेटिंग बनाए रखें?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> तक"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"रखें"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"बदलें"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index dfcd5f2..9e138ae 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -165,7 +165,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Baterija se puni, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> posto."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Postavke sustava."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Obavijesti."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Spremnik dodatnih obavijesti"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Pogledajte sve obavijesti"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Brisanje obavijesti"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS je omogućen."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Dohvaćanje GPS-a."</string>
@@ -564,8 +564,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Sve kategorije"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Više postavki"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Prilagodite: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"kontrole obavijesti"</string>
@@ -747,9 +746,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je isključen"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je isključen"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Način Ne uznemiravaj isključen"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Način Ne uznemiravaj uključen je automatskim pravilom (<xliff:g id="ID_1">%s</xliff:g>). Želite li zadržati trenutačne postavke?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Način Ne uznemiravaj uključila je aplikacija (<xliff:g id="ID_1">%s</xliff:g>). Želite li zadržati trenutačne postavke?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Način Ne uznemiravaj uključen je automatskim pravilom ili ga je uključila aplikacija. Želite li zadržati trenutačne postavke?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Zadrži"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Zamijeni"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 7ce96d3..a34da65 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Akkumulátor töltése folyamatban, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> százalék."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Rendszerbeállítások"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Értesítések"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Az értesítések túlcsordulási tárolója"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Összes értesítés megtekintése"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Értesítés törlése"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS engedélyezve."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS lekérése."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Minden kategória"</string>
<string name="notification_more_settings" msgid="816306283396553571">"További beállítások"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Személyre szabás: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Kész"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> – <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"értesítésvezérlők"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"A Wi-Fi ki van kapcsolva"</string>
<string name="bt_is_off" msgid="2640685272289706392">"A Bluetooth ki van kapcsolva"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"A „Ne zavarjanak” mód ki van kapcsolva"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Az egyik automatikus szabály (<xliff:g id="ID_1">%s</xliff:g>) bekapcsolta a „Ne zavarjanak” módot. Megtartja a jelenlegi beállításokat?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Az egyik alkalmazás (<xliff:g id="ID_1">%s</xliff:g>) bekapcsolta a „Ne zavarjanak” módot. Megtartja a jelenlegi beállításokat?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Az egyik alkalmazás vagy automatikus szabály bekapcsolta a „Ne zavarjanak” módot. Megtartja a jelenlegi beállításokat?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Eddig: <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Megtartás"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Csere"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 1fb282e..6635e61 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Մարտկոցը լիցքավորվում է: Լիցքը <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> տոկոս է:"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Համակարգի կարգավորումներ:"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Ծանուցումներ:"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Ծանուցումների գերբեռնման զետեղարան"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Տեսնել բոլոր ծանուցումները"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Մաքրել ծանուցումը:"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS-ը միացված է:"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS-ի ստացում:"</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Բոլոր կատեգորիաները"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Այլ կարգավորումներ"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Հարմարեցնել՝ <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Պատրաստ է"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"ծանուցման կառավարներ"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi-ն անջատված է"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth-ն անջատված է"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Չանհանգստացնելու ռեժիմն անջատված է"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Չանհանգստացնելու ռեժիմն անջատվել է ավտոմատ կանոնի կողմից (<xliff:g id="ID_1">%s</xliff:g>)։ Պահպանե՞լ ընթացիկ կարգավորումները։"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Չանհանգստացնելու ռեժիմն անջատվել է հավելվածի կողմից (<xliff:g id="ID_1">%s</xliff:g>)։ Պահպանե՞լ ընթացիկ կարգավորումները։"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Չանհանգստացնելու ռեժիմն անջատվել է ավտոմատ կանոնի կամ հավելվածի կողմից։ Պահպանե՞լ ընթացիկ կարգավորումները։"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Մինչև <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Պահել"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Փոխարինել"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 153a5b7..6c079440 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Mengisi daya baterai, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> persen."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Setelan sistem."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifikasi."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Penampung luapan notifikasi"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Lihat semua notifikasi"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Menghapus pemberitahuan."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS diaktifkan."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Memperoleh GPS."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Semua Kategori"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Setelan lainnya"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Sesuaikan: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Selesai"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"kontrol notifikasi"</string>
@@ -740,12 +739,15 @@
<string name="instant_apps_message" msgid="8116608994995104836">"Aplikasi instan tidak perlu diinstal."</string>
<string name="app_info" msgid="6856026610594615344">"Info aplikasi"</string>
<string name="mobile_data" msgid="7094582042819250762">"Data seluler"</string>
- <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi aktif"</string>
+ <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi nonaktif"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth nonaktif"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Fitur Jangan Ganggu nonaktif"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Fitur Jangan Ganggu diaktifkan oleh aturan otomatis (<xliff:g id="ID_1">%s</xliff:g>). Simpan setelan saat ini?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Fitur Jangan Ganggu diaktifkan oleh aplikasi (<xliff:g id="ID_1">%s</xliff:g>). Simpan setelan saat ini?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Fitur Jangan Ganggu diaktifkan oleh aplikasi atau aturan otomatis. Simpan setelan saat ini?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Hingga <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Simpan"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Ganti"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index e92c8d2..57e031d 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Rafhlaða í hleðslu, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> prósent."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Kerfisstillingar."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Tilkynningar."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Geymir yfirflæðistilkynninga"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Sjá allar tilkynningar"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Hreinsa tilkynningu."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS virkt."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Tenging við GPS."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Allir flokkar"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Fleiri stillingar"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Sérstilla: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Lokið"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"tilkynningastýringar"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Slökkt á Wi-Fi"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Slökkt á Bluetooth"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Slökkt á „Ónáðið ekki“"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Sjálfvirk regla (<xliff:g id="ID_1">%s</xliff:g>) kveikti á „Ónáðið ekki“. Halda núverandi stillingum?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Forrit (<xliff:g id="ID_1">%s</xliff:g>) kveikti á „Ónáðið ekki“. Halda núverandi stillingum?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Sjálfvirk regla eða forrit slökkti á „Ónáðið ekki“. Halda núverandi stillingum?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Þar til <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Halda"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Skipta út"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index b9141c7..1aab341 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -166,7 +166,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Impostazioni di sistema."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifiche."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Contenitore per notifiche overflow"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Visualizza tutte le notifiche"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Cancella notifica."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS abilitato."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Acquisizione GPS."</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Tutte le categorie"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Altre impostazioni"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Personalizza: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Fine"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"gestione delle notifiche"</string>
@@ -745,9 +744,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi disattivato"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth non attivo"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Funzione Non disturbare disattivata"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"La funzione Non disturbare è stata attivata da una regola automatica (<xliff:g id="ID_1">%s</xliff:g>). Mantenere le impostazioni attuali?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"La funzione Non disturbare è stata attivata da un\'app (<xliff:g id="ID_1">%s</xliff:g>). Mantenere le impostazioni attuali?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"La funzione Non disturbare è stata attivata da una regola automatica o da un\'app. Mantenere le impostazioni attuali?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Fino alle ore <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Mantieni"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Sostituisci"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index d1a160c..ab821b6 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -166,7 +166,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"טעינת סוללה, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> אחוז."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"הגדרות מערכת"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"התראות"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"מאגר הודעות נוספות"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"הצגת כל ההודעות"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"נקה התראה"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS מופעל."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"השגת GPS."</string>
@@ -568,8 +568,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"כל הקטגוריות"</string>
<string name="notification_more_settings" msgid="816306283396553571">"הגדרות נוספות"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"התאם אישית: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"סיום"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"בקרת הודעות"</string>
@@ -748,22 +747,16 @@
<string name="instant_apps_message" msgid="8116608994995104836">"אפליקציות אינסטנט לא דורשות התקנה."</string>
<string name="app_info" msgid="6856026610594615344">"פרטי אפליקציה"</string>
<string name="mobile_data" msgid="7094582042819250762">"נתונים סלולריים"</string>
- <!-- no translation found for wifi_is_off (1838559392210456893) -->
+ <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi כבוי"</string>
+ <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth כבוי"</string>
+ <string name="dnd_is_off" msgid="6167780215212497572">"מצב \'נא לא להפריע\' כבוי"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
<skip />
- <!-- no translation found for bt_is_off (2640685272289706392) -->
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
<skip />
- <!-- no translation found for dnd_is_off (6167780215212497572) -->
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
<skip />
- <!-- no translation found for qs_dnd_prompt_auto_rule (1570808639425342) -->
- <skip />
- <!-- no translation found for qs_dnd_prompt_app (1131614608680529190) -->
- <skip />
- <!-- no translation found for qs_dnd_prompt_auto_rule_app (3685659782196144067) -->
- <skip />
- <!-- no translation found for qs_dnd_until (3469471136280079874) -->
- <skip />
- <!-- no translation found for qs_dnd_keep (1825009164681928736) -->
- <skip />
- <!-- no translation found for qs_dnd_replace (8019520786644276623) -->
- <skip />
+ <string name="qs_dnd_until" msgid="3469471136280079874">"עד <xliff:g id="ID_1">%s</xliff:g>"</string>
+ <string name="qs_dnd_keep" msgid="1825009164681928736">"שמור"</string>
+ <string name="qs_dnd_replace" msgid="8019520786644276623">"החלף"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 4a8fb66..9454d54 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -166,7 +166,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"システム設定。"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"通知。"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"通知のオーバーフロー コンテナ"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"通知をすべて表示"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"通知を消去。"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPSが有効です。"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS取得中です。"</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"すべてのカテゴリ"</string>
<string name="notification_more_settings" msgid="816306283396553571">"詳細設定"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"カスタマイズ: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"完了"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"通知管理"</string>
@@ -745,9 +744,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi は OFF です"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth は OFF です"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"マナーモードは OFF です"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"マナーモードが自動ルール(<xliff:g id="ID_1">%s</xliff:g>)によって ON になりました。現在の設定を維持しますか?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"マナーモードがアプリ(<xliff:g id="ID_1">%s</xliff:g>)によって ON になりました。現在の設定を維持しますか?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"マナーモードが自動ルールまたはアプリによって ON になりました。現在の設定を維持しますか?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"終了時間: <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"設定を維持"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"設定を変更"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 9099a02..5281011 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ბატარეა იტენება, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> პროცენტი."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"სისტემის პარამეტრები."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"შეტყობინებები"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"შეტყობინების გადავსების კონტეინერი"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"ყველა შეტყობინების ნახვა"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"შეტყობინებების გასუფთავება."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS გააქტიურდა."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS-ის დადგენა."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"ყველა კატეგორია"</string>
<string name="notification_more_settings" msgid="816306283396553571">"დამატებითი პარამეტრები"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"მორგება: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"მზადაა"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"შეტყობინებების მართვის საშუალებები"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi გამორთულია"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth გამორთულია"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"„არ შემაწუხოთ“ რეჟიმი გამორთულია"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"„არ შემაწუხოთ“ ჩართულია ავტომატური წესის მიხედვით (<xliff:g id="ID_1">%s</xliff:g>). გსურთ მიმდინარე პარამეტრების შენარჩუნება?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"„არ შემაწუხოთ“ ჩართულია აპის მიერ (<xliff:g id="ID_1">%s</xliff:g>). გსურთ მიმდინარე პარამეტრების შენარჩუნება?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"„არ შემაწუხოთ“ ჩართულია ავტომატური წესის მიხედვით ან აპის მიერ. გსურთ მიმდინარე პარამეტრების შენარჩუნება?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g>-მდე"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"შენარჩუნება"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"ჩანაცვლება"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 1ba56ac..0ae02cc 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Батарея зарядталуда, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> пайыз."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Жүйе параметрлері."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Хабарлар."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Хабарландырулардың қосымша контейнері"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Барлық хабарландыруды қарау"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Хабарларды өшіру."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS қосылған."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS қыземтін шығару."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Барлық санаттар"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Қосымша параметрлер"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Реттеу: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Дайын"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"хабарландыруларды басқару элементтері"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi өшірулі"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth өшірулі"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"\"Мазаламау\" режимі өшірулі"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"\"Мазаламау\" режимі (<xliff:g id="ID_1">%s</xliff:g>) автоматты ережесі арқылы қосылды. Ағымдағы параметрлер қалсын ба?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"\"Мазаламау\" режимі (<xliff:g id="ID_1">%s</xliff:g>) қолданбасы арқылы қосылды. Ағымдағы параметрлер қалсын ба?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"\"Мазаламау\" режимі автоматты ереже немесе қолданба арқылы қосылды. Ағымдағы параметрлер қалсын ба?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> дейін"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Қалсын"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Ауыстыру"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 989bd5e..6545d3a 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"កំពុងសាកថ្ម <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ភាគរយ"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"ការកំណត់ប្រព័ន្ធ។"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"ការជូនដំណឹង។"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"អង្គផ្ទុកបន្ថែមសម្រាប់ការជូនដំណឹង"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"មើលការជូនដំណឹងទាំងអស់"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"សម្អាតការជូនដំណឹង។"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"បានបើក GPS ។"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"ទទួល GPS ។"</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"ប្រភេទទាំងអស់"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ការកំណត់ច្រើនទៀត"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"ប្ដូរតាមបំណង៖ <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"រួចរាល់"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"ការគ្រប់គ្រងការជូនដំណឹង"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi បានបិទ"</string>
<string name="bt_is_off" msgid="2640685272289706392">"ប៊្លូធូសបានបិទ"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"មុខងារកុំរំខានបានបិទ"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"មុខងារកុំរំខានត្រូវបានបើកដោយច្បាប់ស្វ័យប្រវត្តិ (<xliff:g id="ID_1">%s</xliff:g>)។ រក្សាការកំណត់បច្ចុប្បន្ននៅដដែល?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"មុខងារកុំរំខានត្រូវបានបើកដោយកម្មវិធី (<xliff:g id="ID_1">%s</xliff:g>)។ រក្សាការកំណត់បច្ចុប្បន្ននៅដដែល?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"មុខងារកុំរំខានត្រូវបានបើកដោយច្បាប់ស្វ័យប្រវត្តិ ឬកម្មវិធី។ រក្សាការកំណត់បច្ចុប្បន្ននៅដដែល?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"រហូតដល់ <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"រក្សានៅដដែល"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"ជំនួស"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 5b0a02d..fd3233e 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ಬ್ಯಾಟರಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ಪ್ರತಿಶತ."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"ಸಿಸ್ಟಂ ಸೆಟ್ಟಿಂಗ್ಗಳು."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"ಅಧಿಸೂಚನೆಗಳು."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"ಅಧಿಸೂಚನೆಯ ಓವರ್ಫ್ಲೋ ಕಂಟೇನರ್"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ನೋಡಿ"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"ಅಧಿಸೂಚನೆ ತೆರವುಗೊಳಿಸು."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ಸಕ್ರಿಯವಾಗಿದೆ."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS ಸ್ವಾಧೀನ."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"ಎಲ್ಲ ವರ್ಗಗಳು"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ಹೆಚ್ಚಿನ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"ಕಸ್ಟಮೈಸ್: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"ಮುಗಿದಿದೆ"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳು"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"ವೈ-ಫೈ ಆಫ್ ಆಗಿದೆ"</string>
<string name="bt_is_off" msgid="2640685272289706392">"ಬ್ಲೂಟೂತ್ ಆಫ್ ಆಗಿದೆ"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಆಫ್ ಆಗಿದೆ"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"(<xliff:g id="ID_1">%s</xliff:g>) ಸ್ವಯಂಚಾಲಿತ ನಿಯಮದ ಮೂಲಕ ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಆನ್ ಆಗಿದೆ. ಪ್ರಸ್ತುತ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಹಾಗೆಯೇ ಇರಿಸುವುದೇ?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"(<xliff:g id="ID_1">%s</xliff:g>) ಅಪ್ಲಿಕೇಶನ್ ಮೂಲಕ ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಆನ್ ಆಗಿದೆ. ಪ್ರಸ್ತುತ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಹಾಗೆಯೇ ಇರಿಸುವುದೇ?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"ಸ್ವಯಂಚಾಲಿತ ನಿಯಮ ಅಥವಾ ಅಪ್ಲಿಕೇಶನ್ ಮೂಲಕ ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಆನ್ ಆಗಿದೆ. ಪ್ರಸ್ತುತ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಹಾಗೆಯೇ ಇರಿಸುವುದೇ?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> ತನಕ"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"ಇರಿಸಿ"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"ಬದಲಿಸಿ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 3bd22e2..649dd1a 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -166,7 +166,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"시스템 설정"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"알림"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"알림 오버플로우 컨테이너"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"모든 알림 보기"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"알림 지우기"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS가 사용 설정되었습니다."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS를 가져오는 중입니다."</string>
@@ -274,7 +274,7 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"블루투스"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"블루투스(<xliff:g id="NUMBER">%d</xliff:g>개의 기기)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"블루투스 사용 안함"</string>
- <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"페어링된 기기가 없습니다."</string>
+ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"페어링된 기기가 없습니다"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"밝기"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"자동 회전"</string>
<string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"화면 자동 회전"</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"전체 카테고리"</string>
<string name="notification_more_settings" msgid="816306283396553571">"설정 더보기"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"맞춤설정: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"완료"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"알림 관리"</string>
@@ -745,9 +744,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi가 사용 중지됨"</string>
<string name="bt_is_off" msgid="2640685272289706392">"블루투스가 사용 중지됨"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"알림 일시중지가 사용 중지됨"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"알림 일시중지가 자동 규칙(<xliff:g id="ID_1">%s</xliff:g>)에 의해 사용 설정되었습니다. 현재 설정을 유지하시겠습니까?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"알림 일시중지가 앱(<xliff:g id="ID_1">%s</xliff:g>)에 의해 사용 설정되었습니다. 현재 설정을 유지하시겠습니까?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"알림 일시중지가 자동 규칙 또는 앱에 의해 사용 설정되었습니다. 현재 설정을 유지하시겠습니까?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g>까지"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"유지"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"바꾸기"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 1b0505d..53b46f9 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Батарея кубатталууда, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> пайыз."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Система тууралоолору."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Эскертмелер."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Эскертмелер контейнери"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Бардык эскертмелерди көрүү"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Эскертмелерди тазалоо."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS жандырылган."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS байланышууда."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Бардык категориялар"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Дагы жөндөөлөр"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Ыңгайлаштыруу: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Бүттү"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"эскертмелерди башкаруу каражаттары"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi өчүк"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth өчүк"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"\"Тынчымды алба\" режими өчүк"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Автоматтык эреже \"Тынчымды алба\" режимин күйгүздү (<xliff:g id="ID_1">%s</xliff:g>). Учурдагы жөндөөлөр сакталсынбы?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Колдонмо \"Тынчымды алба\" режимин күйгүздү (<xliff:g id="ID_1">%s</xliff:g>). Учурдагы жөндөөлөр сакталсынбы?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Автоматтык эреже же колдонмо \"Тынчымды алба\" режимин күйгүздү. Учурдагы жөндөөлөр сакталсынбы?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> чейин"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Ушундай калтыруу"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Алмаштыруу"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 02798f1..72fc0c6 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ກຳລັງສາກແບັດເຕີຣີ, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ເປີເຊັນ."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"ການຕັ້ງຄ່າລະບົບ."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"ການແຈ້ງເຕືອນ."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"ຕົວບັນຈຸການລົ້ມການແຈ້ງເຕືອນ"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"ເບິ່ງການແຈ້ງເຕືອນທັງໝົດ"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"ລຶບລ້າງການແຈ້ງເຕືອນ."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ເປີດແລ້ວ."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"ກຳລັງຊອກຫາ GPS."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"ທຸກໝວດໝູ່"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ການຕັ້ງຄ່າເພີ່ມເຕີມ"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"ປັບແຕ່ງ: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"ສຳເລັດແລ້ວ"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"ການຄວບຄຸມການແຈ້ງເຕືອນ"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ປິດຢູ່"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ປິດຢູ່"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"ຫ້າມລົບກວນ ປິດຢູ່"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"ໂໝດຫ້າມລົບກວນຖືກເປີດໃຊ້ໂດຍກົດອັດຕະໂນມັດ (<xliff:g id="ID_1">%s</xliff:g>). ເກັບການຕັ້ງຄ່າປັດຈຸບັນໄວ້ບໍ?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"ໂໝດຫ້າມລົບກວນຖືກເປີດໃຊ້ໂດຍແອັບໜຶ່ງ (<xliff:g id="ID_1">%s</xliff:g>). ເກັບການຕັ້ງຄ່າປັດຈຸບັນໄວ້ບໍ?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"ໂໝດຫ້າມລົບກວນຖືກເປີດໃຊ້ໂດຍກົດອັດຕະໂນມັດ ຫຼື ແອັບໃດໜຶ່ງ. ເກັບການຕັ້ງຄ່າປັດຈຸບັນໄວ້ບໍ?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"ຈົນຮອດ <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"ເກັບໄວ້"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"ແທນທີ່"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 3470ad4..51d738c 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -166,7 +166,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Įkraunamas akumuliatorius, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> proc."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Sistemos nustatymai"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Pranešimai."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Pranešimų perpildymo sudėtinis rodinys"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Žr. visus pranešimus"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Išvalyti pranešimą."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS įgalintas."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Gaunama GPS."</string>
@@ -568,8 +568,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Visos kategorijos"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Daugiau nustatymų"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Tinkinti: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Atlikta"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"pranešimų valdikliai"</string>
@@ -751,9 +750,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"„Wi-Fi“ išjungtas"</string>
<string name="bt_is_off" msgid="2640685272289706392">"„Bluetooth“ išjungtas"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Netrukdymo režimas išjungtas"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Netrukdymo režimas įjungtas naudojant automatinę taisyklę (<xliff:g id="ID_1">%s</xliff:g>). Palikti dabartinius nustatymus?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Netrukdymo režimą įjungė programa (<xliff:g id="ID_1">%s</xliff:g>). Palikti dabartinius nustatymus?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Netrukdymo režimas įjungtas naudojant automatinę taisyklę arba programą. Palikti dabartinius nustatymus?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Iki <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Palikti"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Pakeisti"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 6bc7b38..b32ac24 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -165,7 +165,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Notiek akumulatora uzlāde, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procenti."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Sistēmas iestatījumi"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Paziņojumi"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Paziņojumu pārpildes konteiners"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Skatīt visus paziņojumus"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Notīrīt paziņojumu"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ir iespējots."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS iegūšana."</string>
@@ -564,8 +564,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Visas kategorijas"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Citi iestatījumi"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Pielāgot: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Gatavs"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"paziņojumu vadīklas"</string>
@@ -747,9 +746,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ir izslēgts"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ir izslēgts"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Režīms “Netraucēt” ir izslēgts"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Režīmu “Netraucēt” ieslēdza automātiska kārtula (<xliff:g id="ID_1">%s</xliff:g>). Vai paturēt pašreizējos iestatījumus?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Režīmu “Netraucēt” ieslēdza lietotne (<xliff:g id="ID_1">%s</xliff:g>). Vai paturēt pašreizējos iestatījumus?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Režīmu “Netraucēt” ieslēdza automātiska kārtula vai lietotne. Vai paturēt pašreizējos iestatījumus?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Līdz: <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Paturēt"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Aizstāt"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 0b160f5..1ecb7cf 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Полнење на батеријата, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> проценти."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Поставки на систем."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Известувања"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Контејнер за прелевање на известувања"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Видете ги сите известувања"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Избриши известување."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS е овозможен."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Се добива GPS..."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Сите категории"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Повеќе поставки"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Приспособи: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"контроли за известувањето"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi е исклучено"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth е исклучен"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"„Не вознемирувај“ е исклучено"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Автоматското правило ја вклучи „Не вознемирувај“ (<xliff:g id="ID_1">%s</xliff:g>). Да се задржат тековните поставки?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Апликацијата (<xliff:g id="ID_1">%s</xliff:g>) ја вклучи „Не вознемирувај“. Да се задржат тековните поставки?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Некое автоматско правило или апликација ја вклучи „Не вознемирувај“. Да се задржат тековните поставки?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"До <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Задржи"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Замени"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 2c949c9..6032246 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ബാറ്ററി ചാർജുചെയ്യുന്നു, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ശതമാനം."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"സിസ്റ്റം ക്രമീകരണങ്ങൾ."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"അറിയിപ്പുകൾ."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"അറിയിപ്പ് ഓവർഫ്ലോ കണ്ടെയിനർ"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"എല്ലാ അറിയിപ്പുകളും കാണുക"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"വിവരം മായ്ക്കുക."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS പ്രവർത്തനക്ഷമമായി."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS നേടുന്നു."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"എല്ലാ വിഭാഗങ്ങളും"</string>
<string name="notification_more_settings" msgid="816306283396553571">"കൂടുതൽ ക്രമീകരണം"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"ഇഷ്ടാനുസൃതമാക്കുക: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"പൂർത്തിയായി"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"അറിയിപ്പ് നിയന്ത്രണങ്ങൾ"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"വൈഫൈ ഓഫാണ്"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ഓഫാണ്"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"\'ശല്യപ്പെടുത്തരുത്\' ഓഫാണ്"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"സ്വയമേവയുള്ള ഒരു നയം (<xliff:g id="ID_1">%s</xliff:g>) \'ശല്യപ്പെടുത്തരുത്\' ഓണാക്കിയിരിക്കുന്നു. നിലവിലെ ക്രമീകരണം നിലനിർത്തണോ?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"ഒരു ആപ്പ് (<xliff:g id="ID_1">%s</xliff:g>) \'ശല്യപ്പെടുത്തരുത്\' ഓണാക്കിയിരിക്കുന്നു. നിലവിലെ ക്രമീകരണം നിലനിർത്തണോ?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"സ്വയമേവയുള്ള ഒരു നയമോ ആപ്പോ \'ശല്യപ്പെടുത്തരുത്\' ഓണാക്കിയിരിക്കുന്നു. നിലവിലെ ക്രമീകരണം നിലനിർത്തണോ?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> വരെ"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"സൂക്ഷിക്കുക"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"മാറ്റിസ്ഥാപിക്കുക"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 56d4b05..d33849d 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -162,7 +162,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Тэжээлийг цэнэглэж байна, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> хувь."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Системийн тохиргоо."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Мэдэгдэл."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Илүү гарсан мэдэгдлийг агуулагч"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Бүх мэдэгдлийг харах"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Мэдэгдлийг цэвэрлэх."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS идэвхтэй."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS хайж байна."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Бүх ангилал"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Бусад тохиргоо"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Өөрчлөх: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Дууссан"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"мэдэгдлийн удирдлага"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi унтраалттай байна"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth унтраалттай байна"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Бүү саад бол горим унтраалттай байна"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Бүү саад бол горимыг автомат дүрэм (<xliff:g id="ID_1">%s</xliff:g>) асаасан. Одоогийн тохиргоог хадгалах уу?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Апп-д (<xliff:g id="ID_1">%s</xliff:g>) Бүү саад бол горимыг асаасан. Одоогийн тохиргоог хадгалах уу?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Бүү саад бол горимыг автомат дүрэм эсвэл апп асаасан. Одоогийн тохиргоог хадгалах уу?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> хүртэл"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Хадгалах"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Солих"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 1bdb272..692753d2 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -164,7 +164,8 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"बॅटरी चार्ज होत आहे, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> टक्के."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"सिस्टम सेटिंग्ज."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"सूचना."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"सूचना ओव्हरफ्लो कंटेनर"</string>
+ <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
+ <skip />
<string name="accessibility_remove_notification" msgid="3603099514902182350">"सूचना साफ करा."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS सक्षम केले."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS प्राप्त करीत आहे."</string>
@@ -560,8 +561,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"सर्व श्रेण्या"</string>
<string name="notification_more_settings" msgid="816306283396553571">"अधिक सेटिंग्ज"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"सानुकूल करा: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"पूर्ण झाले"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"सूचना नियंत्रणे"</string>
@@ -740,22 +740,16 @@
<string name="instant_apps_message" msgid="8116608994995104836">"इन्सटंट अॅप्सना स्थापनेची आवश्यकता नसते."</string>
<string name="app_info" msgid="6856026610594615344">"अॅप माहिती"</string>
<string name="mobile_data" msgid="7094582042819250762">"मोबाइल डेटा"</string>
- <!-- no translation found for wifi_is_off (1838559392210456893) -->
+ <string name="wifi_is_off" msgid="1838559392210456893">"वाय-फाय बंद आहे"</string>
+ <string name="bt_is_off" msgid="2640685272289706392">"ब्लूटुथ बंद आहे"</string>
+ <string name="dnd_is_off" msgid="6167780215212497572">"व्यत्यय आणू नका बंद आहे"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
<skip />
- <!-- no translation found for bt_is_off (2640685272289706392) -->
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
<skip />
- <!-- no translation found for dnd_is_off (6167780215212497572) -->
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
<skip />
- <!-- no translation found for qs_dnd_prompt_auto_rule (1570808639425342) -->
- <skip />
- <!-- no translation found for qs_dnd_prompt_app (1131614608680529190) -->
- <skip />
- <!-- no translation found for qs_dnd_prompt_auto_rule_app (3685659782196144067) -->
- <skip />
- <!-- no translation found for qs_dnd_until (3469471136280079874) -->
- <skip />
- <!-- no translation found for qs_dnd_keep (1825009164681928736) -->
- <skip />
- <!-- no translation found for qs_dnd_replace (8019520786644276623) -->
- <skip />
+ <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> पर्यंत"</string>
+ <string name="qs_dnd_keep" msgid="1825009164681928736">"ठेवा"</string>
+ <string name="qs_dnd_replace" msgid="8019520786644276623">"पुनर्स्थित करा"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 76f2bf5..89070f7 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Bateri mengecas, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> peratus."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Tetapan sistem."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Pemberitahuan."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Bekas limpahan pemberitahuan"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Lihat semua pemberitahuan"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Padamkan pemberitahuan."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS didayakan."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS sedang mendapatkan."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Semua Kategori"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Lagi tetapan"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Sesuaikan: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Selesai"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"kawalan pemberitahuan"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi dimatikan"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth dimatikan"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Jangan Ganggu dimatikan"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Jangan Ganggu telah dihidupkan oleh peraturan automatik (<xliff:g id="ID_1">%s</xliff:g>). Simpan tetapan semasa?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Jangan Ganggu dihidupkan oleh apl (<xliff:g id="ID_1">%s</xliff:g>). Simpan tetapan semasa?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Jangan Ganggu telah dihidupkan oleh peraturan automatik atau apl. Simpan tetapan semasa?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Hingga <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Simpan"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Gantikan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 770ec03..c7fb3d3 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ဘက်ထရီအားသွင်းနေသည်၊ <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ရာခိုင်နှုန်း။"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"စနစ်အပြင်အဆင်များ"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"အကြောင်းကြားချက်များ။"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"အကြောင်းကြားချက် ကွန်တိန်နာ"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"သတိပေးချက်များအားလုံးကို ကြည့်ရန်"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"သတိပေးချက်အား ဖယ်ရှားခြင်း။"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPSသုံးစွဲနိုင်သည်"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS ဖမ်းယူနေသည်။"</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"အုပ်စုအားလုံး"</string>
<string name="notification_more_settings" msgid="816306283396553571">"နောက်ထပ် ဆက်တင်များ"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"စိတ်ကြိုက်သတ်မှတ်ရန်− <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"ပြီးပါပြီ"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"အကြောင်းကြားချက် ထိန်းချုပ်မှုများ"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ကို ပိတ်ထားသည်"</string>
<string name="bt_is_off" msgid="2640685272289706392">"ဘလူးတုသ်ကို ပိတ်ထားသည်"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"\"မနှောင့်ယှက်ရ\" ကို ပိတ်ထားသည်"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"အလိုလျောက်စည်းမျဉ်း (<xliff:g id="ID_1">%s</xliff:g>) က \"မနှောင့်ယှက်ရ\" ကို ဖွင့့့်််လိုက်ပါသည်။ လက်ရှိဆက်တင်များကို သိမ်းလိုပါသလား။"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"အက်ပ် (<xliff:g id="ID_1">%s</xliff:g>) က \"မနှောင့်ယှက်ရ\" ကို ဖွင့်လိုက်ပါသည်။ လက်ရှိဆက်တင်များကို သိမ်းလိုပါသလား။"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"အလိုလျောက်စည်းမျဉ်း သို့မဟုတ် အက်ပ်တစ်ခုက \"မနှောင့်ယှက်ရ\" ကို ဖွင့့့်််လိုက်ပါသည်။ လက်ရှိဆက်တင်များကို သိမ်းလိုပါသလား။"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> အထိ"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"သိမ်းထားရန်"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"အစားထိုးရန်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 4fe0bca..5bf6d52 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Batteriet lades – <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> prosent."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Systeminnstillinger."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Varsler."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Overflytsbeholder for varsel"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Se alle varslene"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Fjern varsling"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS er aktivert."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Henting av GPS-signal."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Alle kategorier"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Flere innstillinger"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Tilpass: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Ferdig"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"varselinnstillinger"</string>
@@ -740,22 +739,16 @@
<string name="instant_apps_message" msgid="8116608994995104836">"Du trenger ikke å installere instant-apper."</string>
<string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
<string name="mobile_data" msgid="7094582042819250762">"Mobildata"</string>
- <!-- no translation found for wifi_is_off (1838559392210456893) -->
+ <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi er av"</string>
+ <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth er av"</string>
+ <string name="dnd_is_off" msgid="6167780215212497572">"Ikke forstyrr er av"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
<skip />
- <!-- no translation found for bt_is_off (2640685272289706392) -->
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
<skip />
- <!-- no translation found for dnd_is_off (6167780215212497572) -->
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
<skip />
- <!-- no translation found for qs_dnd_prompt_auto_rule (1570808639425342) -->
- <skip />
- <!-- no translation found for qs_dnd_prompt_app (1131614608680529190) -->
- <skip />
- <!-- no translation found for qs_dnd_prompt_auto_rule_app (3685659782196144067) -->
- <skip />
- <!-- no translation found for qs_dnd_until (3469471136280079874) -->
- <skip />
- <!-- no translation found for qs_dnd_keep (1825009164681928736) -->
- <skip />
- <!-- no translation found for qs_dnd_replace (8019520786644276623) -->
- <skip />
+ <string name="qs_dnd_until" msgid="3469471136280079874">"Til <xliff:g id="ID_1">%s</xliff:g>"</string>
+ <string name="qs_dnd_keep" msgid="1825009164681928736">"Behold"</string>
+ <string name="qs_dnd_replace" msgid="8019520786644276623">"Erstatt"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 3c42036..815293e2 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ब्याट्री चार्ज हुँदैछ, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> प्रतिशत।"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"प्रणाली सेटिङहरू"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"सूचनाहरू।"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"सूचना ओभरफ्लोको कन्टेनर"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"सबै सूचनाहरू हेर्नुहोस्"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"सूचना खाली गर्नुहोस्।"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS सक्षम गरिएको"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS प्राप्त हुँदैछ।"</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"सबै कोटिहरू"</string>
<string name="notification_more_settings" msgid="816306283396553571">"थप सेटिङहरू"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"आफू अनुकूल पार्नुहोस्: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"सम्पन्न भयो"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"सूचना सम्बन्धी नियन्त्रणहरू"</string>
@@ -740,22 +739,16 @@
<string name="instant_apps_message" msgid="8116608994995104836">"तात्कालिक अनुप्रयोगहरूलाई स्थापना गर्नु पर्दैन|"</string>
<string name="app_info" msgid="6856026610594615344">"अनुप्रयोगका बारे जानकारी"</string>
<string name="mobile_data" msgid="7094582042819250762">"मोबाइल डेटा"</string>
- <!-- no translation found for wifi_is_off (1838559392210456893) -->
+ <string name="wifi_is_off" msgid="1838559392210456893">"Wi‑Fi निष्क्रिय छ"</string>
+ <string name="bt_is_off" msgid="2640685272289706392">"ब्लुटुथ निष्क्रिय छ"</string>
+ <string name="dnd_is_off" msgid="6167780215212497572">"बाधा नपुर्याउनुहोस् नामक विकल्प निष्क्रिय छ"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
<skip />
- <!-- no translation found for bt_is_off (2640685272289706392) -->
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
<skip />
- <!-- no translation found for dnd_is_off (6167780215212497572) -->
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
<skip />
- <!-- no translation found for qs_dnd_prompt_auto_rule (1570808639425342) -->
- <skip />
- <!-- no translation found for qs_dnd_prompt_app (1131614608680529190) -->
- <skip />
- <!-- no translation found for qs_dnd_prompt_auto_rule_app (3685659782196144067) -->
- <skip />
- <!-- no translation found for qs_dnd_until (3469471136280079874) -->
- <skip />
- <!-- no translation found for qs_dnd_keep (1825009164681928736) -->
- <skip />
- <!-- no translation found for qs_dnd_replace (8019520786644276623) -->
- <skip />
+ <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> सम्म"</string>
+ <string name="qs_dnd_keep" msgid="1825009164681928736">"राख्नुहोस्"</string>
+ <string name="qs_dnd_replace" msgid="8019520786644276623">"प्रतिस्थापन गर्नुहोस्"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index cb75e54..1ad45bd 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Accu wordt opgeladen, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procent."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Systeeminstellingen."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Meldingen."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Overloopcontainer voor meldingen"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Alle meldingen bekijken"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Melding wissen"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"gps ingeschakeld."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Verbinding maken met gps."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Alle categorieën"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Meer instellingen"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Aanpassen: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Gereed"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"beheeropties voor meldingen"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wifi is uitgeschakeld"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is uitgeschakeld"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"\'Niet storen\' is uitgeschakeld"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"\'Niet storen\' is ingeschakeld door een automatische regel (<xliff:g id="ID_1">%s</xliff:g>). Huidige instellingen behouden?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"\'Niet storen\' is ingeschakeld door een app (<xliff:g id="ID_1">%s</xliff:g>). Huidige instellingen behouden?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"\'Niet storen\' is ingeschakeld voor een automatische regel of app. Huidige instellingen behouden?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Tot <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Behouden"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Vervangen"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index ee4df38..183b22c 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ਬੈਟਰੀ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ਪ੍ਰਤੀਸ਼ਤ।"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"ਸਿਸਟਮ ਸੈਟਿੰਗਾਂ।"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"ਸੂਚਨਾਵਾਂ।"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"ਸੂਚਨਾ ਓਵਰਫਲੋ ਕੰਟੇਨਰ"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਦੇਖੋ"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"ਸੂਚਨਾ ਹਟਾਓ।"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ਸਮਰਥਿਤ।"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS ਪ੍ਰਾਪਤ ਕਰ ਰਿਹਾ ਹੈ।"</string>
@@ -438,14 +438,14 @@
<string name="monitoring_button_view_policies" msgid="100913612638514424">"ਨੀਤੀਆਂ ਵੇਖੋ"</string>
<string name="monitoring_description_named_management" msgid="4872859182820011954">"ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।\n\nਤੁਹਾਡਾ ਪ੍ਰਸ਼ਾਸਕ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਨਾਲ ਸਬੰਧਿਤ ਸੈਟਿੰਗਾਂ, ਕਾਰਪੋਰੇਟ ਪਹੁੰਚ, ਐਪਾਂ, ਡੈਟੇ ਅਤੇ ਤੁਹਾਡੀਆਂ ਡੀਵਾਈਸਾਂ ਦੀ ਟਿਕਾਣਾ ਜਾਣਕਾਰੀ ਦੀ ਨਿਗਰਾਨੀ ਅਤੇ ਉਹਨਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰ ਸਕਦਾ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।\""</string>
<string name="monitoring_description_management" msgid="3115563193381106341">"ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।\n\nਤੁਹਾਡਾ ਪ੍ਰਸ਼ਾਸਕ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਨਾਲ ਸਬੰਧਿਤ ਸੈਟਿੰਗਾਂ, ਕਾਰਪੋਰੇਟ ਪਹੁੰਚ, ਐਪਾਂ, ਡੈਟੇ ਅਤੇ ਤੁਹਾਡੀਆਂ ਡੀਵਾਈਸਾਂ ਦੀ ਟਿਕਾਣਾ ਜਾਣਕਾਰੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦਾ ਹੈ ਅਤੇ ਉਹਨਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰ ਸਕਦਾ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।\""</string>
- <string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਇੱਕ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਅਥਾਰਿਟੀ ਸਥਾਪਤ ਕੀਤੀ ਗਈ ਹੈ। ਤੁਹਾਡੀ ਸੁਰੱਖਿਅਤ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਾਂ ਉਸਨੂੰ ਸੋਧਿਆ ਜਾ ਸਕਦਾ ਹੈ।"</string>
- <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਇੱਕ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਅਥਾਰਿਟੀ ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਸਥਾਪਤ ਕੀਤੀ ਗਈ ਹੈ। ਤੁਹਾਡੀ ਸੁਰੱਖਿਅਤ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਾਂ ਉਸਨੂੰ ਸੋਧਿਆ ਜਾ ਸਕਦਾ ਹੈ।"</string>
- <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"ਇੱਕ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਅਥਾਰਿਟੀ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਸਥਾਪਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ। ਤੁਹਾਡੀ ਸੁਰੱਖਿਅਤ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਾਂ ਉਸਨੂੰ ਸੋਧਿਆ ਜਾ ਸਕਦਾ ਹੈ।"</string>
- <string name="monitoring_description_management_network_logging" msgid="7184005419733060736">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਨੈੱਟਵਰਕ ਲੌਗਿੰਗ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਹੋਇਆ ਹੈ, ਜੋ ਤੁਹਾਡੀ ਡੀਵਾਈਸ \'ਤੇ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰਦੀ ਹੈ।"</string>
+ <string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਇੱਕ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਅਥਾਰਟੀ ਸਥਾਪਤ ਕੀਤੀ ਗਈ ਹੈ। ਤੁਹਾਡੇ ਸੁਰੱਖਿਅਤ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਾਂ ਉਸਨੂੰ ਸੋਧਿਆ ਜਾ ਸਕਦਾ ਹੈ।"</string>
+ <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਇੱਕ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਅਥਾਰਟੀ ਸਥਾਪਤ ਕੀਤੀ ਗਈ ਹੈ। ਤੁਹਾਡੇ ਸੁਰੱਖਿਅਤ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਾਂ ਉਸਨੂੰ ਸੋਧਿਆ ਜਾ ਸਕਦਾ ਹੈ।"</string>
+ <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"ਇੱਕ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਅਥਾਰਟੀ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਸਥਾਪਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ। ਤੁਹਾਡੇ ਸੁਰੱਖਿਅਤ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਾਂ ਉਸਨੂੰ ਸੋਧਿਆ ਜਾ ਸਕਦਾ ਹੈ।"</string>
+ <string name="monitoring_description_management_network_logging" msgid="7184005419733060736">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਨੈੱਟਵਰਕ ਲੌਗਿੰਗ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਹੋਇਆ ਹੈ, ਜੋ ਤੁਹਾਡੀ ਡੀਵਾਈਸ \'ਤੇ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰਦਾ ਹੈ।"</string>
<string name="monitoring_description_named_vpn" msgid="639013857356724268">"ਤੁਸੀਂ <xliff:g id="VPN_APP">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string>
<string name="monitoring_description_two_named_vpns" msgid="4479748971871539316">"ਤੁਸੀਂ <xliff:g id="VPN_APP_0">%1$s</xliff:g> ਅਤੇ <xliff:g id="VPN_APP_1">%2$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string>
<string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"ਤੁਹਾਡਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ <xliff:g id="VPN_APP">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੈ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string>
- <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"ਤੁਹਾਡਾ ਨਿੱਜੀ ਪ੍ਰੋਫ਼ਾਈਲ <xliff:g id="VPN_APP">%1$s</xliff:g>ਨਾਲ ਕਨੈਕਟ ਹੈ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string>
+ <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"ਤੁਹਾਡਾ ਨਿੱਜੀ ਪ੍ਰੋਫਾਈਲ <xliff:g id="VPN_APP">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੈ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string>
<string name="monitoring_description_do_header_generic" msgid="96588491028288691">"ਤੁਹਾਡੀ ਡੀਵਾਈਸ <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ।"</string>
<string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਦੇ ਪ੍ਰਬੰਧਨ ਲਈ <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਦੀ ਹੈ।"</string>
<string name="monitoring_description_do_body" msgid="3639594537660975895">"ਤੁਹਾਡਾ ਪ੍ਰਸ਼ਾਸਕ ਸੈਟਿੰਗਾਂ, ਕਾਰਪੋਰੇਟ ਪਹੁੰਚ, ਐਪਾਂ, ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਨਾਲ ਜੁੜੇ ਡੈਟੇ ਅਤੇ ਟਿਕਾਣਾ ਜਾਣਕਾਰੀ ਦੀ ਨਿਗਰਾਨੀ ਅਤੇ ਪ੍ਰਬੰਧਨ ਕਰ ਸਕਦਾ ਹੈ।"</string>
@@ -464,7 +464,7 @@
<string name="monitoring_description_app_personal" msgid="484599052118316268">"ਤੁਸੀਂ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋ, ਜੋ ਈਮੇਲ, ਐਪਸ ਅਤੇ ਵੈਬਸਫ਼ਿਆਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦੀ ਹੈ।"</string>
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"ਤੁਸੀਂ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨਿੱਜੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫ਼ਾਈਲ ਦਾ ਪ੍ਰਬੰਧਨ <xliff:g id="ORGANIZATION">%1$s</xliff:g> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਇਹ ਪ੍ਰੋਫ਼ਾਈਲ <xliff:g id="APPLICATION">%2$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੈ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਕਾਰਜ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
- <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"ਤੁਹਾਡੀ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਦਾ ਪ੍ਰਬੰਧਨ <xliff:g id="ORGANIZATION">%1$s</xliff:g> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਪ੍ਰੋਫਾਈਲ <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤੀ ਗਈ ਹੈ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਕਾਰਜ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।\n\nਤੁਸੀਂ <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> ਨਾਲ ਵੀ ਕਨੈਕਟ ਹੋਂ, ਜੋ ਤੁਹਾਡੀ ਨਿੱਜੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string>
+ <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਦਾ ਪ੍ਰਬੰਧਨ <xliff:g id="ORGANIZATION">%1$s</xliff:g> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਪ੍ਰੋਫਾਈਲ <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ ਹੈ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਕਾਰਜ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।\n\nਤੁਸੀਂ <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> ਨਾਲ ਵੀ ਕਨੈਕਟ ਹੋਂ, ਜੋ ਤੁਹਾਡੀ ਨਿੱਜੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"ਡੀਵਾਈਸ ਲੌਕ ਰਹੇਗੀ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਮੈਨੂਅਲੀ ਅਨਲੌਕ ਨਹੀਂ ਕਰਦੇ"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"ਤੇਜ਼ੀ ਨਾਲ ਸੂਚਨਾਵਾਂ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"ਅਨਲੌਕ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਉਹਨਾਂ ਨੂੰ ਦੇਖੋ"</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"ਸਭ ਸ਼੍ਰੇਣੀਆਂ"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ਹੋਰ ਸੈਟਿੰਗਾਂ"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਕਰੋ: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"ਹੋ ਗਿਆ"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"ਸੂਚਨਾ ਕੰਟਰੋਲ"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ਬੰਦ ਹੈ"</string>
<string name="bt_is_off" msgid="2640685272289706392">"ਬਲੂਟੁੱਥ ਬੰਦ ਹੈ"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"\'ਮੈਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਬੰਦ ਹੈ"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"ਸਵੈਚਲਿਤ ਨਿਯਮ ਦੁਆਰਾ \'ਮੈਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਚਾਲੂ ਕੀਤਾ ਗਿਆ (<xliff:g id="ID_1">%s</xliff:g>)। ਵਰਤਮਾਨ ਸੈਟਿੰਗਾਂ ਰੱਖੀਏ?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"ਐਪ ਵੱਲੋਂ \'ਮੈਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਚਾਲੂ ਕੀਤਾ ਗਿਆ (<xliff:g id="ID_1">%s</xliff:g>)। ਵਰਤਮਾਨ ਸੈਟਿੰਗਾਂ ਰੱਖੀਏ?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"ਸਵੈਚਲਿਤ ਨਿਯਮ ਜਾਂ ਐਪ ਵੱਲੋਂ \'ਮੈਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਚਾਲੂ ਕੀਤਾ ਗਿਆ। ਵਰਤਮਾਨ ਸੈਟਿੰਗਾਂ ਰੱਖੀਏ?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> ਤੱਕ"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"ਰੱਖੋ"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"ਬਦਲੋ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 96eeb6a..8b9ee0b 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -166,7 +166,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Ładuję baterię, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procent."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Ustawienia systemu."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Powiadomienia."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Kontener przepełnienia powiadomień"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Zobacz wszystkie powiadomienia"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Usuń powiadomienie."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS włączony."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Pobieranie danych GPS."</string>
@@ -568,8 +568,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Wszystkie kategorie"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Więcej ustawień"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Dostosuj: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotowe"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"sterowanie powiadomieniami"</string>
@@ -751,9 +750,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi jest wyłączone"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth jest wyłączony"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Tryb Nie przeszkadzać jest wyłączony"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Tryb Nie przeszkadzać został włączony przez regułę automatyczną (<xliff:g id="ID_1">%s</xliff:g>). Zachować obecne ustawienia?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Tryb Nie przeszkadzać został włączony przez aplikację (<xliff:g id="ID_1">%s</xliff:g>). Zachować obecne ustawienia?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Tryb Nie przeszkadzać został włączony przez regułę automatyczną lub aplikację. Zachować obecne ustawienia?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Do: <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Zachowaj"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Zastąp"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 4ec9a0e..45e2fda 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -166,7 +166,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Configurações do sistema"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificações."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Contêiner flutuante de notificações"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Ver todas as notificações"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Limpar notificação."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ativado."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Aquisição de GPS."</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Todas as categorias"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mais configurações"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Personalizar: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> do <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"controles de notificação"</string>
@@ -745,9 +744,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"O Wi-Fi está desativado"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desativado"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"O recurso Não perturbe está desativado"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"O recurso Não perturbe foi ativado por uma regra automática (<xliff:g id="ID_1">%s</xliff:g>). Manter as configurações atuais?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"O recurso Não perturbe foi ativado por um app (<xliff:g id="ID_1">%s</xliff:g>). Manter as configurações atuais?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"O recurso Não perturbe foi ativado por uma regra automática ou app. Manter as configurações atuais?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Até <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Manter"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Substituir"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index e8351f8..741b3d6 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"A bateria está a carregar, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> por cento."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Definições do sistema"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificações."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Contentor de excesso de notificações"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Ver todas as notificações"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Limpar notificações"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ativado."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Adquirir GPS."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Todas as categorias"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mais definições"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Personalizar: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> do <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"controlos de notificação"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desativado"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desativado"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Não incomodar desativado"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Não incomodar foi ativado por uma regra automática (<xliff:g id="ID_1">%s</xliff:g>). Pretende manter as definições atuais?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Não incomodar foi ativado por uma aplicação (<xliff:g id="ID_1">%s</xliff:g>). Pretende manter as definições atuais?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Não incomodar foi ativado por uma regra automática ou uma aplicação. Pretende manter as definições atuais?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Até à(s) <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Manter"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Substituir"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 4ec9a0e..45e2fda 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -166,7 +166,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Configurações do sistema"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificações."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Contêiner flutuante de notificações"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Ver todas as notificações"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Limpar notificação."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ativado."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Aquisição de GPS."</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Todas as categorias"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mais configurações"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Personalizar: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> do <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"controles de notificação"</string>
@@ -745,9 +744,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"O Wi-Fi está desativado"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desativado"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"O recurso Não perturbe está desativado"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"O recurso Não perturbe foi ativado por uma regra automática (<xliff:g id="ID_1">%s</xliff:g>). Manter as configurações atuais?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"O recurso Não perturbe foi ativado por um app (<xliff:g id="ID_1">%s</xliff:g>). Manter as configurações atuais?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"O recurso Não perturbe foi ativado por uma regra automática ou app. Manter as configurações atuais?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Até <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Manter"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Substituir"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 6cdc29c..e7dffee 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -167,7 +167,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Setări de sistem."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificări."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Container pentru surplusul de notificări"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Vedeți toate notificările"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Ștergeți notificarea."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS activat."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Se obține GPS."</string>
@@ -566,8 +566,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Toate categoriile"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mai multe setări"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Personalizați: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Terminat"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"comenzile notificării"</string>
@@ -749,9 +748,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Conexiunea Wi-Fi este dezactivată"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Funcția Bluetooth este dezactivată"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Funcția Nu deranja este dezactivată"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Funcția Nu deranja a fost activată de o regulă automată (<xliff:g id="ID_1">%s</xliff:g>). Păstrați setările actuale?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Funcția Nu deranja a fost activată de o aplicație (<xliff:g id="ID_1">%s</xliff:g>). Păstrați setările actuale?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Funcția Nu deranja a fost activată de o regulă automată sau de o aplicație. Păstrați setările actuale?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Până la <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Păstrați"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Înlocuiți"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 0bcdf7a..75310a3 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -168,7 +168,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Настройки"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Уведомления"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Контейнер всплывающих уведомлений"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Показать все уведомления"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Удалить уведомление"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"Система GPS включена."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Установление связи с GPS."</string>
@@ -570,8 +570,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Все категории"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Другие настройки"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"<xliff:g id="SUB_CATEGORY">%1$s</xliff:g>: настроить"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g>: <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"настройки уведомлений"</string>
@@ -753,9 +752,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Модуль Wi-Fi отключен"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Модуль Bluetooth отключен"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Режим \"Не беспокоить\" отключен"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Режим \"Не беспокоить\" был включен специальным правилом (<xliff:g id="ID_1">%s</xliff:g>). Сохранить текущие настройки?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Режим \"Не беспокоить\" был включен приложением (<xliff:g id="ID_1">%s</xliff:g>). Сохранить текущие настройки?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Режим \"Не беспокоить\" был включен специальным правилом или приложением. Сохранить текущие настройки?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"До <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Сохранить"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Заменить"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 4199123..c71d5a2 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"බැටරිය ආරෝපණය කරමින්, සියයට <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"පද්ධති සැකසීම්."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"දැනුම්දීම්."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"දැනුම් දීම් පිටාර බඳුන"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"සියලු දැනුම්දීම් බලන්න"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"දැනුම්දීම හිස් කරන්න."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS සබල කර ඇත."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS ලබා ගනිමින්."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"සියලු ප්රවර්ග"</string>
<string name="notification_more_settings" msgid="816306283396553571">"තව සැකසීම්"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"අභිමත කරන්න: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"නිමයි"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"දැනුම්දීම් පාලන"</string>
@@ -740,22 +739,16 @@
<string name="instant_apps_message" msgid="8116608994995104836">"ක්ෂණික යෙදුම් ස්ථාපනය කිරීම අවශ්ය නොවේ."</string>
<string name="app_info" msgid="6856026610594615344">"යෙදුම් තොරතුරු"</string>
<string name="mobile_data" msgid="7094582042819250762">"ජංගම දත්ත"</string>
- <!-- no translation found for wifi_is_off (1838559392210456893) -->
+ <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ක්රියා විරහිතයි"</string>
+ <string name="bt_is_off" msgid="2640685272289706392">"බ්ලූටූත් ක්රියා විරහිතයි"</string>
+ <string name="dnd_is_off" msgid="6167780215212497572">"බාධා නොකරන්න ක්රියා විරහිතයි"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
<skip />
- <!-- no translation found for bt_is_off (2640685272289706392) -->
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
<skip />
- <!-- no translation found for dnd_is_off (6167780215212497572) -->
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
<skip />
- <!-- no translation found for qs_dnd_prompt_auto_rule (1570808639425342) -->
- <skip />
- <!-- no translation found for qs_dnd_prompt_app (1131614608680529190) -->
- <skip />
- <!-- no translation found for qs_dnd_prompt_auto_rule_app (3685659782196144067) -->
- <skip />
- <!-- no translation found for qs_dnd_until (3469471136280079874) -->
- <skip />
- <!-- no translation found for qs_dnd_keep (1825009164681928736) -->
- <skip />
- <!-- no translation found for qs_dnd_replace (8019520786644276623) -->
- <skip />
+ <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> දක්වා"</string>
+ <string name="qs_dnd_keep" msgid="1825009164681928736">"තබන්න"</string>
+ <string name="qs_dnd_replace" msgid="8019520786644276623">"ප්රතිස්ථාපනය"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 829226e..59dce6f 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -168,7 +168,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Nastavenia systému."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Upozornenia."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Rozbaľovací kontajner s upozorneniami"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Zobraziť všetky upozornenia"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Vymazať upozornenie."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS je povolené."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Prebieha zameriavanie GPS."</string>
@@ -570,8 +570,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Všetky kategórie"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Ďalšie nastavenia"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Prispôsobiť: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Hotovo"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"ovládacie prvky pre upozornenia"</string>
@@ -753,9 +752,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Pripojenie Wi-Fi je vypnuté"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Rozhranie Bluetooth je vypnuté"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Nastavenie Nerušiť je vypnuté"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Nastavenie Nerušiť bolo zapnuté automatickým pravidlom (<xliff:g id="ID_1">%s</xliff:g>). Chcete ponechať aktuálne nastavenia?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Nastavenie Nerušiť bolo zapnuté aplikáciou (<xliff:g id="ID_1">%s</xliff:g>). Chcete ponechať aktuálne nastavenia?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Nastavenie Nerušiť bolo zapnuté automatickým pravidlom alebo aplikáciou. Chcete ponechať aktuálne nastavenia?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Ponechať"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Nahradiť"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index c661426..53ae44e 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -168,7 +168,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Sistemske nastavitve."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Obvestila."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Prekoračitveni vsebnik za obvestila"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Prikaži vsa obvestila"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Izbriši obvestilo."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS omogočen."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Pridobivanje GPS."</string>
@@ -570,8 +570,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Vse kategorije"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Več nastavitev"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Prilagodi: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Dokončano"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"kontrolniki obvestil"</string>
@@ -753,9 +752,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je izklopljen"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je izklopljen"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Način »ne moti« je izklopljen"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Samodejno pravilo (<xliff:g id="ID_1">%s</xliff:g>) je vklopilo način »ne moti«. Želite obdržati trenutne nastavitve?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Aplikacija (<xliff:g id="ID_1">%s</xliff:g>) je vklopila način »ne moti«. Želite obdržati trenutne nastavitve?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Način »ne moti« je vklopljen zaradi samodejnega pravila ali aplikacije. Želite obdržati trenutne nastavitve?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Obdrži"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Zamenjaj"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index dfbe4ef..12573bc 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Bateria po ngarkohet, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> për qind."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Cilësimet e sistemit."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Njoftimet."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Kontejneri i tejkalimit të njoftimeve"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Shiko të gjitha njoftimet"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Pastro njoftimin."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS-ja është e aktivizuar."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Po siguron GPS-në."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Të gjitha kategoritë"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Cilësime të tjera"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Peresonalizoje: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"U krye"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"kontrollet e njoftimit"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi është joaktiv"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth-i është joaktiv"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Modaliteti \"Mos shqetëso\" është joaktiv"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Modaliteti \"Mos shqetëso\" është aktivizuar nga një rregull automatik (<xliff:g id="ID_1">%s</xliff:g>). Të mbahen cilësimet aktuale?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Modaliteti \"Mos shqetëso\" është aktivizuar nga një aplikacion (<xliff:g id="ID_1">%s</xliff:g>). Të mbahen cilësimet aktuale?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Modaliteti \"Mos shqetëso\" është aktivizuar nga një rregull automatik ose një aplikacion. Të mbahen cilësimet aktuale?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Deri në <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Mbaj"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Zëvendëso"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index f0f228f..664c3084 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -165,7 +165,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Батерија се пуни, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> процената."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Системска подешавања."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Обавештења."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Контејнер преклопног менија за обавештења"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Погледајте сва обавештења"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Обриши обавештење."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS је омогућен."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Учитавање GPS-а."</string>
@@ -564,8 +564,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Све категорије"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Још подешавања"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Прилагодите: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"контроле обавештења"</string>
@@ -747,9 +746,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi је искључен"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth је искључен"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Режим Не узнемиравај је искључен"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Аутоматско правило (<xliff:g id="ID_1">%s</xliff:g>) је укључило режим Не узнемиравај. Желите ли да задржите актуелна подешавања?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Апликација (<xliff:g id="ID_1">%s</xliff:g>) је укључила режим Не узнемиравај. Желите ли да задржите актуелна подешавања?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Аутоматско правило или апликација су укључили режим Не узнемиравај. Желите ли да задржите актуелна подешавања?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"До <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Задржи"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Замени"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 1d19a70..65d0712 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Batteriet laddas, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procent."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Systeminställningar."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Meddelanden."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Spillbehållare för aviseringar"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Visa alla aviseringar"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Ta bort meddelandet."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS aktiverad."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Tar emot GPS."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Alla kategorier"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Fler inställningar"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Anpassa: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Klar"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"inställningar för aviseringar"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi är inaktiverat"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth är inaktiverat"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Stör ej är inaktiverat"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Stör ej aktiverades av en automatisk regel (<xliff:g id="ID_1">%s</xliff:g>). Vill du behålla de nuvarande inställningarna?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Stör ej aktiverades av en app (<xliff:g id="ID_1">%s</xliff:g>). Vill du behålla de nuvarande inställningarna?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Stör ej aktiverades av en automatisk regel eller app. Vill du behålla de nuvarande inställningarna?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Till <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Behåll"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Ersätt"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 3dd253e..1935944 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Betri inachaji, asilimia <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Mipangilio ya mfumo."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Arifa."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Metadata ya arifa za ziada"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Angalia arifa zote"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Futa arifa"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS imewashwa."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Kupata GPS."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Aina Zote"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mipangilio zaidi"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Badilisha upendavyo: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Nimemaliza"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"vidhibiti vya arifa"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi imezimwa"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth imezimwa"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Kipengele cha Usinisumbue kimezimwa"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Kipengele cha Usinisumbue kimewashwa na sheria ya kiotomatiki (<xliff:g id="ID_1">%s</xliff:g>). Ungependa kutumia mipangilio ya sasa?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Kipengele cha Usinisumbue kimewashwa na programu (<xliff:g id="ID_1">%s</xliff:g>). Ungependa kutumia mipangilio ya sasa?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Kipengele cha Usinisumbue kimewashwa na sheria ya kiotomatiki au programu. Ungependa kutumia mipangilio ya sasa?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Hadi <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Usibadilishe"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Badilisha"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 341f757..36d247f 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"பேட்டரி சார்ஜ் செய்யப்படுகிறது, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> சதவீதம்."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"கணினி அமைப்பு."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"அறிவிப்புகள்."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"அறிவிப்பு ஓவர்ஃப்ளோ கண்டெய்னர்"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"எல்லா அறிவிப்புகளையும் காட்டும்"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"அறிவிப்பை அழி."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS இயக்கப்பட்டது."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS பெறப்படுகிறது."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"எல்லா வகைகளும்"</string>
<string name="notification_more_settings" msgid="816306283396553571">"மேலும் அமைப்புகள்"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"தனிப்பயனாக்கு: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"முடிந்தது"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"அறிவிப்புக் கட்டுப்பாடுகள்"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"வைஃபை முடக்கத்தில் உள்ளது"</string>
<string name="bt_is_off" msgid="2640685272289706392">"புளூடூத் முடக்கத்தில் உள்ளது"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"\"தொந்தரவு செய்ய வேண்டாம்\" முடக்கத்தில் உள்ளது"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"\"தொந்தரவு செய்ய வேண்டாம்\" எனும் பயன்முறையை, தானியங்கு விதி (<xliff:g id="ID_1">%s</xliff:g>) இயக்கியுள்ளது. தற்போதைய அமைப்புகளையே வைத்திருக்கவா?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"\"தொந்தரவு செய்ய வேண்டாம்\" எனும் பயன்முறையை, பயன்பாடு (<xliff:g id="ID_1">%s</xliff:g>) இயக்கியுள்ளது. தற்போதைய அமைப்புகளையே வைத்திருக்கவா?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"\"தொந்தரவு செய்ய வேண்டாம்\" எனும் பயன்முறையை, தானியங்கு விதி அல்லது பயன்பாடு இயக்கியுள்ளது. தற்போதைய அமைப்புகளையே வைத்திருக்கவா?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> வரை"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"வைத்திரு"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"மாற்று"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index a6a6fde..766ee06 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"బ్యాటరీ ఛార్జ్ అవుతోంది, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> శాతం."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"సిస్టమ్ సెట్టింగ్లు."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"నోటిఫికేషన్లు."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"అధిక నోటిఫికేషన్ల కంటైనర్"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"అన్ని నోటిఫికేషన్లను చూడండి"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"నోటిఫికేషన్ను క్లియర్ చేయండి."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ప్రారంభించబడింది."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPSని పొందడం."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"అన్ని వర్గాలు"</string>
<string name="notification_more_settings" msgid="816306283396553571">"మరిన్ని సెట్టింగ్లు"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"అనుకూలీకరించండి: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"పూర్తయింది"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"నోటిఫికేషన్ నియంత్రణలు"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ఆఫ్లో ఉంది"</string>
<string name="bt_is_off" msgid="2640685272289706392">"బ్లూటూత్ ఆఫ్లో ఉంది"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"అంతరాయం కలిగించవద్దు ఆఫ్లో ఉంది"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"స్వయంచాలక నియమం (<xliff:g id="ID_1">%s</xliff:g>) ద్వారా అంతరాయం కలిగించవద్దు ఆన్ చేయబడింది. ప్రస్తుత సెట్టింగ్లను కొనసాగించాలా?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"అనువర్తనం (<xliff:g id="ID_1">%s</xliff:g>) ద్వారా అంతరాయం కలిగించవద్దు ఆన్ చేయబడింది. ప్రస్తుత సెట్టింగ్లను కొనసాగించాలా?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"స్వయంచాలక నియమం లేదా అనువర్తనం ద్వారా అంతరాయం కలిగించవద్దు ఆన్ చేయబడింది. ప్రస్తుత సెట్టింగ్లను కొనసాగించాలా?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> వరకు"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"ఉంచు"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"భర్తీ చేయి"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 64e418d..ef281dc 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"กำลังชาร์จแบตเตอรี่ <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> เปอร์เซ็นต์"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"การตั้งค่าระบบ"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"การแจ้งเตือน"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"คอนเทนเนอร์รายการเพิ่มเติมของการแจ้งเตือน"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"ดูการแจ้งเตือนทั้งหมด"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"ล้างการแจ้งเตือน"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"เปิดใช้งาน GPS แล้ว"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"การดึงข้อมูล GPS"</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"ทุกหมวดหมู่"</string>
<string name="notification_more_settings" msgid="816306283396553571">"การตั้งค่าเพิ่มเติม"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"ปรับแต่ง: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"เสร็จสิ้น"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"ส่วนควบคุมการแจ้งเตือน"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ปิดอยู่"</string>
<string name="bt_is_off" msgid="2640685272289706392">"บลูทูธปิดอยู่"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"\"ห้ามรบกวน\" ปิดอยู่"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"มีการเปิด \"ห้ามรบกวน\" โดยกฎอัตโนมัติ (<xliff:g id="ID_1">%s</xliff:g>) ให้คงการตั้งค่าปัจจุบันใช่ไหม"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"มีการเปิด \"ห้ามรบกวน\" โดยแอป (<xliff:g id="ID_1">%s</xliff:g>) ให้คงการตั้งค่าปัจจุบันใช่ไหม"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"มีการเปิด \"ห้ามรบกวน\" โดยกฎอัตโนมัติหรือแอป ให้คงการตั้งค่าปัจจุบันใช่ไหม"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"จนถึง <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"เก็บไว้"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"แทนที่"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 3628675..9a0bad7 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Nagcha-charge ang baterya, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> (na) porsyento."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Mga setting ng system."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Mga Notification."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Container ng pag-overflow ng notification"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Tingnan ang lahat ng notification"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"I-clear ang notification."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"Pinapagana ang GPS."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Kumukuha ng GPS."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Lahat ng Kategorya"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Higit pang mga setting"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"I-customize: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Tapos Na"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"mga kontrol ng notification"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Naka-off ang Wi-Fi"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Naka-off ang Bluetooth"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Naka-off ang Huwag Istorbohin"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Na-on ang Huwag Istorbohin dahil sa isang awtomatikong panuntunan (<xliff:g id="ID_1">%s</xliff:g>). Panatilihin ang mga kasalukuyang setting?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Na-on ang Huwag Istorbohin dahil sa isang app (<xliff:g id="ID_1">%s</xliff:g>). Panatilihin ang mga kasalukuyang setting?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Na-on ang Huwag Istorbohin dahil sa isang awtomatikong panuntunan o app. Panatilihin ang mga kasalukuyang setting?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Hanggang <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Panatilihin"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Palitan"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 4375161..af703c0 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Pil şarj oluyor, yüzde <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Sistem ayarları."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Bildirimler."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Bildirim taşma kapsayıcısı"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Tüm bildirimleri göster"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Bildirimi temizle."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS etkin."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS alınıyor."</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Tüm Kategoriler"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Diğer ayarlar"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Özelleştir: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Bitti"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"Bildirim kontrolleri"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Kablosuz bağlantı kapalı"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth kapalı"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Rahatsız Etmeyin kapalı"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Rahatsız Etmeyin ayarı bir otomatik kural (<xliff:g id="ID_1">%s</xliff:g>) tarafından açıldı. Geçerli ayarlar korunsun mu?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Rahatsız Etmeyin ayarı bir uygulama (<xliff:g id="ID_1">%s</xliff:g>) tarafından açıldı. Geçerli ayarlar korunsun mu?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Rahatsız Etmeyin ayarı bir otomatik kural veya uygulama tarafından açıldı. Geçerli ayarlar korunsun mu?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Bitiş: <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Koru"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Değiştir"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index d999fc6..8edfa59 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -168,7 +168,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Налаштування системи."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Сповіщення."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Додатковий контейнер для сповіщень"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Переглянути всі сповіщення"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Очистити сповіщення."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS увімкнено."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Встановлення зв’язку з GPS."</string>
@@ -570,8 +570,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Усі категорії"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Більше налаштувань"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Налаштувати: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"елементи керування сповіщеннями"</string>
@@ -753,9 +752,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi вимкнено"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth вимкнено"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Режим \"Не турбувати\" вимкнено"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Автоматичне правило ввімкнуло режим \"Не турбувати\" (<xliff:g id="ID_1">%s</xliff:g>). Залишити поточні налаштування?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Додаток увімкнув режим \"Не турбувати\" (<xliff:g id="ID_1">%s</xliff:g>). Залишити поточні налаштування?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Автоматичне правило або додаток увімкнули режим \"Не турбувати\". Залишити поточні налаштування?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"До <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Залишити"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Замінити"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index e612b6b..572f327 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"بیٹری چارجنگ، <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> فیصد۔"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"سسٹم کی ترتیبات۔"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"اطلاعات۔"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"اطلاعاتی اوورفلو کنٹینر"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"تمام اطلاعات دیکھیں"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"اطلاع صاف کریں۔"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS فعال ہے۔"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS حاصل کرنا۔"</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"سبھی زمرے"</string>
<string name="notification_more_settings" msgid="816306283396553571">"مزید ترتیبات"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"حسب ضرورت بنائیں: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"ہوگیا"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"اطلاع کے کنٹرولز"</string>
@@ -740,22 +739,16 @@
<string name="instant_apps_message" msgid="8116608994995104836">"فوری ایپس کو انسٹالیشن کی ضرورت نہیں ہے۔"</string>
<string name="app_info" msgid="6856026610594615344">"ایپ کی معلومات"</string>
<string name="mobile_data" msgid="7094582042819250762">"موبائل ڈیٹا"</string>
- <!-- no translation found for wifi_is_off (1838559392210456893) -->
+ <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi آف ہے"</string>
+ <string name="bt_is_off" msgid="2640685272289706392">"بلوٹوتھ آف ہے"</string>
+ <string name="dnd_is_off" msgid="6167780215212497572">"\'ڈسٹرب نہ کریں\' آف ہے"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
<skip />
- <!-- no translation found for bt_is_off (2640685272289706392) -->
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
<skip />
- <!-- no translation found for dnd_is_off (6167780215212497572) -->
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
<skip />
- <!-- no translation found for qs_dnd_prompt_auto_rule (1570808639425342) -->
- <skip />
- <!-- no translation found for qs_dnd_prompt_app (1131614608680529190) -->
- <skip />
- <!-- no translation found for qs_dnd_prompt_auto_rule_app (3685659782196144067) -->
- <skip />
- <!-- no translation found for qs_dnd_until (3469471136280079874) -->
- <skip />
- <!-- no translation found for qs_dnd_keep (1825009164681928736) -->
- <skip />
- <!-- no translation found for qs_dnd_replace (8019520786644276623) -->
- <skip />
+ <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> تک"</string>
+ <string name="qs_dnd_keep" msgid="1825009164681928736">"رکھیں"</string>
+ <string name="qs_dnd_replace" msgid="8019520786644276623">"بدلیں"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 844ff60..2f0fa7f 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -166,7 +166,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"Tizim sozlamalari."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Eslatmalar."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Qalqib chiquvchi bildirishnomalar konteyneri"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Barcha bildirishnomalarni ko‘rish"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Eslatmalarni tozalash."</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS yoqildi."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS so‘rovi."</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Barcha turkumlar"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Boshqa sozlamalar"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"<xliff:g id="SUB_CATEGORY">%1$s</xliff:g>: sozlash"</string>
<string name="notification_done" msgid="5279426047273930175">"Tayyor"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"bildirishnoma sozlamalari"</string>
@@ -745,9 +744,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi o‘chiq"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth o‘chiq"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Bezovta qilinmasin rejimi o‘chiq"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Bezovta qilinmasin rejimi avtomatik qoida (<xliff:g id="ID_1">%s</xliff:g>) tomonidan yoqilgan. Joriy sozlamalar saqlab qolinsimi?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Bezovta qilinmasin rejimi ilova (<xliff:g id="ID_1">%s</xliff:g>) tomonidan yoqilgan. Joriy sozlamalar saqlab qolinsimi?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Bezovta qilinmasin rejimi ilova yoki avtomatik qoida tomonidan yoqilgan. Joriy sozlamalar saqlab qolinsimi?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> gacha"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Saqlab qolish"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Almashtirish"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index cefd071..e9bc587 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Đang sạc pin, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> phần trăm."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Cài đặt hệ thống"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Thông báo."</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Vùng chứa bổ sung cho thông báo"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Xem tất cả thông báo"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Xóa thông báo"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"Đã bật GPS."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Nhận GPS."</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Tất cả danh mục"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Cài đặt khác"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Tùy chỉnh: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Xong"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"điều khiển thông báo"</string>
@@ -745,9 +744,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi tắt"</string>
<string name="bt_is_off" msgid="2640685272289706392">"Bluetooth tắt"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Không làm phiền tắt"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Không làm phiền đã được một quy tắc tự động (<xliff:g id="ID_1">%s</xliff:g>) bật. Giữ cài đặt hiện tại?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Không làm phiền đã được một ứng dụng (<xliff:g id="ID_1">%s</xliff:g>) bật. Giữ cài đặt hiện tại?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Không làm phiền đã được một quy tắc tự động hoặc ứng dụng bật. Giữ cài đặt hiện tại?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Cho tới <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Giữ"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Thay thế"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 22464a6..a855481 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"正在充电,已完成百分之<xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>。"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"系统设置。"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"通知。"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"通知溢出容器"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"查看所有通知"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"清除通知。"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS已启用。"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"正在获取GPS信号。"</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"所有类别"</string>
<string name="notification_more_settings" msgid="816306283396553571">"更多设置"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"自定义:<xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"完成"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g><xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"通知设置"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"WLAN 已关闭"</string>
<string name="bt_is_off" msgid="2640685272289706392">"蓝牙已关闭"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"“勿扰”模式已关闭"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"有个自动规则(<xliff:g id="ID_1">%s</xliff:g>)已开启“勿扰”模式。要保留当前的设置吗?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"有个应用(<xliff:g id="ID_1">%s</xliff:g>)已开启“勿扰”模式。要保留当前的设置吗?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"有个自动规则或应用已开启“勿扰”模式。要保留当前的设置吗?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"直到<xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"保留"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"替换"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 16101e1..52d7650 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -166,7 +166,7 @@
<skip />
<string name="accessibility_settings_button" msgid="799583911231893380">"系統設定"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"通知。"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"通知溢出容器"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"睇所有通知"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"清除通知。"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS 已啟用。"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"正在取得 GPS 訊號。"</string>
@@ -562,8 +562,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"所有類別"</string>
<string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"自訂:<xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"完成"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"通知控制項"</string>
@@ -745,9 +744,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi 已關閉"</string>
<string name="bt_is_off" msgid="2640685272289706392">"藍牙已關閉"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"「請勿騷擾」已關閉"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"「<xliff:g id="ID_1">%s</xliff:g>」自動規則已開啟「請勿騷擾」。要保留目前的設定嗎?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"「<xliff:g id="ID_1">%s</xliff:g>」應用程式已開啟「請勿騷擾」。要保留目前的設定嗎?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"某個自動規則或應用程式已開啟「請勿騷擾」。要保留目前的設定嗎?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"直至<xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"保留"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"取代"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index e0a4b57..cd3eb55 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"充電中,已完成百分之 <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>。"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"系統設定"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"通知。"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"通知溢位容器"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"查看所有通知"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"清除通知。"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS 已啟用。"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"正在取得 GPS 訊號。"</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"所有類別"</string>
<string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"自訂:<xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"完成"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"通知控制項"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi 已關閉"</string>
<string name="bt_is_off" msgid="2640685272289706392">"藍牙已關閉"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"零打擾模式已關閉"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"「<xliff:g id="ID_1">%s</xliff:g>」自動規則已將零打擾模式開啟。要保留目前的設定嗎?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"「<xliff:g id="ID_1">%s</xliff:g>」應用程式已將零打擾模式開啟。要保留目前的設定嗎?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"某個自動規則或應用程式已將零打擾模式開啟。要保留目前的設定嗎?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"直到 <xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"保留"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"取代"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index e9968eb..4914477 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Ibhethri liyashaja, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> iphesenti."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Izilungiselelo zesistimu"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Izaziso"</string>
- <string name="notification_shelf_content_description" msgid="5511922384591583913">"Isiqukathi sokugeleza kwesaziso"</string>
+ <string name="accessibility_overflow_action" msgid="5681882033274783311">"Bona zonke izaziso"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Sula isaziso"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"i-GPS inikwe amandla"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"i-GPS iyafuna"</string>
@@ -560,8 +560,7 @@
</plurals>
<string name="notification_all_categories" msgid="5407190218055113282">"Zonke izigaba"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Izilungiselelo eziningi"</string>
- <!-- no translation found for notification_app_settings (3743278649182392015) -->
- <skip />
+ <string name="notification_app_settings" msgid="3743278649182392015">"Enza ngendlela oyifisayo: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
<string name="notification_done" msgid="5279426047273930175">"Kwenziwe"</string>
<string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="notification_menu_gear_description" msgid="2204480013726775108">"izilawuli zesaziso"</string>
@@ -743,9 +742,12 @@
<string name="wifi_is_off" msgid="1838559392210456893">"I-Wi-Fi ivaliwe"</string>
<string name="bt_is_off" msgid="2640685272289706392">"I-Bluetooth ivaliwe"</string>
<string name="dnd_is_off" msgid="6167780215212497572">"Ungaphazamisi kuvaliwe"</string>
- <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Ungaphazamisi kuvulwe umthetho wokuzenzakalelayo (<xliff:g id="ID_1">%s</xliff:g>). Gcina izilungiselelo zamanje?"</string>
- <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Ungaphazamisi kuvulwe uhlelo lokusebenza (<xliff:g id="ID_1">%s</xliff:g>). Gcina izilungiselelo zamanje?"</string>
- <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Ungaphazamisi kuvulwe umthetho ozenzakalelayo noma uhlelo lokusebenza. Gcina izilungiselelo zamanje?"</string>
+ <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+ <skip />
+ <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+ <skip />
<string name="qs_dnd_until" msgid="3469471136280079874">"Kuze kube-<xliff:g id="ID_1">%s</xliff:g>"</string>
<string name="qs_dnd_keep" msgid="1825009164681928736">"Gcina"</string>
<string name="qs_dnd_replace" msgid="8019520786644276623">"Buyisela"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index f15475c..e9d6fec 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -332,4 +332,7 @@
<!-- Whether or the notifications can be shown and dismissed with a drag. -->
<bool name="config_enableNotificationShadeDrag">true</bool>
+ <!-- Whether to show activity indicators in the status bar -->
+ <bool name="config_showActivity">false</bool>
+
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ac4bdfc..6d8a077 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -218,8 +218,8 @@
<!-- The size of the gesture span needed to activate the "pull" notification expansion -->
<dimen name="pull_span_min">25dp</dimen>
- <dimen name="qs_tile_height">88dp</dimen>
- <dimen name="qs_tile_margin">28dp</dimen>
+ <dimen name="qs_tile_height">106dp</dimen>
+ <dimen name="qs_tile_margin">19dp</dimen>
<dimen name="qs_tile_margin_top">16dp</dimen>
<dimen name="qs_quick_tile_size">48dp</dimen>
<dimen name="qs_quick_tile_padding">12dp</dimen>
@@ -563,6 +563,10 @@
<dimen name="screen_pinning_request_button_width">84dp</dimen>
<!-- Screen pinning request padding on top of inner circle -->
<dimen name="screen_pinning_request_inner_padding">14dp</dimen>
+ <!-- Screen pinning request seascape negative padding -->
+ <dimen name="screen_pinning_request_seascape_padding_negative">-18dp</dimen>
+ <!-- Screen pinning request seascape button offset -->
+ <dimen name="screen_pinning_request_seascape_button_offset">-4dp</dimen>
<!-- Screen pinning request padding on top of icons -->
<dimen name="screen_pinning_request_nav_icon_padding">18dp</dimen>
<!-- Screen pinning request padding on side of icons
@@ -734,7 +738,7 @@
<dimen name="pip_dismiss_gradient_height">196dp</dimen>
<!-- The bottom margin of the PIP drag to dismiss info text shown when moving a PIP. -->
- <dimen name="pip_dismiss_text_bottom_margin">36dp</dimen>
+ <dimen name="pip_dismiss_text_bottom_margin">24dp</dimen>
<!-- The shortest-edge size of the expanded PiP. -->
<dimen name="pip_expanded_shortest_edge_size">160dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7bd9526..eeb28c8 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1895,6 +1895,13 @@
<!-- Tuner string -->
<string name="default_theme" translatable="false">Default</string>
+ <!-- Title for notification & dialog that the user's phone last shut down because it got too hot. [CHAR LIMIT=30] -->
+ <string name="thermal_shutdown_title">Phone turned off due to heat</string>
+ <!-- Message body for notification that user's phone last shut down because it got too hot. [CHAR LIMIT=100] -->
+ <string name="thermal_shutdown_message">Your phone is now running normally</string>
+ <!-- Text body for dialog alerting user that their phone last shut down bewcause it got too hot. [CHAR LIMIT=300] -->
+ <string name="thermal_shutdown_dialog_message">Your phone was too hot, so it turned off to cool down. Your phone is now running normally.\n\nYour phone may get too hot if you:\n\t• Use resource-intensive apps (such as gaming, video, or navigation apps)\n\t• Download or upload large files\n\t• Use your phone in high temperatures</string>
+
<!-- Title for notification (and dialog) that user's phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=30] -->
<string name="high_temp_title">Phone is getting warm</string>
<!-- Message body for notification that user's phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=100] -->
@@ -1975,13 +1982,13 @@
<string name="dnd_is_off">Do Not Disturb is off</string>
<!-- Prompt for when Do not disturb is on from automatic rule in QS [CHAR LIMIT=NONE] -->
- <string name="qs_dnd_prompt_auto_rule">Do Not Disturb was turned on by an automatic rule (<xliff:g name="rule">%s</xliff:g>). Keep current settings?</string>
+ <string name="qs_dnd_prompt_auto_rule">Do Not Disturb was turned on by an automatic rule (<xliff:g name="rule">%s</xliff:g>).</string>
<!-- Prompt for when Do not disturb is on from app in QS [CHAR LIMIT=NONE] -->
- <string name="qs_dnd_prompt_app">Do Not Disturb was turned on by an app (<xliff:g name="app">%s</xliff:g>). Keep current settings?</string>
+ <string name="qs_dnd_prompt_app">Do Not Disturb was turned on by an app (<xliff:g name="app">%s</xliff:g>).</string>
<!-- Prompt for when Do not disturb is on from automatic rule or app in QS [CHAR LIMIT=NONE] -->
- <string name="qs_dnd_prompt_auto_rule_app">Do Not Disturb was turned on by an automatic rule or app. Keep current settings?</string>
+ <string name="qs_dnd_prompt_auto_rule_app">Do Not Disturb was turned on by an automatic rule or app.</string>
<!-- Description of Do Not Disturb option in QS that ends at the specified time[CHAR LIMIT=20] -->
<string name="qs_dnd_until">Until <xliff:g name="time">%s</xliff:g></string>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 908fb20..a685c79 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -145,7 +145,7 @@
<com.android.systemui.tuner.TunerSwitch
android:key="doze_sensors_wake_up_fully"
android:title="@string/tuner_doze_sensors_wake_up_fully"
- sysui:defValue="true" />
+ sysui:defValue="false" />
</PreferenceScreen>
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java b/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java
index 0a89d9b..e98ef06 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java
@@ -37,8 +37,8 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mCarrierText = (CarrierText) findViewById(R.id.carrier_text);
- mEmergencyButton = (EmergencyButton) findViewById(R.id.emergency_call_button);
+ mCarrierText = findViewById(R.id.carrier_text);
+ mEmergencyButton = findViewById(R.id.emergency_call_button);
// The emergency button overlaps the carrier text, only noticeable when highlighted.
// So temporarily hide the carrier text while the emergency button is pressed.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 5aa673b..abc3b94 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -98,7 +98,7 @@
mSecurityMessageDisplay = KeyguardMessageArea.findSecurityMessageDisplay(this);
mEcaView = findViewById(R.id.keyguard_selector_fade_container);
- EmergencyButton button = (EmergencyButton) findViewById(R.id.emergency_call_button);
+ EmergencyButton button = findViewById(R.id.emergency_call_button);
if (button != null) {
button.setCallback(this);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
index dd5544d..27a3f7d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
@@ -143,7 +143,7 @@
@Override
protected void onFinishInflate() {
mSecurityContainer =
- (KeyguardSecurityContainer) findViewById(R.id.keyguard_security_container);
+ findViewById(R.id.keyguard_security_container);
mLockPatternUtils = new LockPatternUtils(mContext);
mSecurityContainer.setLockPatternUtils(mLockPatternUtils);
mSecurityContainer.setSecurityCallback(this);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
index 590d8d5..c1cff9e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
@@ -79,11 +79,11 @@
protected void onFinishInflate() {
super.onFinishInflate();
- mContainer = (ViewGroup) findViewById(R.id.container);
- mRow0 = (ViewGroup) findViewById(R.id.row0);
- mRow1 = (ViewGroup) findViewById(R.id.row1);
- mRow2 = (ViewGroup) findViewById(R.id.row2);
- mRow3 = (ViewGroup) findViewById(R.id.row3);
+ mContainer = findViewById(R.id.container);
+ mRow0 = findViewById(R.id.row0);
+ mRow1 = findViewById(R.id.row1);
+ mRow2 = findViewById(R.id.row2);
+ mRow3 = findViewById(R.id.row3);
mDivider = findViewById(R.id.divider);
mViews = new View[][]{
new View[]{
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index d49ff97..b6184a8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -174,7 +174,7 @@
mImm = (InputMethodManager) getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
- mPasswordEntry = (TextView) findViewById(getPasswordTextViewId());
+ mPasswordEntry = findViewById(getPasswordTextViewId());
mPasswordEntryDisabler = new TextViewInputDisabler(mPasswordEntry);
mPasswordEntry.setKeyListener(TextKeyListener.getInstance());
mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index c2b57ff..3c9a6b9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -140,7 +140,7 @@
mLockPatternUtils = mLockPatternUtils == null
? new LockPatternUtils(mContext) : mLockPatternUtils;
- mLockPatternView = (LockPatternView) findViewById(R.id.lockPatternView);
+ mLockPatternView = findViewById(R.id.lockPatternView);
mLockPatternView.setSaveEnabled(false);
mLockPatternView.setOnPatternListener(new UnlockPatternListener());
@@ -150,9 +150,9 @@
mSecurityMessageDisplay =
(KeyguardMessageArea) KeyguardMessageArea.findSecurityMessageDisplay(this);
mEcaView = findViewById(R.id.keyguard_selector_fade_container);
- mContainer = (ViewGroup) findViewById(R.id.container);
+ mContainer = findViewById(R.id.container);
- EmergencyButton button = (EmergencyButton) findViewById(R.id.emergency_call_button);
+ EmergencyButton button = findViewById(R.id.emergency_call_button);
if (button != null) {
button.setCallback(this);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 108b466..c04ae68 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -171,7 +171,7 @@
@Override
protected void onFinishInflate() {
- mPasswordEntry = (PasswordTextView) findViewById(getPasswordTextViewId());
+ mPasswordEntry = findViewById(getPasswordTextViewId());
mPasswordEntry.setOnKeyListener(this);
// Set selected property on so the view can send accessibility events.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 8cdb906..b447979 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -160,7 +160,7 @@
}
protected void onFinishInflate() {
- mSecurityViewFlipper = (KeyguardSecurityViewFlipper) findViewById(R.id.view_flipper);
+ mSecurityViewFlipper = findViewById(R.id.view_flipper);
mSecurityViewFlipper.setLockPatternUtils(mLockPatternUtils);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 839d3ce..0cf8900 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -144,7 +144,7 @@
if (mEcaView instanceof EmergencyCarrierArea) {
((EmergencyCarrierArea) mEcaView).setCarrierTextVisible(true);
}
- mSimImageView = (ImageView) findViewById(R.id.keyguard_sim);
+ mSimImageView = findViewById(R.id.keyguard_sim);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 3871448..fb3cee7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -187,7 +187,7 @@
if (mEcaView instanceof EmergencyCarrierArea) {
((EmergencyCarrierArea) mEcaView).setCarrierTextVisible(true);
}
- mSimImageView = (ImageView) findViewById(R.id.keyguard_sim);
+ mSimImageView = findViewById(R.id.keyguard_sim);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index b2b0ee4..162faa5 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -115,14 +115,14 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mClockContainer = (ViewGroup) findViewById(R.id.keyguard_clock_container);
- mAlarmStatusView = (TextView) findViewById(R.id.alarm_status);
- mDateView = (TextClock) findViewById(R.id.date_view);
- mClockView = (TextClock) findViewById(R.id.clock_view);
+ mClockContainer = findViewById(R.id.keyguard_clock_container);
+ mAlarmStatusView = findViewById(R.id.alarm_status);
+ mDateView = findViewById(R.id.date_view);
+ mClockView = findViewById(R.id.clock_view);
mDateView.setShowCurrentUserTime(true);
mClockView.setShowCurrentUserTime(true);
- mOwnerInfo = (TextView) findViewById(R.id.owner_info);
- mBatteryDoze = (ChargingView) findViewById(R.id.battery_doze);
+ mOwnerInfo = findViewById(R.id.owner_info);
+ mBatteryDoze = findViewById(R.id.battery_doze);
mVisibleInDoze = new View[]{mBatteryDoze, mClockView};
boolean shouldMarquee = KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive();
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index d57e88c..911ef24 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -149,7 +149,7 @@
@Override
public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
mDrawable.setBatteryLevel(level);
- mDrawable.setPluggedIn(pluggedIn);
+ mDrawable.setCharging(pluggedIn);
mLevel = level;
updatePercentText();
setContentDescription(
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 429e859..f4d4a9f 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -42,6 +42,7 @@
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
import com.android.systemui.statusbar.policy.AccessibilityController;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryControllerImpl;
import com.android.systemui.statusbar.policy.BluetoothController;
@@ -260,6 +261,9 @@
mProviders.put(MetricsLogger.class, () -> new MetricsLogger());
+ mProviders.put(AccessibilityManagerWrapper.class,
+ () -> new AccessibilityManagerWrapper(mContext));
+
// Put all dependencies above here so the factory can override them if it wants.
SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
}
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 0b0ea720..7fed3e8 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -31,6 +31,7 @@
import android.view.View;
import android.view.ViewConfiguration;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -130,6 +131,11 @@
}
};
+ @VisibleForTesting
+ ObjectAnimator getScaleAnimation() {
+ return mScaleAnimation;
+ }
+
private class ViewScaler {
ExpandableView mView;
@@ -176,7 +182,8 @@
mFlingAnimationUtils = new FlingAnimationUtils(context, EXPAND_DURATION);
}
- private void updateExpansion() {
+ @VisibleForTesting
+ void updateExpansion() {
if (DEBUG_SCALE) Log.v(TAG, "updateExpansion()");
// are we scaling or dragging?
float span = mSGD.getCurrentSpan() - mInitialTouchSpan;
@@ -500,7 +507,8 @@
/**
* @return True if the view is expandable, false otherwise.
*/
- private boolean startExpanding(ExpandableView v, int expandType) {
+ @VisibleForTesting
+ boolean startExpanding(ExpandableView v, int expandType) {
if (!(v instanceof ExpandableNotificationRow)) {
return false;
}
@@ -535,7 +543,8 @@
* state
* @param velocity the velocity this was expanded/ collapsed with
*/
- private void finishExpanding(boolean forceAbort, float velocity) {
+ @VisibleForTesting
+ void finishExpanding(boolean forceAbort, float velocity) {
if (!mExpanding) return;
if (DEBUG) Log.d(TAG, "scale in finishing on view: " + mResizedView);
@@ -571,7 +580,9 @@
public void onAnimationEnd(Animator animation) {
if (!mCancelled) {
mCallback.setUserExpandedChild(scaledView, expand);
- mScaler.setView(null);
+ if (!mExpanding) {
+ mScaler.setView(null);
+ }
} else {
mCallback.setExpansionCancelled(scaledView);
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index fbb075a..0eb469f 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -158,6 +158,7 @@
* the main process.
* <p>This method must only be called from the main thread.</p>
*/
+
public void startServicesIfNeeded() {
startServicesIfNeeded(SERVICES);
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java
index abcf27d..1d032e8 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java
@@ -137,7 +137,7 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mLogo = (ImageView) findViewById(R.id.search_logo);
+ mLogo = findViewById(R.id.search_logo);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java b/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
index cdda45f..f06ea45 100644
--- a/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
@@ -30,8 +30,8 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mland);
- mLand = (MLand) findViewById(R.id.world);
- mLand.setScoreFieldHolder((ViewGroup) findViewById(R.id.scores));
+ mLand = findViewById(R.id.world);
+ mLand.setScoreFieldHolder(findViewById(R.id.scores));
final View welcome = findViewById(R.id.welcome);
mLand.setSplash(welcome);
final int numControllers = mLand.getGameControllers().size();
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 2b6ea15..8ac97f3 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -35,6 +35,7 @@
import com.android.settingslib.applications.InterestingConfigChanges;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.Plugin;
+import com.android.systemui.util.leak.LeakDetector;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -77,6 +78,11 @@
public void onFragmentViewDestroyed(FragmentManager fm, Fragment f) {
FragmentHostManager.this.onFragmentViewDestroyed(f);
}
+
+ @Override
+ public void onFragmentDestroyed(FragmentManager fm, Fragment f) {
+ Dependency.get(LeakDetector.class).trackGarbage(f);
+ }
};
mFragments.getFragmentManager().registerFragmentLifecycleCallbacks(mLifecycleCallbacks,
true);
@@ -157,7 +163,7 @@
// TODO: Do something?
}
- private View findViewById(int id) {
+ private <T extends View> T findViewById(int id) {
return mRootView.findViewById(id);
}
@@ -245,7 +251,7 @@
@Override
@Nullable
- public View onFindViewById(int id) {
+ public <T extends View> T onFindViewById(int id) {
return FragmentHostManager.this.findViewById(id);
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 114a594..c565373 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -86,6 +86,7 @@
ComponentName topPipActivity = PipUtils.getTopPinnedActivity(mContext,
mActivityManager);
+ mMenuController.hideMenu();
mNotificationController.onActivityUnpinned(topPipActivity);
SystemServicesProxy.getInstance(mContext).setPipVisibility(topPipActivity != null);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 4e7cf72..9c4f16b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -21,11 +21,16 @@
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_CONTROLLER_MESSENGER;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_DISMISS_FRACTION;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MOVEMENT_BOUNDS;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_SHOW_MENU;
+import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MENU_STATE;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_STACK_BOUNDS;
+import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_NONE;
+import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE;
+import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_FULL;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
@@ -85,7 +90,7 @@
private static final float DISABLED_ACTION_ALPHA = 0.54f;
- private boolean mMenuVisible;
+ private int mMenuState;
private boolean mAllowMenuTimeout = true;
private final List<RemoteAction> mActions = new ArrayList<>();
@@ -98,7 +103,8 @@
private ImageView mExpandButton;
private int mBetweenActionPaddingLand;
- private ObjectAnimator mMenuContainerAnimator;
+ private AnimatorSet mMenuContainerAnimator;
+
private ValueAnimator.AnimatorUpdateListener mMenuBgUpdateListener =
new ValueAnimator.AnimatorUpdateListener() {
@Override
@@ -119,7 +125,8 @@
switch (msg.what) {
case MESSAGE_SHOW_MENU: {
final Bundle data = (Bundle) msg.obj;
- showMenu(data.getParcelable(EXTRA_STACK_BOUNDS),
+ showMenu(data.getInt(EXTRA_MENU_STATE),
+ data.getParcelable(EXTRA_STACK_BOUNDS),
data.getParcelable(EXTRA_MOVEMENT_BOUNDS),
data.getBoolean(EXTRA_ALLOW_TIMEOUT));
break;
@@ -170,16 +177,21 @@
mMenuContainer = findViewById(R.id.menu_container);
mMenuContainer.setAlpha(0);
mMenuContainer.setOnClickListener((v) -> {
- expandPip();
+ if (mMenuState == MENU_STATE_CLOSE) {
+ showPipMenu();
+ } else {
+ expandPip();
+ }
});
mDismissButton = findViewById(R.id.dismiss);
+ mDismissButton.setAlpha(0);
mDismissButton.setOnClickListener((v) -> {
dismissPip();
});
- mActionsGroup = (LinearLayout) findViewById(R.id.actions_group);
+ mActionsGroup = findViewById(R.id.actions_group);
mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
R.dimen.pip_between_action_padding_land);
- mExpandButton = (ImageView) findViewById(R.id.expand_button);
+ mExpandButton = findViewById(R.id.expand_button);
updateFromIntent(getIntent());
setTitle(R.string.pip_menu_title);
@@ -236,7 +248,8 @@
break;
case MotionEvent.ACTION_MOVE:
mDownDelta.set(ev.getX() - mDownPosition.x, ev.getY() - mDownPosition.y);
- if (mDownDelta.length() > mViewConfig.getScaledTouchSlop() && mMenuVisible) {
+ if (mDownDelta.length() > mViewConfig.getScaledTouchSlop()
+ && mMenuState != MENU_STATE_NONE) {
// Restore the input consumer and let that drive the movement of this menu
notifyRegisterInputConsumer();
cancelDelayedFinish();
@@ -259,17 +272,28 @@
// Do nothing
}
- private void showMenu(Rect stackBounds, Rect movementBounds, boolean allowMenuTimeout) {
+ private void showMenu(int menuState, Rect stackBounds, Rect movementBounds,
+ boolean allowMenuTimeout) {
mAllowMenuTimeout = allowMenuTimeout;
- if (!mMenuVisible) {
+ if (mMenuState != menuState) {
+ cancelDelayedFinish();
updateActionViews(stackBounds);
if (mMenuContainerAnimator != null) {
mMenuContainerAnimator.cancel();
}
- notifyMenuVisibility(true);
+ notifyMenuStateChange(menuState);
updateExpandButtonFromBounds(stackBounds, movementBounds);
- mMenuContainerAnimator = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
+ mMenuContainerAnimator = new AnimatorSet();
+ ObjectAnimator menuAnim = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
mMenuContainer.getAlpha(), 1f);
+ menuAnim.addUpdateListener(mMenuBgUpdateListener);
+ ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
+ mDismissButton.getAlpha(), 1f);
+ if (menuState == MENU_STATE_FULL) {
+ mMenuContainerAnimator.playTogether(menuAnim, dismissAnim);
+ } else {
+ mMenuContainerAnimator.play(dismissAnim);
+ }
mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN);
mMenuContainerAnimator.setDuration(MENU_FADE_DURATION);
if (allowMenuTimeout) {
@@ -280,7 +304,6 @@
}
});
}
- mMenuContainerAnimator.addUpdateListener(mMenuBgUpdateListener);
mMenuContainerAnimator.start();
} else {
// If we are already visible, then just start the delayed dismiss and unregister any
@@ -297,13 +320,18 @@
}
private void hideMenu(final Runnable animationFinishedRunnable, boolean notifyMenuVisibility) {
- if (mMenuVisible) {
+ if (mMenuState != MENU_STATE_NONE) {
cancelDelayedFinish();
if (notifyMenuVisibility) {
- notifyMenuVisibility(false);
+ notifyMenuStateChange(MENU_STATE_NONE);
}
- mMenuContainerAnimator = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
+ mMenuContainerAnimator = new AnimatorSet();
+ ObjectAnimator menuAnim = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
mMenuContainer.getAlpha(), 0f);
+ menuAnim.addUpdateListener(mMenuBgUpdateListener);
+ ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
+ mDismissButton.getAlpha(), 0f);
+ mMenuContainerAnimator.playTogether(menuAnim, dismissAnim);
mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT);
mMenuContainerAnimator.setDuration(MENU_FADE_DURATION);
mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
@@ -312,11 +340,9 @@
if (animationFinishedRunnable != null) {
animationFinishedRunnable.run();
}
-
finish();
}
});
- mMenuContainerAnimator.addUpdateListener(mMenuBgUpdateListener);
mMenuContainerAnimator.start();
} else {
// If the menu is not visible, just finish now
@@ -332,11 +358,12 @@
mActions.clear();
mActions.addAll(actions.getList());
}
- if (intent.getBooleanExtra(EXTRA_SHOW_MENU, false)) {
+ final int menuState = intent.getIntExtra(EXTRA_MENU_STATE, MENU_STATE_NONE);
+ if (menuState != MENU_STATE_NONE) {
Rect stackBounds = intent.getParcelableExtra(EXTRA_STACK_BOUNDS);
Rect movementBounds = intent.getParcelableExtra(EXTRA_MOVEMENT_BOUNDS);
boolean allowMenuTimeout = intent.getBooleanExtra(EXTRA_ALLOW_TIMEOUT, true);
- showMenu(stackBounds, movementBounds, allowMenuTimeout);
+ showMenu(menuState, stackBounds, movementBounds, allowMenuTimeout);
}
}
@@ -365,14 +392,14 @@
}
private void updateActionViews(Rect stackBounds) {
- ViewGroup expandContainer = (ViewGroup) findViewById(R.id.expand_container);
- ViewGroup actionsContainer = (ViewGroup) findViewById(R.id.actions_container);
+ ViewGroup expandContainer = findViewById(R.id.expand_container);
+ ViewGroup actionsContainer = findViewById(R.id.actions_container);
actionsContainer.setOnTouchListener((v, ev) -> {
// Do nothing, prevent click through to parent
return true;
});
- if (mActions.isEmpty()) {
+ if (mActions.isEmpty() || mMenuState == MENU_STATE_CLOSE) {
actionsContainer.setVisibility(View.INVISIBLE);
} else {
actionsContainer.setVisibility(View.VISIBLE);
@@ -427,12 +454,17 @@
private void updateDismissFraction(float fraction) {
int alpha;
- if (mMenuVisible) {
- mMenuContainer.setAlpha(1 - fraction);
+ final float menuAlpha = 1 - fraction;
+ if (mMenuState == MENU_STATE_FULL) {
+ mMenuContainer.setAlpha(menuAlpha);
+ mDismissButton.setAlpha(menuAlpha);
final float interpolatedAlpha =
- MENU_BACKGROUND_ALPHA * (1.0f - fraction) + DISMISS_BACKGROUND_ALPHA * fraction;
+ MENU_BACKGROUND_ALPHA * menuAlpha + DISMISS_BACKGROUND_ALPHA * fraction;
alpha = (int) (interpolatedAlpha * 255);
} else {
+ if (mMenuState == MENU_STATE_CLOSE) {
+ mDismissButton.setAlpha(menuAlpha);
+ }
alpha = (int) (fraction * DISMISS_BACKGROUND_ALPHA * 255);
}
mBackgroundDrawable.setAlpha(alpha);
@@ -450,11 +482,11 @@
sendMessage(m, "Could not notify controller to unregister input consumer");
}
- private void notifyMenuVisibility(boolean visible) {
- mMenuVisible = visible;
+ private void notifyMenuStateChange(int menuState) {
+ mMenuState = menuState;
Message m = Message.obtain();
- m.what = PipMenuActivityController.MESSAGE_MENU_VISIBILITY_CHANGED;
- m.arg1 = visible ? 1 : 0;
+ m.what = PipMenuActivityController.MESSAGE_MENU_STATE_CHANGED;
+ m.arg1 = menuState;
sendMessage(m, "Could not notify controller of PIP menu visibility");
}
@@ -481,6 +513,12 @@
}, false /* notifyMenuVisibility */);
}
+ private void showPipMenu() {
+ Message m = Message.obtain();
+ m.what = PipMenuActivityController.MESSAGE_SHOW_MENU;
+ sendMessage(m, "Could not notify controller to show PIP menu");
+ }
+
private void notifyActivityCallback(Messenger callback) {
Message m = Message.obtain();
m.what = PipMenuActivityController.MESSAGE_UPDATE_ACTIVITY_CALLBACK;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 875fb14..c41f898 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -57,16 +57,21 @@
public static final String EXTRA_STACK_BOUNDS = "stack_bounds";
public static final String EXTRA_MOVEMENT_BOUNDS = "movement_bounds";
public static final String EXTRA_ALLOW_TIMEOUT = "allow_timeout";
- public static final String EXTRA_SHOW_MENU = "show_menu";
public static final String EXTRA_DISMISS_FRACTION = "dismiss_fraction";
+ public static final String EXTRA_MENU_STATE = "menu_state";
- public static final int MESSAGE_MENU_VISIBILITY_CHANGED = 100;
+ public static final int MESSAGE_MENU_STATE_CHANGED = 100;
public static final int MESSAGE_EXPAND_PIP = 101;
public static final int MESSAGE_MINIMIZE_PIP = 102;
public static final int MESSAGE_DISMISS_PIP = 103;
public static final int MESSAGE_UPDATE_ACTIVITY_CALLBACK = 104;
public static final int MESSAGE_REGISTER_INPUT_CONSUMER = 105;
public static final int MESSAGE_UNREGISTER_INPUT_CONSUMER = 106;
+ public static final int MESSAGE_SHOW_MENU = 107;
+
+ public static final int MENU_STATE_NONE = 0;
+ public static final int MENU_STATE_CLOSE = 1;
+ public static final int MENU_STATE_FULL = 2;
/**
* A listener interface to receive notification on changes in PIP.
@@ -75,10 +80,10 @@
/**
* Called when the PIP menu visibility changes.
*
- * @param menuVisible whether or not the menu is visible
- * @param resize whether or not to resize the PiP with the visibility change
+ * @param menuState the current state of the menu
+ * @param resize whether or not to resize the PiP with the state change
*/
- void onPipMenuVisibilityChanged(boolean menuVisible, boolean resize);
+ void onPipMenuStateChanged(int menuState, boolean resize);
/**
* Called when the PIP requested to be expanded.
@@ -94,6 +99,11 @@
* Called when the PIP requested to be dismissed.
*/
void onPipDismiss();
+
+ /**
+ * Called when the PIP requested to show the menu.
+ */
+ void onPipShowMenu();
}
private Context mContext;
@@ -104,7 +114,7 @@
private ArrayList<Listener> mListeners = new ArrayList<>();
private ParceledListSlice mAppActions;
private ParceledListSlice mMediaActions;
- private boolean mMenuVisible;
+ private int mMenuState;
// The dismiss fraction update is sent frequently, so use a temporary bundle for the message
private Bundle mTmpDismissFractionData = new Bundle();
@@ -115,16 +125,16 @@
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MESSAGE_MENU_VISIBILITY_CHANGED: {
- boolean visible = msg.arg1 > 0;
- onMenuVisibilityChanged(visible, true /* resize */);
+ case MESSAGE_MENU_STATE_CHANGED: {
+ int menuState = msg.arg1;
+ onMenuStateChanged(menuState, true /* resize */);
break;
}
case MESSAGE_EXPAND_PIP: {
mListeners.forEach(l -> l.onPipExpand());
// Preemptively mark the menu as invisible once we expand the PiP, but don't
// resize as we will be animating the stack
- onMenuVisibilityChanged(false, false /* resize */);
+ onMenuStateChanged(MENU_STATE_NONE, false /* resize */);
break;
}
case MESSAGE_MINIMIZE_PIP: {
@@ -135,7 +145,11 @@
mListeners.forEach(l -> l.onPipDismiss());
// Preemptively mark the menu as invisible once we dismiss the PiP, but don't
// resize as we'll be removing the stack in place
- onMenuVisibilityChanged(false, false /* resize */);
+ onMenuStateChanged(MENU_STATE_NONE, false /* resize */);
+ break;
+ }
+ case MESSAGE_SHOW_MENU: {
+ mListeners.forEach(l -> l.onPipShowMenu());
break;
}
case MESSAGE_REGISTER_INPUT_CONSUMER: {
@@ -151,7 +165,7 @@
mStartActivityRequested = false;
// Mark the menu as invisible once the activity finishes as well
if (mToActivityMessenger == null) {
- onMenuVisibilityChanged(false, true /* resize */);
+ onMenuStateChanged(MENU_STATE_NONE, true /* resize */);
}
break;
}
@@ -176,7 +190,7 @@
}
public void onActivityPinned() {
- if (!mMenuVisible) {
+ if (mMenuState == MENU_STATE_NONE) {
// If the menu is not visible, then re-register the input consumer if it is not already
// registered
mInputConsumerController.registerInputConsumer();
@@ -209,23 +223,25 @@
try {
mToActivityMessenger.send(m);
} catch (RemoteException e) {
- Log.e(TAG, "Could not notify menu to show", e);
+ Log.e(TAG, "Could not notify menu to update dismiss fraction", e);
}
} else if (!mStartActivityRequested) {
- startMenuActivity(null /* stackBounds */, null /* movementBounds */,
- false /* showMenu */, false /* allowMenuTimeout */);
+ startMenuActivity(MENU_STATE_NONE, null /* stackBounds */,
+ null /* movementBounds */, false /* allowMenuTimeout */);
}
}
/**
* Shows the menu activity.
*/
- public void showMenu(Rect stackBounds, Rect movementBounds, boolean allowMenuTimeout) {
+ public void showMenu(int menuState, Rect stackBounds, Rect movementBounds,
+ boolean allowMenuTimeout) {
if (DEBUG) {
Log.d(TAG, "showMenu() hasActivity=" + (mToActivityMessenger != null));
}
if (mToActivityMessenger != null) {
Bundle data = new Bundle();
+ data.putInt(EXTRA_MENU_STATE, menuState);
data.putParcelable(EXTRA_STACK_BOUNDS, stackBounds);
data.putParcelable(EXTRA_MOVEMENT_BOUNDS, movementBounds);
data.putBoolean(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout);
@@ -238,7 +254,7 @@
Log.e(TAG, "Could not notify menu to show", e);
}
} else if (!mStartActivityRequested) {
- startMenuActivity(stackBounds, movementBounds, true /* showMenu */, allowMenuTimeout);
+ startMenuActivity(menuState, stackBounds, movementBounds, allowMenuTimeout);
}
}
@@ -279,10 +295,10 @@
}
/**
- * @return whether the menu is currently visible.
+ * @return the current menu state.
*/
- public boolean isMenuVisible() {
- return mMenuVisible;
+ public int getMenuState() {
+ return mMenuState;
}
/**
@@ -306,7 +322,7 @@
/**
* Starts the menu activity on the top task of the pinned stack.
*/
- private void startMenuActivity(Rect stackBounds, Rect movementBounds, boolean showMenu,
+ private void startMenuActivity(int menuState, Rect stackBounds, Rect movementBounds,
boolean allowMenuTimeout) {
try {
StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
@@ -321,7 +337,7 @@
if (movementBounds != null) {
intent.putExtra(EXTRA_MOVEMENT_BOUNDS, movementBounds);
}
- intent.putExtra(EXTRA_SHOW_MENU, showMenu);
+ intent.putExtra(EXTRA_MENU_STATE, menuState);
intent.putExtra(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout);
ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
options.setLaunchTaskId(
@@ -378,19 +394,19 @@
/**
* Handles changes in menu visibility.
*/
- private void onMenuVisibilityChanged(boolean visible, boolean resize) {
+ private void onMenuStateChanged(int menuState, boolean resize) {
if (DEBUG) {
- Log.d(TAG, "onMenuVisibilityChanged() mMenuVisible=" + mMenuVisible
- + " menuVisible=" + visible + " resize=" + resize);
+ Log.d(TAG, "onMenuStateChanged() mMenuState=" + mMenuState
+ + " menuState=" + menuState + " resize=" + resize);
}
- if (visible) {
- mInputConsumerController.unregisterInputConsumer();
- } else {
+ if (menuState == MENU_STATE_NONE) {
mInputConsumerController.registerInputConsumer();
+ } else {
+ mInputConsumerController.unregisterInputConsumer();
}
- if (visible != mMenuVisible) {
- mListeners.forEach(l -> l.onPipMenuVisibilityChanged(visible, resize));
- if (visible) {
+ if (menuState != mMenuState) {
+ mListeners.forEach(l -> l.onPipMenuStateChanged(menuState, resize));
+ if (menuState == MENU_STATE_FULL) {
// Once visible, start listening for media action changes. This call will trigger
// the menu actions to be updated again.
mMediaController.addListener(mMediaActionListener);
@@ -400,13 +416,13 @@
mMediaController.removeListener(mMediaActionListener);
}
}
- mMenuVisible = visible;
+ mMenuState = menuState;
}
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
- pw.println(innerPrefix + "mMenuVisible=" + mMenuVisible);
+ pw.println(innerPrefix + "mMenuState=" + mMenuState);
pw.println(innerPrefix + "mToActivityMessenger=" + mToActivityMessenger);
pw.println(innerPrefix + "mListeners=" + mListeners.size());
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 161bdac..3f26fdd 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -16,6 +16,10 @@
package com.android.systemui.pip.phone;
+import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_NONE;
+import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE;
+import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_FULL;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
@@ -106,7 +110,7 @@
private boolean mEnableMinimize = false;
// Behaviour states
- private boolean mIsMenuVisible;
+ private int mMenuState;
private boolean mIsMinimized;
private boolean mIsImeShowing;
private int mImeHeight;
@@ -129,8 +133,8 @@
*/
private class PipMenuListener implements PipMenuActivityController.Listener {
@Override
- public void onPipMenuVisibilityChanged(boolean menuVisible, boolean resize) {
- setMenuVisibilityState(menuVisible, resize);
+ public void onPipMenuStateChanged(int menuState, boolean resize) {
+ setMenuState(menuState, resize);
}
@Override
@@ -152,6 +156,12 @@
MetricsLogger.action(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_DISMISSED,
METRIC_VALUE_DISMISSED_BY_TAP);
}
+
+ @Override
+ public void onPipShowMenu() {
+ mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
+ mMovementBounds, true /* allowMenuTimeout */);
+ }
}
public PipTouchHandler(Context context, IActivityManager activityManager,
@@ -193,20 +203,21 @@
public void showPictureInPictureMenu() {
// Only show the menu if the user isn't currently interacting with the PiP
if (!mTouchState.isUserInteracting()) {
- mMenuController.showMenu(mMotionHelper.getBounds(), mMovementBounds,
- false /* allowMenuTimeout */);
+ mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
+ mMovementBounds, false /* allowMenuTimeout */);
}
}
public void onActivityPinned() {
// Reset some states once we are pinned
- if (mIsMenuVisible) {
- mIsMenuVisible = false;
- }
+ mMenuState = MENU_STATE_NONE;
+
if (mIsMinimized) {
setMinimizedStateInternal(false);
}
mDismissViewController.destroyDismissTarget();
+ mMenuController.showMenu(MENU_STATE_CLOSE, mMotionHelper.getBounds(),
+ mMovementBounds, true /* allowMenuTimeout */);
}
public void onPinnedStackAnimationEnded() {
@@ -266,7 +277,7 @@
// touching the screen
} else {
final Rect bounds = new Rect(animatingBounds);
- final Rect toMovementBounds = mIsMenuVisible
+ final Rect toMovementBounds = mMenuState == MENU_STATE_FULL
? expandedMovementBounds
: normalMovementBounds;
if (mIsImeShowing) {
@@ -293,7 +304,7 @@
// above
mNormalMovementBounds = normalMovementBounds;
mExpandedMovementBounds = expandedMovementBounds;
- updateMovementBounds(mIsMenuVisible);
+ updateMovementBounds(mMenuState);
}
private void onRegistrationChanged(boolean isRegistered) {
@@ -303,8 +314,8 @@
}
private void onAccessibilityShowMenu() {
- mMenuController.showMenu(mMotionHelper.getBounds(), mMovementBounds,
- false /* allowMenuTimeout */);
+ mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
+ mMovementBounds, false /* allowMenuTimeout */);
}
private boolean handleTouchEvent(MotionEvent ev) {
@@ -336,7 +347,7 @@
case MotionEvent.ACTION_UP: {
// Update the movement bounds again if the state has changed since the user started
// dragging (ie. when the IME shows)
- updateMovementBounds(mIsMenuVisible);
+ updateMovementBounds(mMenuState);
for (PipTouchGesture gesture : mGestures) {
if (gesture.onUp(mTouchState)) {
@@ -378,7 +389,7 @@
break;
}
}
- return !mIsMenuVisible;
+ return mMenuState == MENU_STATE_NONE;
}
/**
@@ -393,7 +404,7 @@
final float distance = bounds.bottom - target;
fraction = Math.min(distance / bounds.height(), 1f);
}
- if (Float.compare(fraction, 0f) != 0 || mMenuController.isMenuVisible()) {
+ if (Float.compare(fraction, 0f) != 0 || mMenuState != MENU_STATE_NONE) {
// Update if the fraction > 0, or if fraction == 0 and the menu was already visible
mMenuController.setDismissFraction(fraction);
}
@@ -449,8 +460,8 @@
/**
* Sets the menu visibility.
*/
- void setMenuVisibilityState(boolean menuVisible, boolean resize) {
- if (menuVisible) {
+ void setMenuState(int menuState, boolean resize) {
+ if (menuState == MENU_STATE_FULL) {
// Save the current snap fraction and if we do not drag or move the PiP, then
// we store back to this snap fraction. Otherwise, we'll reset the snap
// fraction and snap to the closest edge
@@ -459,7 +470,7 @@
mSavedSnapFraction = mMotionHelper.animateToExpandedState(expandedBounds,
mMovementBounds, mExpandedMovementBounds);
}
- } else {
+ } else if (menuState == MENU_STATE_NONE) {
// Try and restore the PiP to the closest edge, using the saved snap fraction
// if possible
if (resize) {
@@ -469,10 +480,12 @@
}
mSavedSnapFraction = -1f;
}
- mIsMenuVisible = menuVisible;
- updateMovementBounds(menuVisible);
- MetricsLogger.visibility(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_MENU,
- menuVisible);
+ mMenuState = menuState;
+ updateMovementBounds(menuState);
+ if (menuState != MENU_STATE_CLOSE) {
+ MetricsLogger.visibility(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_MENU,
+ menuState == MENU_STATE_FULL);
+ }
}
/**
@@ -501,7 +514,7 @@
// If the menu is still visible, and we aren't minimized, then just poke the menu
// so that it will timeout after the user stops touching it
- if (mMenuController.isMenuVisible() && !mIsMinimized) {
+ if (mMenuState != MENU_STATE_NONE && !mIsMinimized) {
mMenuController.pokeMenu();
}
@@ -599,7 +612,7 @@
!mIsMinimized && (mMotionHelper.shouldMinimizePip() || isFlingToEdge)) {
// Pip should be minimized
setMinimizedStateInternal(true);
- if (mMenuController.isMenuVisible()) {
+ if (mMenuState == MENU_STATE_FULL) {
// If the user dragged the expanded PiP to the edge, then hiding the menu
// will trigger the PiP to be scaled back to the normal size with the
// minimize offset adjusted
@@ -617,11 +630,11 @@
}
AnimatorListenerAdapter postAnimationCallback = null;
- if (mMenuController.isMenuVisible()) {
+ if (mMenuState != MENU_STATE_NONE) {
// If the menu is still visible, and we aren't minimized, then just poke the
// menu so that it will timeout after the user stops touching it
- mMenuController.showMenu(mMotionHelper.getBounds(), mMovementBounds,
- true /* allowMenuTimeout */);
+ mMenuController.showMenu(mMenuState, mMotionHelper.getBounds(),
+ mMovementBounds, true /* allowMenuTimeout */);
} else {
// If the menu is not visible, then we can still be showing the activity for the
// dismiss overlay, so just finish it after the animation completes
@@ -645,10 +658,11 @@
mMotionHelper.animateToClosestSnapTarget(mMovementBounds, null /* updateListener */,
null /* animatorListener */);
setMinimizedStateInternal(false);
- } else if (!mIsMenuVisible) {
- mMenuController.showMenu(mMotionHelper.getBounds(), mMovementBounds,
- true /* allowMenuTimeout */);
+ } else if (mMenuState != MENU_STATE_FULL) {
+ mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
+ mMovementBounds, true /* allowMenuTimeout */);
} else {
+ mMenuController.hideMenu();
mMotionHelper.expandPip();
}
return true;
@@ -658,8 +672,8 @@
/**
* Updates the current movement bounds based on whether the menu is currently visible.
*/
- private void updateMovementBounds(boolean isExpanded) {
- mMovementBounds = isExpanded
+ private void updateMovementBounds(int menuState) {
+ mMovementBounds = menuState == MENU_STATE_FULL
? mExpandedMovementBounds
: mNormalMovementBounds;
}
@@ -672,7 +686,7 @@
pw.println(innerPrefix + "mNormalMovementBounds=" + mNormalMovementBounds);
pw.println(innerPrefix + "mExpandedBounds=" + mExpandedBounds);
pw.println(innerPrefix + "mExpandedMovementBounds=" + mExpandedMovementBounds);
- pw.println(innerPrefix + "mIsMenuVisible=" + mIsMenuVisible);
+ pw.println(innerPrefix + "mMenuState=" + mMenuState);
pw.println(innerPrefix + "mIsMinimized=" + mIsMinimized);
pw.println(innerPrefix + "mIsImeShowing=" + mIsImeShowing);
pw.println(innerPrefix + "mImeHeight=" + mImeHeight);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlButtonView.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlButtonView.java
index 59cb086..40a63d7 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlButtonView.java
@@ -77,9 +77,9 @@
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.tv_pip_control_button, this);
- mIconImageView = (ImageView) findViewById(R.id.icon);
- mButtonImageView = (ImageView) findViewById(R.id.button);
- mDescriptionTextView = (TextView) findViewById(R.id.desc);
+ mIconImageView = findViewById(R.id.icon);
+ mButtonImageView = findViewById(R.id.button);
+ mDescriptionTextView = findViewById(R.id.desc);
int[] values = new int[] {android.R.attr.src, android.R.attr.text};
TypedArray typedArray =
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
index a2aff2d..4c81907 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
@@ -107,7 +107,7 @@
public void onFinishInflate() {
super.onFinishInflate();
- mFullButtonView = (PipControlButtonView) findViewById(R.id.full_button);
+ mFullButtonView = findViewById(R.id.full_button);
mFullButtonView.setOnFocusChangeListener(mFocusChangeListener);
mFullButtonView.setOnClickListener(new View.OnClickListener() {
@Override
@@ -116,7 +116,7 @@
}
});
- mCloseButtonView = (PipControlButtonView) findViewById(R.id.close_button);
+ mCloseButtonView = findViewById(R.id.close_button);
mCloseButtonView.setOnFocusChangeListener(mFocusChangeListener);
mCloseButtonView.setOnClickListener(new View.OnClickListener() {
@Override
@@ -128,7 +128,7 @@
}
});
- mPlayPauseButtonView = (PipControlButtonView) findViewById(R.id.play_pause_button);
+ mPlayPauseButtonView = findViewById(R.id.play_pause_button);
mPlayPauseButtonView.setOnFocusChangeListener(mFocusChangeListener);
mPlayPauseButtonView.setOnClickListener(new View.OnClickListener() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
index 01d86b6..9945079 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
@@ -44,7 +44,7 @@
mPipManager.addListener(this);
mRestorePipSizeWhenClose = true;
- mPipControlsView = (PipControlsView) findViewById(R.id.pip_controls);
+ mPipControlsView = findViewById(R.id.pip_controls);
mFadeInAnimation = AnimatorInflater.loadAnimator(
this, R.anim.tv_pip_menu_fade_in_animation);
mFadeInAnimation.setTarget(mPipControlsView);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipOnboardingActivity.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipOnboardingActivity.java
index 57952f4..423530a 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipOnboardingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipOnboardingActivity.java
@@ -65,7 +65,7 @@
mEnterAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
- ImageView button = (ImageView) findViewById(R.id.remote_button);
+ ImageView button = findViewById(R.id.remote_button);
((AnimationDrawable) button.getDrawable()).start();
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index d2a2919..f124e86 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -92,14 +92,14 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mDetailContent = (ViewGroup) findViewById(android.R.id.content);
- mDetailSettingsButton = (TextView) findViewById(android.R.id.button2);
- mDetailDoneButton = (TextView) findViewById(android.R.id.button1);
+ mDetailContent = findViewById(android.R.id.content);
+ mDetailSettingsButton = findViewById(android.R.id.button2);
+ mDetailDoneButton = findViewById(android.R.id.button1);
mQsDetailHeader = findViewById(R.id.qs_detail_header);
mQsDetailHeaderTitle = (TextView) mQsDetailHeader.findViewById(android.R.id.title);
mQsDetailHeaderSwitch = (Switch) mQsDetailHeader.findViewById(android.R.id.toggle);
- mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress);
+ mQsDetailHeaderProgress = findViewById(R.id.qs_detail_header_progress);
updateDetailText();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
index 65238b1..f91aa9a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
@@ -76,13 +76,13 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mItemList = (AutoSizingList) findViewById(android.R.id.list);
+ mItemList = findViewById(android.R.id.list);
mItemList.setVisibility(GONE);
mItemList.setAdapter(mAdapter);
mEmpty = findViewById(android.R.id.empty);
mEmpty.setVisibility(GONE);
- mEmptyText = (TextView) mEmpty.findViewById(android.R.id.title);
- mEmptyIcon = (ImageView) mEmpty.findViewById(android.R.id.icon);
+ mEmptyText = mEmpty.findViewById(android.R.id.title);
+ mEmptyIcon = mEmpty.findViewById(android.R.id.icon);
}
@Override
@@ -104,8 +104,10 @@
}
public void setEmptyState(int icon, int text) {
- mEmptyIcon.setImageResource(icon);
- mEmptyText.setText(text);
+ mEmptyIcon.post(() -> {
+ mEmptyIcon.setImageResource(icon);
+ mEmptyText.setText(text);
+ });
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 2e6116d..38485c7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -32,6 +32,7 @@
import android.widget.LinearLayout;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.DetailAdapter;
@@ -118,7 +119,8 @@
protected void addDivider() {
mDivider = LayoutInflater.from(mContext).inflate(R.layout.qs_divider, this, false);
- mDivider.setBackgroundColor(getColorForState(mContext, Tile.STATE_INACTIVE));
+ mDivider.setBackgroundColor(Utils.applyAlpha(mDivider.getAlpha(),
+ getColorForState(mContext, Tile.STATE_ACTIVE)));
addView(mDivider);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index d0d6f61..7518527a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -21,15 +21,19 @@
import android.graphics.Rect;
import android.support.annotation.VisibleForTesting;
import android.util.AttributeSet;
+import android.view.View;
import android.widget.RelativeLayout;
+import android.widget.TextClock;
import com.android.settingslib.Utils;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.R.id;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.qs.QSDetail.Callback;
import com.android.systemui.statusbar.SignalClusterView;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
public class QuickStatusBarHeader extends RelativeLayout {
@@ -63,19 +67,27 @@
updateResources();
// Set the light/dark theming on the header status UI to match the current theme.
- SignalClusterView cluster = findViewById(R.id.signal_cluster);
int colorForeground = Utils.getColorAttr(getContext(), android.R.attr.colorForeground);
float intensity = colorForeground == Color.WHITE ? 0 : 1;
- cluster.onDarkChanged(new Rect(0, 0, 0, 0), intensity, colorForeground);
+ Rect tintArea = new Rect(0, 0, 0, 0);
+
+ applyDarkness(R.id.signal_cluster, tintArea, intensity, colorForeground);
+ applyDarkness(R.id.battery, tintArea, intensity, colorForeground);
+ applyDarkness(R.id.clock, tintArea, intensity, colorForeground);
BatteryMeterView battery = findViewById(R.id.battery);
battery.setForceShowPercent(true);
- int colorSecondary = Utils.getColorAttr(getContext(), android.R.attr.textColorSecondary);
- battery.setRawColors(colorForeground, colorSecondary);
mActivityStarter = Dependency.get(ActivityStarter.class);
}
+ private void applyDarkness(int id, Rect tintArea, float intensity, int color) {
+ View v = findViewById(id);
+ if (v instanceof DarkReceiver) {
+ ((DarkReceiver) v).onDarkChanged(tintArea, intensity, color);
+ }
+ }
+
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 596d3bc..30053e3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -82,7 +82,7 @@
LayoutInflater.from(getContext()).inflate(R.layout.qs_customize_panel_content, this);
- mToolbar = (Toolbar) findViewById(com.android.internal.R.id.action_bar);
+ mToolbar = findViewById(com.android.internal.R.id.action_bar);
TypedValue value = new TypedValue();
mContext.getTheme().resolveAttribute(android.R.attr.homeAsUpIndicator, value, true);
mToolbar.setNavigationIcon(
@@ -98,7 +98,7 @@
mContext.getString(com.android.internal.R.string.reset));
mToolbar.setTitle(R.string.qs_edit);
- mRecyclerView = (RecyclerView) findViewById(android.R.id.list);
+ mRecyclerView = findViewById(android.R.id.list);
mTileAdapter = new TileAdapter(getContext());
mRecyclerView.setAdapter(mTileAdapter);
mTileAdapter.getItemTouchHelper().attachToRecyclerView(mRecyclerView);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 1aa51b1..6781c16 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -22,6 +22,7 @@
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_ACTION;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import android.R.attr;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
@@ -73,6 +74,7 @@
private String mTileSpec;
private EnforcedAdmin mEnforcedAdmin;
+ private boolean mShowingDetail;
public abstract TState newTileState();
@@ -286,11 +288,16 @@
}
private void handleShowDetail(boolean show) {
+ mShowingDetail = show;
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).onShowDetail(show);
}
}
+ protected boolean isShowingDetail() {
+ return mShowingDetail;
+ }
+
private void handleToggleStateChanged(boolean state) {
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).onToggleStateChanged(state);
@@ -336,9 +343,9 @@
Utils.getColorAttr(context, android.R.attr.textColorTertiary));
case Tile.STATE_INACTIVE:
return Utils.getDisabled(context,
- Utils.getColorAttr(context, android.R.attr.colorForeground));
+ Utils.getColorAttr(context, android.R.attr.textColorSecondary));
case Tile.STATE_ACTIVE:
- return Utils.getColorAttr(context, android.R.attr.colorForeground);
+ return Utils.getColorAttr(context, attr.textColorSecondary);
default:
Log.e("QSTile", "Invalid state " + state);
return 0;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
index 5c99809..263dac0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
@@ -42,6 +42,7 @@
private int mState;
private ViewGroup mLabelContainer;
private View mExpandIndicator;
+ private View mExpandSpace;
public QSTileView(Context context, QSIconView icon) {
this(context, icon, false);
@@ -84,6 +85,7 @@
mPadLock = mLabelContainer.findViewById(R.id.restricted_padlock);
mDivider = mLabelContainer.findViewById(R.id.underline);
mExpandIndicator = mLabelContainer.findViewById(R.id.expand_indicator);
+ mExpandSpace = mLabelContainer.findViewById(R.id.expand_space);
addView(mLabelContainer);
}
@@ -101,8 +103,8 @@
mState = state.state;
mLabel.setText(state.label);
}
- mDivider.setVisibility(state.dualTarget ? View.VISIBLE : View.INVISIBLE);
mExpandIndicator.setVisibility(state.dualTarget ? View.VISIBLE : View.GONE);
+ mExpandSpace.setVisibility(state.dualTarget ? View.VISIBLE : View.GONE);
mLabelContainer.setContentDescription(state.dualTarget ? state.dualLabelContentDescription
: null);
if (state.dualTarget != mLabelContainer.isClickable()) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index 8209ee2..ecc275d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -181,7 +181,7 @@
return;
}
mDrawable.setBatteryLevel(100);
- mDrawable.setPluggedIn(false);
+ mDrawable.setCharging(false);
mDrawable.setPowerSave(true);
mDrawable.setShowPercent(false);
((ImageView) mCurrentView.findViewById(android.R.id.icon)).setImageDrawable(mDrawable);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 75e9d5a..d27bb85 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -35,10 +35,10 @@
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
import com.android.systemui.qs.QSHost;
-import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.BluetoothController;
@@ -99,10 +99,6 @@
return;
}
showDetail(true);
- if (!mState.value) {
- mState.value = true;
- mController.setBluetoothEnabled(true);
- }
}
@Override
@@ -176,6 +172,9 @@
@Override
public void onBluetoothStateChange(boolean enabled) {
refreshState();
+ if (isShowingDetail()) {
+ mDetailAdapter.updateItems();
+ }
}
@Override
@@ -187,6 +186,9 @@
}
});
refreshState();
+ if (isShowingDetail()) {
+ mDetailAdapter.updateItems();
+ }
}
};
@@ -223,7 +225,6 @@
public void setToggleState(boolean state) {
MetricsLogger.action(mContext, MetricsEvent.QS_BLUETOOTH_TOGGLE, state);
mController.setBluetoothEnabled(state);
- showDetail(false);
}
@Override
@@ -235,8 +236,6 @@
public View createDetailView(Context context, View convertView, ViewGroup parent) {
mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
mItems.setTagSuffix("Bluetooth");
- mItems.setEmptyState(R.drawable.ic_qs_bluetooth_detail_empty,
- R.string.quick_settings_bluetooth_detail_empty_text);
mItems.setCallback(this);
updateItems();
setItemsVisible(mState.value);
@@ -250,6 +249,13 @@
private void updateItems() {
if (mItems == null) return;
+ if (mController.isBluetoothEnabled()) {
+ mItems.setEmptyState(R.drawable.ic_qs_bluetooth_detail_empty,
+ R.string.quick_settings_bluetooth_detail_empty_text);
+ } else {
+ mItems.setEmptyState(R.drawable.ic_qs_bluetooth_detail_empty,
+ R.string.bt_is_off);
+ }
ArrayList<Item> items = new ArrayList<Item>();
final Collection<CachedBluetoothDevice> devices = mController.getDevices();
if (devices != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 9b3ee30..1151c8c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -35,8 +35,8 @@
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile.SignalState;
-import com.android.systemui.qs.CellTileView;
import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.SignalTileView;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
@@ -83,7 +83,7 @@
@Override
public QSIconView createTileView(Context context) {
- return new CellTileView(context);
+ return new SignalTileView(context);
}
@Override
@@ -118,15 +118,6 @@
}
final Resources r = mContext.getResources();
- final int iconId = cb.noSim ? R.drawable.ic_qs_no_sim
- : !cb.enabled || cb.airplaneModeEnabled ? R.drawable.ic_qs_signal_disabled
- : cb.mobileSignalIconId > 0 ? cb.mobileSignalIconId
- : R.drawable.ic_qs_signal_no_signal;
- if (cb.dataTypeIconId != 0) {
- state.icon = ResourceIcon.get(cb.dataTypeIconId);
- } else {
- state.icon = ResourceIcon.get(iconId);
- }
state.activityIn = cb.enabled && cb.activityIn;
state.activityOut = cb.enabled && cb.activityOut;
@@ -136,8 +127,16 @@
state.expandedAccessibilityClassName = Switch.class.getName();
state.value = mDataController.isMobileDataSupported()
&& mDataController.isMobileDataEnabled();
- state.state = cb.airplaneModeEnabled ? Tile.STATE_UNAVAILABLE
+ state.icon = ResourceIcon.get(R.drawable.ic_data_unavailable);
+ state.state = cb.airplaneModeEnabled || !cb.enabled ? Tile.STATE_UNAVAILABLE
: state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+ if (state.state == Tile.STATE_ACTIVE) {
+ state.icon = ResourceIcon.get(R.drawable.ic_data_on);
+ } else if (state.state == Tile.STATE_INACTIVE) {
+ state.icon = ResourceIcon.get(R.drawable.ic_data_off);
+ } else {
+ state.icon = ResourceIcon.get(R.drawable.ic_data_unavailable);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
index 9cd79f8..7224ae6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -98,21 +98,21 @@
usageColor = Utils.getColorAccent(mContext);
}
- final TextView title = (TextView) findViewById(android.R.id.title);
+ final TextView title = findViewById(android.R.id.title);
title.setText(titleId);
- final TextView usage = (TextView) findViewById(R.id.usage_text);
+ final TextView usage = findViewById(R.id.usage_text);
usage.setText(formatBytes(bytes));
usage.setTextColor(usageColor);
- final DataUsageGraph graph = (DataUsageGraph) findViewById(R.id.usage_graph);
+ final DataUsageGraph graph = findViewById(R.id.usage_graph);
graph.setLevels(info.limitLevel, info.warningLevel, info.usageLevel);
- final TextView carrier = (TextView) findViewById(R.id.usage_carrier_text);
+ final TextView carrier = findViewById(R.id.usage_carrier_text);
carrier.setText(info.carrier);
- final TextView period = (TextView) findViewById(R.id.usage_period_text);
+ final TextView period = findViewById(R.id.usage_period_text);
period.setText(info.period);
- final TextView infoTop = (TextView) findViewById(R.id.usage_info_top_text);
+ final TextView infoTop = findViewById(R.id.usage_info_top_text);
infoTop.setVisibility(top != null ? View.VISIBLE : View.GONE);
infoTop.setText(top);
- final TextView infoBottom = (TextView) findViewById(R.id.usage_info_bottom_text);
+ final TextView infoBottom = findViewById(R.id.usage_info_bottom_text);
infoBottom.setVisibility(bottom != null ? View.VISIBLE : View.GONE);
infoBottom.setText(bottom);
boolean showLevel = info.warningLevel > 0 || info.limitLevel > 0;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 3c2e897..ecbc4f7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -16,16 +16,25 @@
package com.android.systemui.qs.tiles;
+import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
+import static android.provider.Settings.Global.ZEN_MODE_OFF;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.net.Uri;
import android.os.UserManager;
import android.provider.Settings;
import android.provider.Settings.Global;
+import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenModeConfig.ZenRule;
import android.service.quicksettings.Tile;
+import android.util.Slog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
@@ -41,9 +50,9 @@
import com.android.systemui.SysUIToast;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
-import com.android.systemui.qs.QSHost;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.volume.ZenModePanel;
@@ -129,10 +138,9 @@
@Override
protected void handleClick() {
if (mState.value) {
- mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
+ mController.setZen(ZEN_MODE_OFF, null, TAG);
} else {
- int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS);
- mController.setZen(zen, null, TAG);
+ mController.setZen(ZEN_MODE_ALARMS, null, TAG);
}
}
@@ -147,8 +155,6 @@
return;
}
showDetail(true);
- int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS);
- mController.setZen(zen, null, TAG);
}
@Override
@@ -159,7 +165,7 @@
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
final int zen = arg instanceof Integer ? (Integer) arg : mController.getZen();
- final boolean newValue = zen != Global.ZEN_MODE_OFF;
+ final boolean newValue = zen != ZEN_MODE_OFF;
final boolean valueChanged = state.value != newValue;
state.dualTarget = true;
state.value = newValue;
@@ -178,7 +184,7 @@
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_dnd_none_on);
break;
- case Global.ZEN_MODE_ALARMS:
+ case ZEN_MODE_ALARMS:
state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
state.label = mContext.getString(R.string.quick_settings_dnd_alarms_label);
state.contentDescription = mContext.getString(
@@ -187,13 +193,10 @@
default:
state.icon = TOTAL_SILENCE.equals(state.icon) ? mDisableTotalSilence : mDisable;
state.label = mContext.getString(R.string.quick_settings_dnd_label);
- state.contentDescription = mContext.getString(
+ state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_dnd);
break;
}
- if (mShowingDetail && !state.value) {
- showDetail(false);
- }
if (valueChanged) {
fireToggleStateChanged(state.value);
}
@@ -249,6 +252,16 @@
private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
public void onZenChanged(int zen) {
refreshState(zen);
+ if (isShowingDetail()) {
+ mDetailAdapter.updatePanel();
+ }
+ }
+
+ @Override
+ public void onConfigChanged(ZenModeConfig config) {
+ if (isShowingDetail()) {
+ mDetailAdapter.updatePanel();
+ }
}
};
@@ -263,6 +276,9 @@
private final class DndDetailAdapter implements DetailAdapter, OnAttachStateChangeListener {
+ private ZenModePanel mZenPanel;
+ private boolean mAuto;
+
@Override
public CharSequence getTitle() {
return mContext.getString(R.string.quick_settings_dnd_label);
@@ -282,8 +298,12 @@
public void setToggleState(boolean state) {
MetricsLogger.action(mContext, MetricsEvent.QS_DND_TOGGLE, state);
if (!state) {
- mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
- showDetail(false);
+ mController.setZen(ZEN_MODE_OFF, null, TAG);
+ mAuto = false;
+ } else {
+ int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN,
+ ZEN_MODE_ALARMS);
+ mController.setZen(zen, null, TAG);
}
}
@@ -294,15 +314,65 @@
@Override
public View createDetailView(Context context, View convertView, ViewGroup parent) {
- final ZenModePanel zmp = convertView != null ? (ZenModePanel) convertView
+ mZenPanel = convertView != null ? (ZenModePanel) convertView
: (ZenModePanel) LayoutInflater.from(context).inflate(
R.layout.zen_mode_panel, parent, false);
if (convertView == null) {
- zmp.init(mController);
- zmp.addOnAttachStateChangeListener(this);
- zmp.setCallback(mZenModePanelCallback);
+ mZenPanel.init(mController);
+ mZenPanel.addOnAttachStateChangeListener(this);
+ mZenPanel.setCallback(mZenModePanelCallback);
+ mZenPanel.setEmptyState(R.drawable.ic_qs_dnd_off, R.string.dnd_is_off);
}
- return zmp;
+ updatePanel();
+ return mZenPanel;
+ }
+
+ private void updatePanel() {
+ if (mZenPanel == null) return;
+ mAuto = false;
+ if (mController.getZen() == ZEN_MODE_OFF) {
+ mZenPanel.setState(ZenModePanel.STATE_OFF);
+ } else {
+ ZenModeConfig config = mController.getConfig();
+ String summary = "";
+ if (config.manualRule != null && config.manualRule.enabler != null) {
+ summary = getOwnerCaption(config.manualRule.enabler);
+ }
+ for (ZenRule automaticRule : config.automaticRules.values()) {
+ if (automaticRule.isAutomaticActive()) {
+ if (summary.isEmpty()) {
+ summary = mContext.getString(R.string.qs_dnd_prompt_auto_rule,
+ automaticRule.name);
+ } else {
+ summary = mContext.getString(R.string.qs_dnd_prompt_auto_rule_app);
+ }
+ }
+ }
+ if (summary.isEmpty()) {
+ mZenPanel.setState(ZenModePanel.STATE_MODIFY);
+ } else {
+ mAuto = true;
+ mZenPanel.setState(ZenModePanel.STATE_AUTO_RULE);
+ mZenPanel.setAutoText(summary);
+ }
+ }
+ }
+
+ private String getOwnerCaption(String owner) {
+ final PackageManager pm = mContext.getPackageManager();
+ try {
+ final ApplicationInfo info = pm.getApplicationInfo(owner, 0);
+ if (info != null) {
+ final CharSequence seq = info.loadLabel(pm);
+ if (seq != null) {
+ final String str = seq.toString().trim();
+ return mContext.getString(R.string.qs_dnd_prompt_app, str);
+ }
+ }
+ } catch (Throwable e) {
+ Slog.w(TAG, "Error loading owner caption", e);
+ }
+ return "";
}
@Override
@@ -313,6 +383,7 @@
@Override
public void onViewDetachedFromWindow(View v) {
mShowingDetail = false;
+ mZenPanel = null;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index b11b15a..6522e10 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -22,7 +22,6 @@
import android.service.quicksettings.Tile;
import android.widget.Switch;
-import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -32,7 +31,7 @@
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.LocationController.LocationSettingsChangeCallback;
+import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
/** Quick settings tile: Location **/
public class LocationTile extends QSTileImpl<BooleanState> {
@@ -132,7 +131,7 @@
}
}
- private final class Callback implements LocationSettingsChangeCallback,
+ private final class Callback implements LocationChangeCallback,
KeyguardMonitor.Callback {
@Override
public void onLocationSettingsChanged(boolean enabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
index c485a9e..1e9a618 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
@@ -117,8 +117,8 @@
@Override
protected void onFinishInflate() {
- mAvatar = (UserAvatarView) findViewById(R.id.user_picture);
- mName = (TextView) findViewById(R.id.user_name);
+ mAvatar = findViewById(R.id.user_picture);
+ mName = findViewById(R.id.user_name);
if (mRegularTypeface == null) {
mRegularTypeface = mName.getTypeface();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 7d2d210..5a23d3b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -32,6 +32,7 @@
import com.android.settingslib.wifi.AccessPoint;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.R.string;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.QSDetailItems;
@@ -98,7 +99,9 @@
}
@Override
- protected DetailAdapter createDetailAdapter() { return new WifiDetailAdapter(); }
+ protected DetailAdapter createDetailAdapter() {
+ return new WifiDetailAdapter();
+ }
@Override
public QSIconView createTileView(Context context) {
@@ -125,10 +128,6 @@
return;
}
showDetail(true);
- if (!mState.value) {
- mController.setWifiEnabled(true);
- mState.value = true;
- }
}
@Override
@@ -234,15 +233,15 @@
@Override
public String toString() {
return new StringBuilder("CallbackInfo[")
- .append("enabled=").append(enabled)
- .append(",connected=").append(connected)
- .append(",wifiSignalIconId=").append(wifiSignalIconId)
- .append(",enabledDesc=").append(enabledDesc)
- .append(",activityIn=").append(activityIn)
- .append(",activityOut=").append(activityOut)
- .append(",wifiSignalContentDescription=").append(wifiSignalContentDescription)
- .append(",isTransient=").append(isTransient)
- .append(']').toString();
+ .append("enabled=").append(enabled)
+ .append(",connected=").append(connected)
+ .append(",wifiSignalIconId=").append(wifiSignalIconId)
+ .append(",enabledDesc=").append(enabledDesc)
+ .append(",activityIn=").append(activityIn)
+ .append(",activityOut=").append(activityOut)
+ .append(",wifiSignalContentDescription=").append(wifiSignalContentDescription)
+ .append(",isTransient=").append(isTransient)
+ .append(']').toString();
}
}
@@ -261,9 +260,14 @@
mInfo.activityOut = activityOut;
mInfo.wifiSignalContentDescription = qsIcon.contentDescription;
mInfo.isTransient = isTransient;
+ if (isShowingDetail()) {
+ mDetailAdapter.updateItems();
+ }
refreshState(mInfo);
}
- };
+ }
+
+ ;
protected class WifiDetailAdapter implements DetailAdapter,
NetworkController.AccessPointController.AccessPointCallback, QSDetailItems.Callback {
@@ -290,7 +294,6 @@
if (DEBUG) Log.d(TAG, "setToggleState " + state);
MetricsLogger.action(mContext, MetricsEvent.QS_WIFI_TOGGLE, state);
mController.setWifiEnabled(state);
- showDetail(false);
}
@Override
@@ -307,8 +310,6 @@
mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
mItems.setTagSuffix("Wifi");
mItems.setCallback(this);
- mItems.setEmptyState(R.drawable.ic_qs_wifi_detail_empty,
- R.string.quick_settings_wifi_detail_empty_text);
updateItems();
setItemsVisible(mState.value);
return mItems;
@@ -352,6 +353,13 @@
private void updateItems() {
if (mItems == null) return;
+ if (mSignalCallback.mInfo.enabled) {
+ mItems.setEmptyState(R.drawable.ic_qs_wifi_detail_empty,
+ R.string.quick_settings_wifi_detail_empty_text);
+ } else {
+ mItems.setEmptyState(R.drawable.ic_qs_wifi_detail_empty,
+ R.string.wifi_is_off);
+ }
Item[] items = null;
if (mAccessPoints != null) {
items = new Item[mAccessPoints.length];
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index f0a9bc3..143d934 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -325,7 +325,7 @@
// Set the Recents layout
setContentView(R.layout.recents);
takeKeyEvents(true);
- mRecentsView = (RecentsView) findViewById(R.id.recents_view);
+ mRecentsView = findViewById(R.id.recents_view);
mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 33ad7fb..164138e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -72,6 +72,7 @@
import com.android.systemui.recents.model.TaskGrouping;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
+import com.android.systemui.recents.views.TaskStackLayoutAlgorithm.VisibilityReport;
import com.android.systemui.recents.views.TaskStackView;
import com.android.systemui.recents.views.TaskStackViewScroller;
import com.android.systemui.recents.views.TaskViewHeader;
@@ -126,11 +127,22 @@
if (runningTaskInfo != null) {
launchOpts.runningTaskId = runningTaskInfo.id;
}
- launchOpts.numVisibleTasks = 2;
- launchOpts.numVisibleTaskThumbnails = 2;
+ mDummyStackView.setTasks(plan.getTaskStack(), false /* allowNotify */);
+ updateDummyStackViewLayout(plan.getTaskStack(),
+ getWindowRect(null /* windowRectOverride */));
+
+ // Launched from app is always the worst case (in terms of how many thumbnails/tasks
+ // visible)
+ RecentsActivityLaunchState launchState = new RecentsActivityLaunchState();
+ launchState.launchedFromApp = true;
+ mDummyStackView.updateLayoutAlgorithm(true /* boundScroll */, launchState);
+
+ VisibilityReport visibilityReport = mDummyStackView.computeStackVisibilityReport();
+ launchOpts.numVisibleTasks = visibilityReport.numVisibleTasks;
+ launchOpts.numVisibleTaskThumbnails = visibilityReport.numVisibleThumbnails;
launchOpts.onlyLoadForCache = true;
launchOpts.onlyLoadPausedActivities = true;
- launchOpts.loadThumbnails = !ActivityManager.ENABLE_TASK_SNAPSHOTS;
+ launchOpts.loadThumbnails = true;
loader.loadTasks(mContext, plan, launchOpts);
}
}
@@ -605,23 +617,12 @@
mHeaderBar.setLayoutDirection(res.getConfiguration().getLayoutDirection());
}
- /**
- * Prepares the header bar layout for the next transition, if the task view bounds has changed
- * since the last call, it will attempt to re-measure and layout the header bar to the new size.
- *
- * @param stack the stack to initialize the stack layout with
- * @param windowRectOverride the rectangle to use when calculating the stack state which can
- * be different from the current window rect if recents is resizing
- * while being launched
- */
- private void updateHeaderBarLayout(TaskStack stack, Rect windowRectOverride) {
+ private void updateDummyStackViewLayout(TaskStack stack, Rect windowRect) {
SystemServicesProxy ssp = Recents.getSystemServices();
Rect displayRect = ssp.getDisplayRect();
Rect systemInsets = new Rect();
ssp.getStableInsets(systemInsets);
- Rect windowRect = windowRectOverride != null
- ? new Rect(windowRectOverride)
- : ssp.getWindowRect();
+
// 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.
@@ -642,6 +643,29 @@
stackLayout.reset();
stackLayout.initialize(displayRect, windowRect, mTaskStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack));
+ }
+ }
+
+ private Rect getWindowRect(Rect windowRectOverride) {
+ return windowRectOverride != null
+ ? new Rect(windowRectOverride)
+ : Recents.getSystemServices().getWindowRect();
+ }
+
+ /**
+ * Prepares the header bar layout for the next transition, if the task view bounds has changed
+ * since the last call, it will attempt to re-measure and layout the header bar to the new size.
+ *
+ * @param stack the stack to initialize the stack layout with
+ * @param windowRectOverride the rectangle to use when calculating the stack state which can
+ * be different from the current window rect if recents is resizing
+ * while being launched
+ */
+ private void updateHeaderBarLayout(TaskStack stack, Rect windowRectOverride) {
+ Rect windowRect = getWindowRect(windowRectOverride);
+ updateDummyStackViewLayout(stack, windowRect);
+ if (stack != null) {
+ TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm();
mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */);
// Get the width of a task view so that we know how wide to draw the header bar.
int taskViewWidth = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 0336905c..521157d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -31,6 +31,7 @@
import android.os.RemoteException;
import android.util.DisplayMetrics;
import android.view.Gravity;
+import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -46,6 +47,11 @@
import java.util.ArrayList;
public class ScreenPinningRequest implements View.OnClickListener {
+
+ private static final int ROTATION_NONE = 0;
+ private static final int ROTATION_LANDSCAPE = 1;
+ private static final int ROTATION_SEASCAPE = 2;
+
private final Context mContext;
private final AccessibilityManager mAccessibilityService;
@@ -124,11 +130,12 @@
clearPrompt();
}
- public FrameLayout.LayoutParams getRequestLayoutParams(boolean isLandscape) {
+ public FrameLayout.LayoutParams getRequestLayoutParams(int rotation) {
return new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
- isLandscape ? (Gravity.CENTER_VERTICAL | Gravity.RIGHT)
+ rotation == ROTATION_SEASCAPE ? (Gravity.CENTER_VERTICAL | Gravity.LEFT) :
+ rotation == ROTATION_LANDSCAPE ? (Gravity.CENTER_VERTICAL | Gravity.RIGHT)
: (Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM));
}
@@ -153,14 +160,16 @@
DisplayMetrics metrics = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getMetrics(metrics);
float density = metrics.density;
- boolean isLandscape = isLandscapePhone(mContext);
+ int rotation = getRotation(mContext);
- inflateView(isLandscape);
+ inflateView(rotation);
int bgColor = mContext.getColor(
R.color.screen_pinning_request_window_bg);
if (ActivityManager.isHighEndGfx()) {
mLayout.setAlpha(0f);
- if (isLandscape) {
+ if (rotation == ROTATION_SEASCAPE) {
+ mLayout.setTranslationX(-OFFSET_DP * density);
+ } else if (rotation == ROTATION_LANDSCAPE) {
mLayout.setTranslationX(OFFSET_DP * density);
} else {
mLayout.setTranslationY(OFFSET_DP * density);
@@ -193,18 +202,27 @@
mContext.registerReceiver(mReceiver, filter);
}
- private boolean isLandscapePhone(Context context) {
+ private int getRotation(Context context) {
Configuration config = mContext.getResources().getConfiguration();
- return config.orientation == Configuration.ORIENTATION_LANDSCAPE
- && config.smallestScreenWidthDp < 600;
+ int rot = context.getDisplay().getRotation();
+ if (config.smallestScreenWidthDp < 600) {
+ if (rot == Surface.ROTATION_90) {
+ return ROTATION_LANDSCAPE;
+ } else if (rot == Surface.ROTATION_270) {
+ return ROTATION_SEASCAPE;
+ }
+ }
+ return ROTATION_NONE;
}
- private void inflateView(boolean isLandscape) {
+ private void inflateView(int rotation) {
// We only want this landscape orientation on <600dp, so rather than handle
// resource overlay for -land and -sw600dp-land, just inflate this
// other view for this single case.
- mLayout = (ViewGroup) View.inflate(getContext(), isLandscape
- ? R.layout.screen_pinning_request_land_phone : R.layout.screen_pinning_request,
+ mLayout = (ViewGroup) View.inflate(getContext(),
+ rotation == ROTATION_SEASCAPE ? R.layout.screen_pinning_request_sea_phone :
+ rotation == ROTATION_LANDSCAPE ? R.layout.screen_pinning_request_land_phone
+ : R.layout.screen_pinning_request,
null);
// Catch touches so they don't trigger cancel/activate, like outside does.
mLayout.setClickable(true);
@@ -240,7 +258,7 @@
mLayout.findViewById(R.id.screen_pinning_back_bg).setVisibility(backBgVisibility);
mLayout.findViewById(R.id.screen_pinning_back_bg_light).setVisibility(backBgVisibility);
- addView(mLayout, getRequestLayoutParams(isLandscape));
+ addView(mLayout, getRequestLayoutParams(rotation));
}
private void swapChildrenIfRtlAndVertical(View group) {
@@ -269,14 +287,14 @@
protected void onConfigurationChanged() {
removeAllViews();
- inflateView(isLandscapePhone(mContext));
+ inflateView(getRotation(mContext));
}
private final Runnable mUpdateLayoutRunnable = new Runnable() {
@Override
public void run() {
if (mLayout != null && mLayout.getParent() != null) {
- mLayout.setLayoutParams(getRequestLayoutParams(isLandscapePhone(mContext)));
+ mLayout.setLayoutParams(getRequestLayoutParams(getRotation(mContext)));
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 1c71da0..397b78d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -355,9 +355,10 @@
rti.firstActiveTime = rti.lastActiveTime = i;
if (i % 2 == 0) {
rti.taskDescription = new ActivityManager.TaskDescription(description,
- Bitmap.createBitmap(mDummyIcon), null,
- 0xFF000000 | (0xFFFFFF & new Random().nextInt()),
- 0xFF000000 | (0xFFFFFF & new Random().nextInt()));
+ Bitmap.createBitmap(mDummyIcon), null,
+ 0xFF000000 | (0xFFFFFF & new Random().nextInt()),
+ 0xFF000000 | (0xFFFFFF & new Random().nextInt()),
+ 0, 0);
} else {
rti.taskDescription = new ActivityManager.TaskDescription();
}
@@ -670,8 +671,7 @@
if (ActivityManager.ENABLE_TASK_SNAPSHOTS) {
ActivityManager.TaskSnapshot snapshot = null;
try {
- snapshot = ActivityManager.getService().getTaskSnapshot(taskId,
- false /* reducedResolution */);
+ snapshot = ActivityManager.getService().getTaskSnapshot(taskId, reducedResolution);
} catch (RemoteException e) {
Log.w(TAG, "Failed to retrieve snapshot", e);
}
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 f8d123b..5c25bfd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -64,7 +64,7 @@
public static class Options {
public int runningTaskId = -1;
public boolean loadIcons = true;
- public boolean loadThumbnails = true;
+ public boolean loadThumbnails = false;
public boolean onlyLoadForCache = false;
public boolean onlyLoadPausedActivities = false;
public int numVisibleTasks = 0;
@@ -189,7 +189,7 @@
? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false)
: null;
ThumbnailData thumbnail = loader.getAndUpdateThumbnail(taskKey,
- false /* loadIfNotCached */);
+ false /* loadIfNotCached */, false /* storeInCache */);
int activityColor = loader.getActivityPrimaryColor(t.taskDescription);
int backgroundColor = loader.getActivityBackgroundColor(t.taskDescription);
boolean isSystemApp = (info != null) &&
@@ -223,9 +223,7 @@
/**
* Called to apply the actual loading based on the specified conditions.
*/
- public synchronized void executePlan(Options opts, RecentsTaskLoader loader,
- TaskResourceLoadQueue loadQueue) {
- RecentsConfiguration config = Recents.getConfiguration();
+ public synchronized void executePlan(Options opts, RecentsTaskLoader loader) {
Resources res = mContext.getResources();
// Iterate through each of the tasks and load them according to the load conditions.
@@ -250,15 +248,9 @@
true);
}
}
- if (opts.loadThumbnails && (isRunningTask || isVisibleThumbnail)) {
- if (task.thumbnail == null || isRunningTask) {
- if (config.svelteLevel <= RecentsConfiguration.SVELTE_LIMIT_CACHE) {
- task.thumbnail = loader.getAndUpdateThumbnail(taskKey,
- true /* loadIfNotCached */);
- } else if (config.svelteLevel == RecentsConfiguration.SVELTE_DISABLE_CACHE) {
- loadQueue.addTask(task);
- }
- }
+ if (opts.loadThumbnails && isVisibleThumbnail) {
+ task.thumbnail = loader.getAndUpdateThumbnail(taskKey,
+ true /* loadIfNotCached */, true /* storeInCache */);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index e378d0a..e8ffb91 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -37,8 +37,6 @@
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.events.activity.PackagesChangedEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.misc.Utilities;
-import com.android.systemui.recents.model.Task.TaskKey;
import java.io.PrintWriter;
import java.util.Map;
@@ -245,11 +243,11 @@
private final TaskResourceLoadQueue mLoadQueue;
private final BackgroundTaskLoader mLoader;
private final HighResThumbnailLoader mHighResThumbnailLoader;
-
+ private final TaskKeyStrongCache<ThumbnailData> mThumbnailCache = new TaskKeyStrongCache<>();
+ private final TaskKeyStrongCache<ThumbnailData> mTempCache = new TaskKeyStrongCache<>();
private final int mMaxThumbnailCacheSize;
private final int mMaxIconCacheSize;
private int mNumVisibleTasksLoaded;
- private int mNumVisibleThumbnailsLoaded;
int mDefaultTaskBarBackgroundColor;
int mDefaultTaskViewBackgroundColor;
@@ -332,10 +330,19 @@
if (opts == null) {
throw new RuntimeException("Requires load options");
}
- plan.executePlan(opts, this, mLoadQueue);
+ if (opts.onlyLoadForCache && opts.loadThumbnails) {
+
+ // If we are loading for the cache, we'd like to have the real cache only include the
+ // visible thumbnails. However, we also don't want to reload already cached thumbnails.
+ // Thus, we copy over the current entries into a second cache, and clear the real cache,
+ // such that the real cache only contains visible thumbnails.
+ mTempCache.copyEntries(mThumbnailCache);
+ mThumbnailCache.evictAll();
+ }
+ plan.executePlan(opts, this);
+ mTempCache.evictAll();
if (!opts.onlyLoadForCache) {
mNumVisibleTasksLoaded = opts.numVisibleTasks;
- mNumVisibleThumbnailsLoaded = opts.numVisibleTaskThumbnails;
// Start the loader
mLoader.start(context);
@@ -349,7 +356,7 @@
Drawable icon = mIconCache.getAndInvalidateIfModified(t.key);
icon = icon != null ? icon : mDefaultIcon;
mLoadQueue.addTask(t);
- t.notifyTaskDataLoaded(null, icon);
+ t.notifyTaskDataLoaded(t.thumbnail, icon);
}
/** Releases the task resource data back into the pool. */
@@ -404,6 +411,7 @@
// The cache is small, only clear the label cache when we are critical
mActivityLabelCache.evictAll();
mContentDescriptionCache.evictAll();
+ mThumbnailCache.evictAll();
break;
default:
break;
@@ -500,15 +508,31 @@
/**
* Returns the cached thumbnail if the task key is not expired, updating the cache if it is.
*/
- ThumbnailData getAndUpdateThumbnail(Task.TaskKey taskKey, boolean loadIfNotCached) {
+ ThumbnailData getAndUpdateThumbnail(Task.TaskKey taskKey, boolean loadIfNotCached,
+ boolean storeInCache) {
SystemServicesProxy ssp = Recents.getSystemServices();
+ ThumbnailData cached = mThumbnailCache.getAndInvalidateIfModified(taskKey);
+ if (cached != null) {
+ return cached;
+ }
+
+ cached = mTempCache.getAndInvalidateIfModified(taskKey);
+ if (cached != null) {
+ mThumbnailCache.put(taskKey, cached);
+ return cached;
+ }
+
if (loadIfNotCached) {
RecentsConfiguration config = Recents.getConfiguration();
if (config.svelteLevel < RecentsConfiguration.SVELTE_DISABLE_LOADING) {
// Load the thumbnail from the system
- ThumbnailData thumbnailData = ssp.getTaskThumbnail(taskKey.id, true /* reducedResolution */);
+ ThumbnailData thumbnailData = ssp.getTaskThumbnail(taskKey.id,
+ true /* reducedResolution */);
if (thumbnailData.thumbnail != null) {
+ if (storeInCache) {
+ mThumbnailCache.put(taskKey, thumbnailData);
+ }
return thumbnailData;
}
}
@@ -590,5 +614,6 @@
writer.print(prefix); writer.println(TAG);
writer.print(prefix); writer.println("Icon Cache");
mIconCache.dump(innerPrefix, writer);
+ mThumbnailCache.dump(innerPrefix, writer);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyCache.java
new file mode 100644
index 0000000..be99f93
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyCache.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.recents.model;
+
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.systemui.recents.model.Task.TaskKey;
+
+/**
+ * Base class for both strong and LRU task key cache.
+ */
+public abstract class TaskKeyCache<V> {
+
+ protected static final String TAG = "TaskKeyCache";
+
+ protected final SparseArray<TaskKey> mKeys = new SparseArray<>();
+
+ /**
+ * Gets a specific entry in the cache with the specified key, regardless of whether the cached
+ * value is valid or not.
+ */
+ final V get(Task.TaskKey key) {
+ return getCacheEntry(key.id);
+ }
+
+ /**
+ * Returns the value only if the key is valid (has not been updated since the last time it was
+ * in the cache)
+ */
+ final V getAndInvalidateIfModified(Task.TaskKey key) {
+ Task.TaskKey lastKey = mKeys.get(key.id);
+ if (lastKey != null) {
+ if ((lastKey.stackId != key.stackId) ||
+ (lastKey.lastActiveTime != key.lastActiveTime)) {
+ // The task has updated (been made active since the last time it was put into the
+ // LRU cache) or the stack id for the task has changed, invalidate that cache item
+ remove(key);
+ return null;
+ }
+ }
+ // Either the task does not exist in the cache, or the last active time is the same as
+ // the key specified, so return what is in the cache
+ return getCacheEntry(key.id);
+ }
+
+ /** Puts an entry in the cache for a specific key. */
+ final void put(Task.TaskKey key, V value) {
+ if (key == null || value == null) {
+ Log.e(TAG, "Unexpected null key or value: " + key + ", " + value);
+ return;
+ }
+ mKeys.put(key.id, key);
+ putCacheEntry(key.id, value);
+ }
+
+
+ /** Removes a cache entry for a specific key. */
+ final void remove(Task.TaskKey key) {
+ // Remove the key after the cache value because we need it to make the callback
+ removeCacheEntry(key.id);
+ mKeys.remove(key.id);
+ }
+
+ /** Removes all the entries in the cache. */
+ final void evictAll() {
+ evictAllCache();
+ mKeys.clear();
+ }
+
+ protected abstract V getCacheEntry(int id);
+ protected abstract void putCacheEntry(int id, V value);
+ protected abstract void removeCacheEntry(int id);
+ protected abstract void evictAllCache();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java
index 23739a0..778df6b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java
@@ -16,12 +16,9 @@
package com.android.systemui.recents.model;
-import android.util.Log;
import android.util.LruCache;
-import android.util.SparseArray;
import java.io.PrintWriter;
-import java.util.ArrayList;
/**
* A mapping of {@link Task.TaskKey} to value, with additional LRU functionality where the least
@@ -31,15 +28,12 @@
* In addition, this also allows the caller to invalidate cached values for keys that have since
* changed.
*/
-public class TaskKeyLruCache<V> {
+public class TaskKeyLruCache<V> extends TaskKeyCache<V> {
public interface EvictionCallback {
public void onEntryEvicted(Task.TaskKey key);
}
- private static final String TAG = "TaskKeyLruCache";
-
- private final SparseArray<Task.TaskKey> mKeys = new SparseArray<>();
private final LruCache<Integer, V> mCache;
private final EvictionCallback mEvictionCallback;
@@ -61,57 +55,6 @@
};
}
- /**
- * Gets a specific entry in the cache with the specified key, regardless of whether the cached
- * value is valid or not.
- */
- final V get(Task.TaskKey key) {
- return mCache.get(key.id);
- }
-
- /**
- * Returns the value only if the key is valid (has not been updated since the last time it was
- * in the cache)
- */
- final V getAndInvalidateIfModified(Task.TaskKey key) {
- Task.TaskKey lastKey = mKeys.get(key.id);
- if (lastKey != null) {
- if ((lastKey.stackId != key.stackId) ||
- (lastKey.lastActiveTime != key.lastActiveTime)) {
- // The task has updated (been made active since the last time it was put into the
- // LRU cache) or the stack id for the task has changed, invalidate that cache item
- remove(key);
- return null;
- }
- }
- // Either the task does not exist in the cache, or the last active time is the same as
- // the key specified, so return what is in the cache
- return mCache.get(key.id);
- }
-
- /** Puts an entry in the cache for a specific key. */
- final void put(Task.TaskKey key, V value) {
- if (key == null || value == null) {
- Log.e(TAG, "Unexpected null key or value: " + key + ", " + value);
- return;
- }
- mKeys.put(key.id, key);
- mCache.put(key.id, value);
- }
-
- /** Removes a cache entry for a specific key. */
- final void remove(Task.TaskKey key) {
- // Remove the key after the cache value because we need it to make the callback
- mCache.remove(key.id);
- mKeys.remove(key.id);
- }
-
- /** Removes all the entries in the cache. */
- final void evictAll() {
- mCache.evictAll();
- mKeys.clear();
- }
-
/** Trims the cache to a specific size */
final void trimToSize(int cacheSize) {
mCache.trimToSize(cacheSize);
@@ -128,4 +71,24 @@
writer.print(innerPrefix); writer.println(mKeys.get(mKeys.keyAt(i)));
}
}
+
+ @Override
+ protected V getCacheEntry(int id) {
+ return mCache.get(id);
+ }
+
+ @Override
+ protected void putCacheEntry(int id, V value) {
+ mCache.put(id, value);
+ }
+
+ @Override
+ protected void removeCacheEntry(int id) {
+ mCache.remove(id);
+ }
+
+ @Override
+ protected void evictAllCache() {
+ mCache.evictAll();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyStrongCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyStrongCache.java
new file mode 100644
index 0000000..c84df8a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyStrongCache.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.recents.model;
+
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.systemui.recents.model.Task.TaskKey;
+
+import java.io.PrintWriter;
+
+/**
+ * Like {@link TaskKeyLruCache}, but without LRU functionality.
+ */
+public class TaskKeyStrongCache<V> extends TaskKeyCache<V> {
+
+ private static final String TAG = "TaskKeyCache";
+
+ private final ArrayMap<Integer, V> mCache = new ArrayMap<>();
+
+ final void copyEntries(TaskKeyStrongCache<V> other) {
+ for (int i = other.mKeys.size() - 1; i >= 0; i--) {
+ TaskKey key = other.mKeys.valueAt(i);
+ put(key, other.mCache.get(key.id));
+ }
+ }
+
+ public void dump(String prefix, PrintWriter writer) {
+ String innerPrefix = prefix + " ";
+ writer.print(prefix); writer.print(TAG);
+ writer.print(" numEntries="); writer.print(mKeys.size());
+ writer.println();
+ int keyCount = mKeys.size();
+ for (int i = 0; i < keyCount; i++) {
+ writer.print(innerPrefix); writer.println(mKeys.get(mKeys.keyAt(i)));
+ }
+ }
+
+ @Override
+ protected V getCacheEntry(int id) {
+ return mCache.get(id);
+ }
+
+ @Override
+ protected void putCacheEntry(int id, V value) {
+ mCache.put(id, value);
+ }
+
+ @Override
+ protected void removeCacheEntry(int id) {
+ mCache.remove(id);
+ }
+
+ @Override
+ protected void evictAllCache() {
+ mCache.clear();
+ }
+}
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 4fa7ecb5..7ba705e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -220,12 +220,11 @@
}
// A report of the visibility state of the stack
- public class VisibilityReport {
+ public static class VisibilityReport {
public int numVisibleTasks;
public int numVisibleThumbnails;
- /** Package level ctor */
- VisibilityReport(int tasks, int thumbnails) {
+ public VisibilityReport(int tasks, int thumbnails) {
numVisibleTasks = tasks;
numVisibleThumbnails = thumbnails;
}
@@ -505,9 +504,9 @@
* Computes the minimum and maximum scroll progress values and the progress values for each task
* in the stack.
*/
- void update(TaskStack stack, ArraySet<Task.TaskKey> ignoreTasksSet) {
+ void update(TaskStack stack, ArraySet<Task.TaskKey> ignoreTasksSet,
+ RecentsActivityLaunchState launchState) {
SystemServicesProxy ssp = Recents.getSystemServices();
- RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
// Clear the progress map
mTaskIndexMap.clear();
@@ -788,6 +787,10 @@
* stack scroll. Requires that update() is called first.
*/
public VisibilityReport computeStackVisibilityReport(ArrayList<Task> tasks) {
+ if (useGridLayout()) {
+ return mTaskGridLayoutAlgorithm.computeStackVisibilityReport(tasks);
+ }
+
// Ensure minimum visibility count
if (tasks.size() <= 1) {
return new VisibilityReport(1, 1);
@@ -795,8 +798,8 @@
// Quick return when there are no stack tasks
if (mNumStackTasks == 0) {
- return new VisibilityReport(Math.max(mNumFreeformTasks, 1),
- Math.max(mNumFreeformTasks, 1));
+ return new VisibilityReport(mNumFreeformTasks > 0 ? Math.max(mNumFreeformTasks, 1) : 0,
+ mNumFreeformTasks > 0 ? Math.max(mNumFreeformTasks, 1) : 0);
}
// Otherwise, walk backwards in the stack and count the number of tasks and visible
@@ -806,8 +809,8 @@
currentRange.offset(mInitialScrollP);
int taskBarHeight = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_task_view_header_height);
- int numVisibleTasks = Math.max(mNumFreeformTasks, 1);
- int numVisibleThumbnails = Math.max(mNumFreeformTasks, 1);
+ int numVisibleTasks = mNumFreeformTasks > 0 ? Math.max(mNumFreeformTasks, 1) : 0;
+ int numVisibleThumbnails = mNumFreeformTasks > 0 ? Math.max(mNumFreeformTasks, 0) : 0;
float prevScreenY = Integer.MAX_VALUE;
for (int i = tasks.size() - 1; i >= 0; i--) {
Task task = tasks.get(i);
@@ -838,15 +841,15 @@
// Once we hit the next front most task that does not have a visible thumbnail,
// walk through remaining visible set
for (int j = i; j >= 0; j--) {
- numVisibleTasks++;
taskProgress = getStackScrollForTask(tasks.get(j));
if (!currentRange.isInRange(taskProgress)) {
- continue;
+ break;
}
+ numVisibleTasks++;
}
break;
}
- } else if (!isFrontMostTaskInGroup) {
+ } else {
// Affiliated task, no thumbnail
numVisibleTasks++;
}
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 b7cedf7..32e3df6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -868,12 +868,17 @@
mTaskViewsClipDirty = false;
}
+ public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax) {
+ updateLayoutAlgorithm(boundScrollToNewMinMax, Recents.getConfiguration().getLaunchState());
+ }
+
/**
* Updates the layout algorithm min and max virtual scroll bounds.
*/
- public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax) {
+ public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax,
+ RecentsActivityLaunchState launchState) {
// Compute the min and max scroll values
- mLayoutAlgorithm.update(mStack, mIgnoreTasks);
+ mLayoutAlgorithm.update(mStack, mIgnoreTasks, launchState);
// Update the freeform workspace background
SystemServicesProxy ssp = Recents.getSystemServices();
@@ -1550,6 +1555,10 @@
@Override
public void onStackTasksUpdated(TaskStack stack) {
+ if (mAwaitingFirstLayout) {
+ return;
+ }
+
// Update the layout and immediately layout
updateLayoutAlgorithm(false /* boundScroll */);
relayoutTaskViews(AnimationProps.IMMEDIATE);
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 b8be580..e34987b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -222,8 +222,8 @@
@Override
protected void onFinishInflate() {
// Bind the views
- mHeaderView = (TaskViewHeader) findViewById(R.id.task_view_bar);
- mThumbnailView = (TaskViewThumbnail) findViewById(R.id.task_view_thumbnail);
+ mHeaderView = findViewById(R.id.task_view_bar);
+ mThumbnailView = findViewById(R.id.task_view_thumbnail);
mThumbnailView.updateClipToTaskBar(mHeaderView);
mActionButtonView = findViewById(R.id.lock_to_app_fab);
mActionButtonView.setOutlineProvider(new ViewOutlineProvider() {
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 311f8ff..ae922fc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -244,12 +244,12 @@
SystemServicesProxy ssp = Recents.getSystemServices();
// Initialize the icon and description views
- mIconView = (ImageView) findViewById(R.id.icon);
+ mIconView = findViewById(R.id.icon);
mIconView.setOnLongClickListener(this);
- mTitleView = (TextView) findViewById(R.id.title);
- mDismissButton = (ImageView) findViewById(R.id.dismiss_task);
+ mTitleView = findViewById(R.id.title);
+ mDismissButton = findViewById(R.id.dismiss_task);
if (ssp.hasFreeformWorkspaceSupport()) {
- mMoveTaskButton = (ImageView) findViewById(R.id.move_task);
+ mMoveTaskButton = findViewById(R.id.move_task);
}
onConfigurationChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
index 4f17536..c513202 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
@@ -16,6 +16,8 @@
package com.android.systemui.recents.views.grid;
+import static com.android.systemui.recents.views.TaskStackLayoutAlgorithm.*;
+
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Point;
@@ -26,9 +28,12 @@
import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent.Direction;
import com.android.systemui.recents.misc.Utilities;
+import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
import com.android.systemui.recents.views.TaskViewTransform;
+import java.util.ArrayList;
+
public class TaskGridLayoutAlgorithm {
private final String TAG = "TaskGridLayoutAlgorithm";
@@ -313,4 +318,9 @@
public int getFocusFrameThickness() {
return mFocusedFrameThickness;
}
+
+ public VisibilityReport computeStackVisibilityReport(ArrayList<Task> tasks) {
+ int visibleCount = Math.min(TaskGridLayoutAlgorithm.MAX_LAYOUT_TASK_COUNT, tasks.size());
+ return new VisibilityReport(visibleCount, visibleCount);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
index 7d847a3..6918a63 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
@@ -54,8 +54,8 @@
R.layout.quick_settings_brightness_dialog, null);
setContentView(v);
- final ImageView icon = (ImageView) findViewById(R.id.brightness_icon);
- final ToggleSliderView slider = (ToggleSliderView) findViewById(R.id.brightness_slider);
+ final ImageView icon = findViewById(R.id.brightness_icon);
+ final ToggleSliderView slider = findViewById(R.id.brightness_slider);
mBrightnessController = new BrightnessController(this, icon, slider);
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java
index afe89ec..5b234e9 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java
@@ -60,13 +60,13 @@
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.ToggleSliderView, defStyle, 0);
- mToggle = (CompoundButton) findViewById(R.id.toggle);
+ mToggle = findViewById(R.id.toggle);
mToggle.setOnCheckedChangeListener(mCheckListener);
- mSlider = (ToggleSeekBar) findViewById(R.id.slider);
+ mSlider = findViewById(R.id.slider);
mSlider.setOnSeekBarChangeListener(mSeekListener);
- mLabel = (TextView) findViewById(R.id.label);
+ mLabel = findViewById(R.id.label);
mLabel.setText(a.getString(R.styleable.ToggleSliderView_text));
mSlider.setAccessibilityLabel(getContentDescription().toString());
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index c48ecdb..da56e62 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -269,9 +269,9 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mHandle = (DividerHandleView) findViewById(R.id.docked_divider_handle);
+ mHandle = findViewById(R.id.docked_divider_handle);
mBackground = findViewById(R.id.docked_divider_background);
- mMinimizedShadow = (MinimizedDockShadow) findViewById(R.id.minimized_dock_shadow);
+ mMinimizedShadow = findViewById(R.id.minimized_dock_shadow);
mHandle.setOnTouchListener(this);
mDividerWindowWidth = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_thickness);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index d4997ea..469f3ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -203,10 +203,10 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mBackgroundNormal = (NotificationBackgroundView) findViewById(R.id.backgroundNormal);
- mFakeShadow = (FakeShadowView) findViewById(R.id.fake_shadow);
+ mBackgroundNormal = findViewById(R.id.backgroundNormal);
+ mFakeShadow = findViewById(R.id.fake_shadow);
mShadowHidden = mFakeShadow.getVisibility() != VISIBLE;
- mBackgroundDimmed = (NotificationBackgroundView) findViewById(R.id.backgroundDimmed);
+ mBackgroundDimmed = findViewById(R.id.backgroundDimmed);
mBackgroundNormal.setCustomBackground(R.drawable.notification_material_bg);
mBackgroundDimmed.setCustomBackground(R.drawable.notification_material_bg_dim);
updateBackground();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 9176f57..677642e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -328,6 +328,9 @@
mIsColorized = mStatusBarNotification.getNotification().isColorized();
mShowingPublicInitialized = false;
updateNotificationColor();
+ if (mMenuRow != null) {
+ mMenuRow.onNotificationUpdated();
+ }
if (mIsSummaryWithChildren) {
mChildrenContainer.recreateNotificationHeader(mExpandClickListener);
mChildrenContainer.onNotificationUpdated();
@@ -760,7 +763,10 @@
}
mMenuRow = plugin;
if (mMenuRow.useDefaultMenuItems()) {
- mMenuRow.setMenuItems(NotificationMenuRow.getDefaultMenuItems(mContext));
+ ArrayList<MenuItem> items = new ArrayList<>();
+ items.add(NotificationMenuRow.createInfoItem(mContext));
+ items.add(NotificationMenuRow.createSnoozeItem(mContext));
+ mMenuRow.setMenuItems(items);
}
if (existed) {
createMenu();
@@ -787,7 +793,6 @@
return mMenuRow;
}
-
public NotificationMenuRowPlugin getProvider() {
return mMenuRow;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutAppItemLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutAppItemLayout.java
index 507b665..5377dee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutAppItemLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutAppItemLayout.java
@@ -44,8 +44,8 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {
- ImageView shortcutIcon = (ImageView) findViewById(R.id.keyboard_shortcuts_icon);
- TextView shortcutKeyword = (TextView) findViewById(R.id.keyboard_shortcuts_keyword);
+ ImageView shortcutIcon = findViewById(R.id.keyboard_shortcuts_icon);
+ TextView shortcutKeyword = findViewById(R.id.keyboard_shortcuts_keyword);
int totalMeasuredWidth = MeasureSpec.getSize(widthMeasureSpec);
int totalPadding = getPaddingLeft() + getPaddingRight();
int availableWidth = totalMeasuredWidth - totalPadding;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index b4b1cd3..7928575 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -151,7 +151,7 @@
pkg, mAppUid, false /* includeDeleted */);
String channelsDescText;
- mNumChannelsView = (TextView) (findViewById(R.id.num_channels_desc));
+ mNumChannelsView = findViewById(R.id.num_channels_desc);
if (isSingleDefaultChannel) {
channelsDescText = mContext.getString(R.string.notification_default_channel_desc);
} else {
@@ -274,6 +274,7 @@
MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
selectedImportance - mStartingUserImportance);
mSingleNotificationChannel.setImportance(selectedImportance);
+ mSingleNotificationChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
try {
mINotificationManager.updateNotificationChannelForPackage(
mPkg, mAppUid, mSingleNotificationChannel);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
index ff4c9a0..fee24b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -30,11 +30,13 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.app.Notification;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.Log;
+import android.service.notification.StatusBarNotification;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -48,12 +50,12 @@
private static final long SHOW_MENU_DELAY = 60;
private static final long SWIPE_MENU_TIMING = 200;
- private static final int NOTIFICATION_INFO_INDEX = 1;
-
private ExpandableNotificationRow mParent;
private Context mContext;
private FrameLayout mMenuContainer;
+ private MenuItem mSnoozeItem;
+ private MenuItem mInfoItem;
private ArrayList<MenuItem> mMenuItems;
private OnMenuEventListener mMenuListener;
@@ -94,7 +96,11 @@
mVertSpaceForIcons = res.getDimensionPixelSize(R.dimen.notification_min_height);
mIconPadding = res.getDimensionPixelSize(R.dimen.notification_menu_icon_padding);
mHandler = new Handler();
- mMenuItems = getDefaultMenuItems(context);
+ mMenuItems = new ArrayList<>();
+ mSnoozeItem = createSnoozeItem(context);
+ mInfoItem = createInfoItem(context);
+ mMenuItems.add(mSnoozeItem);
+ mMenuItems.add(mInfoItem);
}
@Override
@@ -104,7 +110,7 @@
@Override
public MenuItem getLongpressMenuItem(Context context) {
- return mMenuItems.get(NOTIFICATION_INFO_INDEX);
+ return mInfoItem;
}
@Override
@@ -120,14 +126,7 @@
@Override
public void createMenu(ViewGroup parent) {
mParent = (ExpandableNotificationRow) parent;
- if (mMenuContainer != null) {
- mMenuContainer.removeAllViews();
- }
- mMenuContainer = new FrameLayout(mContext);
- for (int i = 0; i < mMenuItems.size(); i++) {
- addMenuView(mMenuItems.get(i), mMenuContainer);
- }
- resetState(false);
+ createMenuViews();
}
@Override
@@ -145,6 +144,40 @@
resetState(true);
}
+ @Override
+ public void onNotificationUpdated() {
+ if (mMenuContainer == null) {
+ // Menu hasn't been created yet, no need to do anything.
+ return;
+ }
+ createMenuViews();
+ }
+
+ private void createMenuViews() {
+ // Filter the menu items based on the notification
+ if (mParent != null && mParent.getStatusBarNotification() != null) {
+ int flags = mParent.getStatusBarNotification().getNotification().flags;
+ boolean isForeground = (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
+ if (isForeground) {
+ // Don't show snooze for foreground services
+ mMenuItems.remove(mSnoozeItem);
+ } else if (!mMenuItems.contains(mSnoozeItem)) {
+ // Was a foreground service but is no longer, add snooze back
+ mMenuItems.add(mSnoozeItem);
+ }
+ }
+ // Recreate the menu
+ if (mMenuContainer != null) {
+ mMenuContainer.removeAllViews();
+ } else {
+ mMenuContainer = new FrameLayout(mContext);
+ }
+ for (int i = 0; i < mMenuItems.size(); i++) {
+ addMenuView(mMenuItems.get(i), mMenuContainer);
+ }
+ resetState(false /* notify */);
+ }
+
private void resetState(boolean notify) {
setMenuAlpha(0f);
mIconsPlaced = false;
@@ -499,24 +532,24 @@
// TODO -- handle / allow custom menu items!
}
- public static ArrayList<MenuItem> getDefaultMenuItems(Context context) {
- ArrayList<MenuItem> items = new ArrayList<MenuItem>();
+ public static MenuItem createSnoozeItem(Context context) {
Resources res = context.getResources();
-
NotificationSnooze content = (NotificationSnooze) LayoutInflater.from(context)
.inflate(R.layout.notification_snooze, null, false);
String snoozeDescription = res.getString(R.string.notification_menu_snooze_description);
MenuItem snooze = new NotificationMenuItem(context, snoozeDescription, content,
R.drawable.ic_snooze);
- items.add(snooze);
+ return snooze;
+ }
- String settingsDescription = res.getString(R.string.notification_menu_gear_description);
- NotificationInfo settingsContent = (NotificationInfo) LayoutInflater.from(context).inflate(
+ public static MenuItem createInfoItem(Context context) {
+ Resources res = context.getResources();
+ String infoDescription = res.getString(R.string.notification_menu_gear_description);
+ NotificationInfo infoContent = (NotificationInfo) LayoutInflater.from(context).inflate(
R.layout.notification_info, null, false);
- MenuItem settings = new NotificationMenuItem(context, settingsDescription, settingsContent,
+ MenuItem info = new NotificationMenuItem(context, infoDescription, infoContent,
R.drawable.ic_settings);
- items.add(settings);
- return items;
+ return info;
}
private void addMenuView(MenuItem item, ViewGroup parent) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 51345c2..b134fc5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -79,7 +79,7 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mShelfIcons = (NotificationIconContainer) findViewById(R.id.content);
+ mShelfIcons = findViewById(R.id.content);
mShelfIcons.setClipChildren(false);
mShelfIcons.setClipToPadding(false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
index 0de3e02..4a3f112 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
@@ -63,9 +63,9 @@
createOptionViews();
// Snackbar
- mSelectedOptionText = (TextView) findViewById(R.id.snooze_option_default);
+ mSelectedOptionText = findViewById(R.id.snooze_option_default);
mSelectedOptionText.setOnClickListener(this);
- mUndoButton = (TextView) findViewById(R.id.undo);
+ mUndoButton = findViewById(R.id.undo);
mUndoButton.setOnClickListener(this);
// Default to first option in list
@@ -102,7 +102,7 @@
}
private void createOptionViews() {
- mSnoozeOptionView = (ViewGroup) findViewById(R.id.snooze_options);
+ mSnoozeOptionView = findViewById(R.id.snooze_options);
mSnoozeOptionView.removeAllViews();
mSnoozeOptionView.setVisibility(View.GONE);
final Resources res = getResources();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 88711fe..d5f0e7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -83,7 +83,8 @@
private int mWifiStrengthId = 0;
private int mLastWifiBadgeId = -1;
private int mLastWifiStrengthId = -1;
- private int mWifiActivityId = 0;
+ private boolean mWifiIn;
+ private boolean mWifiOut;
private int mLastWifiActivityId = -1;
private boolean mIsAirplaneMode = false;
private int mAirplaneIconId = 0;
@@ -99,7 +100,8 @@
ViewGroup mEthernetGroup, mWifiGroup;
View mNoSimsCombo;
ImageView mVpn, mEthernet, mWifi, mAirplane, mNoSims, mEthernetDark, mWifiDark, mNoSimsDark;
- ImageView mWifiActivity;
+ ImageView mWifiActivityIn;
+ ImageView mWifiActivityOut;
View mWifiAirplaneSpacer;
View mWifiSignalSpacer;
LinearLayout mMobileSignalGroup;
@@ -116,6 +118,7 @@
private boolean mBlockMobile;
private boolean mBlockWifi;
private boolean mBlockEthernet;
+ private boolean mActivityEnabled;
public SignalClusterView(Context context) {
this(context, null);
@@ -144,6 +147,7 @@
mIconScaleFactor = typedValue.getFloat();
mNetworkController = Dependency.get(NetworkController.class);
mSecurityController = Dependency.get(SecurityController.class);
+ updateActivityEnabled();
}
@Override
@@ -173,21 +177,22 @@
protected void onFinishInflate() {
super.onFinishInflate();
- mVpn = (ImageView) findViewById(R.id.vpn);
- mEthernetGroup = (ViewGroup) findViewById(R.id.ethernet_combo);
- mEthernet = (ImageView) findViewById(R.id.ethernet);
- mEthernetDark = (ImageView) findViewById(R.id.ethernet_dark);
- mWifiGroup = (ViewGroup) findViewById(R.id.wifi_combo);
- mWifi = (ImageView) findViewById(R.id.wifi_signal);
- mWifiDark = (ImageView) findViewById(R.id.wifi_signal_dark);
- mWifiActivity = (ImageView) findViewById(R.id.wifi_inout);
- mAirplane = (ImageView) findViewById(R.id.airplane);
- mNoSims = (ImageView) findViewById(R.id.no_sims);
- mNoSimsDark = (ImageView) findViewById(R.id.no_sims_dark);
+ mVpn = findViewById(R.id.vpn);
+ mEthernetGroup = findViewById(R.id.ethernet_combo);
+ mEthernet = findViewById(R.id.ethernet);
+ mEthernetDark = findViewById(R.id.ethernet_dark);
+ mWifiGroup = findViewById(R.id.wifi_combo);
+ mWifi = findViewById(R.id.wifi_signal);
+ mWifiDark = findViewById(R.id.wifi_signal_dark);
+ mWifiActivityIn = findViewById(R.id.wifi_in);
+ mWifiActivityOut= findViewById(R.id.wifi_out);
+ mAirplane = findViewById(R.id.airplane);
+ mNoSims = findViewById(R.id.no_sims);
+ mNoSimsDark = findViewById(R.id.no_sims_dark);
mNoSimsCombo = findViewById(R.id.no_sims_combo);
mWifiAirplaneSpacer = findViewById(R.id.wifi_airplane_spacer);
mWifiSignalSpacer = findViewById(R.id.wifi_signal_spacer);
- mMobileSignalGroup = (LinearLayout) findViewById(R.id.mobile_signal_group);
+ mMobileSignalGroup = findViewById(R.id.mobile_signal_group);
maybeScaleVpnAndNoSimsIcons();
}
@@ -264,6 +269,10 @@
});
}
+ private void updateActivityEnabled() {
+ mActivityEnabled = mContext.getResources().getBoolean(R.bool.config_showActivity);
+ }
+
@Override
public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
boolean activityIn, boolean activityOut, String description, boolean isTransient) {
@@ -271,10 +280,8 @@
mWifiStrengthId = statusIcon.icon;
mWifiBadgeId = statusIcon.iconOverlay;
mWifiDescription = statusIcon.contentDescription;
- mWifiActivityId = activityIn && activityOut ? R.drawable.stat_sys_wifi_inout
- : activityIn ? R.drawable.stat_sys_wifi_in
- : activityOut ? R.drawable.stat_sys_wifi_out
- : 0;
+ mWifiIn = activityIn && mActivityEnabled;
+ mWifiOut = activityOut && mActivityEnabled;
apply();
}
@@ -294,10 +301,8 @@
state.mMobileTypeDescription = typeContentDescription;
state.mIsMobileTypeIconWide = statusType != 0 && isWide;
state.mRoaming = roaming;
- state.mMobileActivityId = activityIn && activityOut ? R.drawable.stat_sys_signal_inout
- : activityIn ? R.drawable.stat_sys_signal_in
- : activityOut ? R.drawable.stat_sys_signal_out
- : 0;
+ state.mActivityIn = activityIn && mActivityEnabled;
+ state.mActivityOut = activityOut && mActivityEnabled;
apply();
}
@@ -421,10 +426,6 @@
mLastWifiStrengthId = -1;
mLastWifiBadgeId = -1;
}
- if (mWifiActivity != null) {
- mWifiActivity.setImageDrawable(null);
- mLastWifiActivityId = -1;
- }
for (PhoneState state : mPhoneStates) {
if (state.mMobile != null) {
@@ -441,10 +442,6 @@
state.mMobileType.setImageDrawable(null);
state.mLastMobileTypeId = -1;
}
- if (state.mMobileActivity != null) {
- state.mMobileActivity.setImageDrawable(null);
- state.mLastMobileActivityId = -1;
- }
}
if (mAirplane != null) {
@@ -504,12 +501,6 @@
mLastWifiStrengthId = mWifiStrengthId;
mLastWifiBadgeId = mWifiBadgeId;
}
- if (mWifiActivityId != mLastWifiActivityId) {
- if (mWifiActivityId != 0) {
- setIconForView(mWifiActivity, mWifiActivityId);
- }
- mLastWifiActivityId = mWifiActivityId;
- }
mWifiGroup.setContentDescription(mWifiDescription);
mWifiGroup.setVisibility(View.VISIBLE);
} else {
@@ -521,7 +512,8 @@
(mWifiVisible ? "VISIBLE" : "GONE"),
mWifiStrengthId));
- mWifiActivity.setVisibility(mWifiActivityId != 0 ? View.VISIBLE : View.GONE);
+ mWifiActivityIn.setVisibility(mWifiIn ? View.VISIBLE : View.GONE);
+ mWifiActivityOut.setVisibility(mWifiOut ? View.VISIBLE : View.GONE);
boolean anyMobileVisible = false;
int firstMobileTypeId = 0;
@@ -631,8 +623,10 @@
applyDarkIntensity(
DarkIconDispatcher.getDarkIntensity(mTintArea, mWifi, mDarkIntensity),
mWifi, mWifiDark);
- setTint(mWifiActivity,
- DarkIconDispatcher.getTint(mTintArea, mWifiActivity, mIconTint));
+ setTint(mWifiActivityIn,
+ DarkIconDispatcher.getTint(mTintArea, mWifiActivityIn, mIconTint));
+ setTint(mWifiActivityOut,
+ DarkIconDispatcher.getTint(mTintArea, mWifiActivityOut, mIconTint));
applyDarkIntensity(
DarkIconDispatcher.getDarkIntensity(mTintArea, mEthernet, mDarkIntensity),
mEthernet, mEthernetDark);
@@ -657,7 +651,7 @@
private class PhoneState {
private final int mSubId;
private boolean mMobileVisible = false;
- private int mMobileStrengthId = 0, mMobileTypeId = 0, mMobileActivityId = 0;
+ private int mMobileStrengthId = 0, mMobileTypeId = 0;
private int mLastMobileStrengthId = -1;
private int mLastMobileTypeId = -1;
private int mLastMobileActivityId = -1;
@@ -667,7 +661,10 @@
private ViewGroup mMobileGroup;
private ImageView mMobile, mMobileDark, mMobileType, mMobileRoaming;
public boolean mRoaming;
- private ImageView mMobileActivity;
+ private ImageView mMobileActivityIn;
+ private ImageView mMobileActivityOut;
+ public boolean mActivityIn;
+ public boolean mActivityOut;
public PhoneState(int subId, Context context) {
ViewGroup root = (ViewGroup) LayoutInflater.from(context)
@@ -678,11 +675,12 @@
public void setViews(ViewGroup root) {
mMobileGroup = root;
- mMobile = (ImageView) root.findViewById(R.id.mobile_signal);
- mMobileDark = (ImageView) root.findViewById(R.id.mobile_signal_dark);
- mMobileType = (ImageView) root.findViewById(R.id.mobile_type);
- mMobileRoaming = (ImageView) root.findViewById(R.id.mobile_roaming);
- mMobileActivity = (ImageView) root.findViewById(R.id.mobile_inout);
+ mMobile = root.findViewById(R.id.mobile_signal);
+ mMobileDark = root.findViewById(R.id.mobile_signal_dark);
+ mMobileType = root.findViewById(R.id.mobile_type);
+ mMobileRoaming = root.findViewById(R.id.mobile_roaming);
+ mMobileActivityIn = root.findViewById(R.id.mobile_in);
+ mMobileActivityOut = root.findViewById(R.id.mobile_out);
}
public boolean apply(boolean isSecondaryIcon) {
@@ -698,10 +696,6 @@
mLastMobileTypeId = mMobileTypeId;
}
- if (mLastMobileActivityId != mMobileActivityId) {
- mMobileActivity.setImageResource(mMobileActivityId);
- mLastMobileActivityId = mMobileActivityId;
- }
mMobileGroup.setContentDescription(mMobileTypeDescription
+ " " + mMobileDescription);
mMobileGroup.setVisibility(View.VISIBLE);
@@ -724,7 +718,8 @@
mMobileType.setVisibility(mMobileTypeId != 0 ? View.VISIBLE : View.GONE);
mMobileRoaming.setVisibility(mRoaming ? View.VISIBLE : View.GONE);
- mMobileActivity.setVisibility(mMobileActivityId != 0 ? View.VISIBLE : View.GONE);
+ mMobileActivityIn.setVisibility(mActivityIn ? View.VISIBLE : View.GONE);
+ mMobileActivityOut.setVisibility(mActivityOut ? View.VISIBLE : View.GONE);
return mMobileVisible;
}
@@ -786,8 +781,10 @@
setTint(mMobileType, DarkIconDispatcher.getTint(tintArea, mMobileType, tint));
setTint(mMobileRoaming, DarkIconDispatcher.getTint(tintArea, mMobileRoaming,
tint));
- setTint(mMobileActivity,
- DarkIconDispatcher.getTint(tintArea, mMobileActivity, tint));
+ setTint(mMobileActivityIn,
+ DarkIconDispatcher.getTint(tintArea, mMobileActivityIn, tint));
+ setTint(mMobileActivityOut,
+ DarkIconDispatcher.getTint(tintArea, mMobileActivityOut, tint));
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
index d530759..6cbbd6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
@@ -40,8 +40,8 @@
@Override
public void onFinishInflate() {
- mNavButtons = (LinearLayout) findViewById(R.id.nav_buttons);
- mLightsOutButtons = (LinearLayout) findViewById(R.id.lights_out);
+ mNavButtons = findViewById(R.id.nav_buttons);
+ mLightsOutButtons = findViewById(R.id.lights_out);
}
public void addButton(CarNavigationButton button, CarNavigationButton lightsOutButton){
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
index f46fc67..2de358f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
@@ -41,13 +41,13 @@
@Override
public void onFinishInflate() {
super.onFinishInflate();
- mIcon = (AlphaOptimizedImageButton) findViewById(R.id.car_nav_button_icon);
+ mIcon = findViewById(R.id.car_nav_button_icon);
mIcon.setScaleType(ImageView.ScaleType.CENTER);
mIcon.setClickable(false);
mIcon.setBackgroundColor(android.R.color.transparent);
mIcon.setAlpha(UNSELECTED_ALPHA);
- mMoreIcon = (AlphaOptimizedImageButton) findViewById(R.id.car_nav_button_more_icon);
+ mMoreIcon = findViewById(R.id.car_nav_button_more_icon);
mMoreIcon.setClickable(false);
mMoreIcon.setBackgroundColor(android.R.color.transparent);
mMoreIcon.setVisibility(INVISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index a444934..c499619 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -81,7 +81,7 @@
}
String location = args.getString("location");
if (location != null) {
- int iconId = location.equals("show") ? LocationControllerImpl.LOCATION_STATUS_ICON_ID
+ int iconId = location.equals("show") ? PhoneStatusBarPolicy.LOCATION_STATUS_ICON_ID
: 0;
updateSlot("location", null, iconId);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 7b2e997..c3f8d97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -125,7 +125,7 @@
public boolean getSensorsWakeUpFully() {
return mAmbientDisplayConfiguration.alwaysOnAvailable()
&& Settings.Secure.getIntForUser(mContext.getContentResolver(),
- DOZE_SENSORS_WAKE_UP_FULLY, 1, UserHandle.USER_CURRENT) != 0;
+ DOZE_SENSORS_WAKE_UP_FULLY, 0, UserHandle.USER_CURRENT) != 0;
}
private boolean getBoolean(String propName, int resId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 9a49d67..41a60e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -227,14 +227,14 @@
protected void onFinishInflate() {
super.onFinishInflate();
mLockPatternUtils = new LockPatternUtils(mContext);
- mPreviewContainer = (ViewGroup) findViewById(R.id.preview_container);
- mRightAffordanceView = (KeyguardAffordanceView) findViewById(R.id.camera_button);
- mLeftAffordanceView = (KeyguardAffordanceView) findViewById(R.id.left_button);
- mLockIcon = (LockIcon) findViewById(R.id.lock_icon);
- mIndicationArea = (ViewGroup) findViewById(R.id.keyguard_indication_area);
- mEnterpriseDisclosure = (TextView) findViewById(
+ mPreviewContainer = findViewById(R.id.preview_container);
+ mRightAffordanceView = findViewById(R.id.camera_button);
+ mLeftAffordanceView = findViewById(R.id.left_button);
+ mLockIcon = findViewById(R.id.lock_icon);
+ mIndicationArea = findViewById(R.id.keyguard_indication_area);
+ mEnterpriseDisclosure = findViewById(
R.id.keyguard_indication_enterprise_disclosure);
- mIndicationText = (TextView) findViewById(R.id.keyguard_indication_text);
+ mIndicationText = findViewById(R.id.keyguard_indication_text);
watchForCameraPolicyChanges();
updateCameraVisibility();
mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 1f03024..fa404b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -64,6 +64,7 @@
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -78,6 +79,7 @@
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.KeyButtonView;
import com.android.systemui.statusbar.stack.StackStateAnimator;
@@ -138,14 +140,14 @@
mDivider = SysUiServiceProvider.getComponent(getContext(), Divider.class);
mWindowManager = getContext().getSystemService(WindowManager.class);
mAccessibilityManager = getContext().getSystemService(AccessibilityManager.class);
- mAccessibilityManager.addAccessibilityServicesStateChangeListener(
- this::updateAccessibilityServicesState);
+ Dependency.get(AccessibilityManagerWrapper.class).addCallback(
+ mAccessibilityListener);
mContentResolver = getContext().getContentResolver();
mMagnificationObserver = new MagnificationContentObserver(
getContext().getMainThreadHandler());
mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED), false,
- mMagnificationObserver);
+ mMagnificationObserver, UserHandle.USER_ALL);
if (savedInstanceState != null) {
mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0);
@@ -164,8 +166,8 @@
public void onDestroy() {
super.onDestroy();
mCommandQueue.removeCallbacks(this);
- mAccessibilityManager.removeAccessibilityServicesStateChangeListener(
- this::updateAccessibilityServicesState);
+ Dependency.get(AccessibilityManagerWrapper.class).removeCallback(
+ mAccessibilityListener);
mContentResolver.unregisterContentObserver(mMagnificationObserver);
try {
WindowManagerGlobal.getWindowManagerService()
@@ -559,20 +561,23 @@
private boolean onAccessibilityLongClick(View v) {
Intent intent = new Intent(AccessibilityManager.ACTION_CHOOSE_ACCESSIBILITY_BUTTON);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- v.getContext().startActivity(intent);
+ v.getContext().startActivityAsUser(intent, UserHandle.CURRENT);
return true;
}
private void updateAccessibilityServicesState() {
int requestingServices = 0;
try {
- if (Settings.Secure.getInt(mContentResolver,
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED) == 1) {
+ if (Settings.Secure.getIntForUser(mContentResolver,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
+ UserHandle.USER_CURRENT) == 1) {
requestingServices++;
}
} catch (Settings.SettingNotFoundException e) {
}
+ // AccessibilityManagerService resolves services for the current user since the local
+ // AccessibilityManager is created from a Context with the INTERACT_ACROSS_USERS permission
final List<AccessibilityServiceInfo> services =
mAccessibilityManager.getEnabledAccessibilityServiceList(
AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
@@ -622,6 +627,9 @@
mNavigationBarView.getBarTransitions().finishAnimations();
}
+ private final AccessibilityServicesStateChangeListener mAccessibilityListener =
+ this::updateAccessibilityServicesState;
+
private class MagnificationContentObserver extends ContentObserver {
public MagnificationContentObserver(Handler handler) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 307a8c7..f1b4498 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -231,9 +231,9 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header);
- mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view);
- mClockView = (TextView) findViewById(R.id.clock_view);
+ mKeyguardStatusBar = findViewById(R.id.keyguard_header);
+ mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
+ mClockView = findViewById(R.id.clock_view);
mNotificationContainerParent = (NotificationsQuickSettingsContainer)
findViewById(R.id.notification_container_parent);
@@ -242,13 +242,13 @@
mNotificationStackScroller.setOnHeightChangedListener(this);
mNotificationStackScroller.setOverscrollTopChangedListener(this);
mNotificationStackScroller.setOnEmptySpaceClickListener(this);
- mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
+ mKeyguardBottomArea = findViewById(R.id.keyguard_bottom_area);
mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
mAffordanceHelper = new KeyguardAffordanceHelper(this, getContext());
mKeyguardBottomArea.setAffordanceHelper(mAffordanceHelper);
mLastOrientation = getResources().getConfiguration().orientation;
- mQsFrame = (FrameLayout) findViewById(R.id.qs_frame);
+ mQsFrame = findViewById(R.id.qs_frame);
}
@Override
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 53ec8c5..5910557 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -73,6 +73,8 @@
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.LocationController;
+import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.RotationLockController;
import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
@@ -86,11 +88,13 @@
* strictly doesn't need to.
*/
public class PhoneStatusBarPolicy implements Callback, Callbacks,
- RotationLockControllerCallback, Listener,
+ RotationLockControllerCallback, Listener, LocationChangeCallback,
ZenModeController.Callback, DeviceProvisionedListener, KeyguardMonitor.Callback {
private static final String TAG = "PhoneStatusBarPolicy";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ public static final int LOCATION_STATUS_ICON_ID = R.drawable.stat_sys_location;
+
private final String mSlotCast;
private final String mSlotHotspot;
private final String mSlotBluetooth;
@@ -102,6 +106,7 @@
private final String mSlotRotate;
private final String mSlotHeadset;
private final String mSlotDataSaver;
+ private final String mSlotLocation;
private final Context mContext;
private final Handler mHandler = new Handler();
@@ -117,6 +122,7 @@
private final ZenModeController mZenController;
private final DeviceProvisionedController mProvisionedController;
private final KeyguardMonitor mKeyguardMonitor;
+ private final LocationController mLocationController;
private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
// Assume it's all good unless we hear otherwise. We don't always seem
@@ -147,6 +153,7 @@
mZenController = Dependency.get(ZenModeController.class);
mProvisionedController = Dependency.get(DeviceProvisionedController.class);
mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ mLocationController = Dependency.get(LocationController.class);
mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
@@ -160,7 +167,7 @@
mSlotRotate = context.getString(com.android.internal.R.string.status_bar_rotate);
mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);
mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver);
-
+ mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location);
// listen for broadcasts
IntentFilter filter = new IntentFilter();
@@ -229,6 +236,7 @@
mNextAlarm.addCallback(mNextAlarmCallback);
mDataSaver.addCallback(this);
mKeyguardMonitor.addCallback(this);
+ mLocationController.addCallback(this);
SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallbacks(this);
SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskListener);
@@ -252,6 +260,7 @@
mNextAlarm.removeCallback(mNextAlarmCallback);
mDataSaver.removeCallback(this);
mKeyguardMonitor.removeCallback(this);
+ mLocationController.removeCallback(this);
SysUiServiceProvider.getComponent(mContext, CommandQueue.class).removeCallbacks(this);
mContext.unregisterReceiver(mIntentReceiver);
@@ -265,6 +274,21 @@
updateVolumeZen();
}
+ @Override
+ public void onLocationActiveChanged(boolean active) {
+ updateLocation();
+ }
+
+ // Updates the status view based on the current state of location requests.
+ private void updateLocation() {
+ if (mLocationController.isLocationActive()) {
+ mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID,
+ mContext.getString(R.string.accessibility_location_active));
+ } else {
+ mIconController.removeIcon(mSlotLocation);
+ }
+ }
+
private void updateAlarm() {
final AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 4dc593b8..916b603 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -75,7 +75,7 @@
@Override
public void onFinishInflate() {
mBarTransitions.init();
- mBattery = (DarkReceiver) findViewById(R.id.battery);
+ mBattery = findViewById(R.id.battery);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 9304de5..d3cb6a4a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -6369,17 +6369,10 @@
.getIdentifier();
if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
&& mKeyguardManager.isDeviceLocked(userId)) {
- boolean canBypass = false;
- try {
- canBypass = ActivityManager.getService()
- .canBypassWorkChallenge(intent);
- } catch (RemoteException e) {
- }
- // For direct-boot aware activities, they can be shown when
- // the device is still locked without triggering the work
- // challenge.
- if ((!canBypass) && startWorkChallengeIfNecessary(userId,
- intent.getIntentSender(), notificationKey)) {
+ // TODO(b/28935539): should allow certain activities to
+ // bypass work challenge
+ if (startWorkChallengeIfNecessary(userId,
+ intent.getIntentSender(), notificationKey)) {
// Show work challenge, do not run PendingIntent and
// remove notification
return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
new file mode 100644
index 0000000..dfa5cbd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT 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.Context;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
+
+/**
+ * For mocking because AccessibilyManager is final for some reason...
+ */
+public class AccessibilityManagerWrapper implements
+ CallbackController<AccessibilityServicesStateChangeListener> {
+
+ private final AccessibilityManager mAccessibilityManager;
+
+ public AccessibilityManagerWrapper(Context context) {
+ mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
+ }
+
+ @Override
+ public void addCallback(AccessibilityServicesStateChangeListener listener) {
+ mAccessibilityManager.addAccessibilityServicesStateChangeListener(listener);
+ }
+
+ @Override
+ public void removeCallback(AccessibilityServicesStateChangeListener listener) {
+ mAccessibilityManager.removeAccessibilityServicesStateChangeListener(listener);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
index 9a5f1b8..8e8a285 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
@@ -16,22 +16,29 @@
package com.android.systemui.statusbar.policy;
-import com.android.systemui.statusbar.policy.LocationController.LocationSettingsChangeCallback;
+import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
-public interface LocationController extends CallbackController<LocationSettingsChangeCallback> {
+public interface LocationController extends CallbackController<LocationChangeCallback> {
+ boolean isLocationActive();
boolean isLocationEnabled();
boolean setLocationEnabled(boolean enabled);
/**
* A callback for change in location settings (the user has enabled/disabled location).
*/
- public interface LocationSettingsChangeCallback {
+ public interface LocationChangeCallback {
+ /**
+ * Called whenever location's state changes.
+ * @param active
+ */
+ default void onLocationActiveChanged(boolean active) {}
+
/**
* Called whenever location settings change.
*
* @param locationEnabled A value of true indicates that at least one type of location
* is enabled in settings.
*/
- void onLocationSettingsChanged(boolean locationEnabled);
+ default void onLocationSettingsChanged(boolean locationEnabled) {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index cc61605..3f5f5a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -41,9 +41,6 @@
* A controller to manage changes of location related states and update the views accordingly.
*/
public class LocationControllerImpl extends BroadcastReceiver implements LocationController {
- // The name of the placeholder corresponding to the location request status icon.
- // This string corresponds to config_statusBarIcons in core/res/res/values/config.xml.
- public static final int LOCATION_STATUS_ICON_ID = R.drawable.stat_sys_location;
private static final int[] mHighPowerRequestAppOpArray
= new int[] {AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION};
@@ -55,14 +52,12 @@
private boolean mAreActiveLocationRequests;
- private ArrayList<LocationSettingsChangeCallback> mSettingsChangeCallbacks =
- new ArrayList<LocationSettingsChangeCallback>();
+ private ArrayList<LocationChangeCallback> mSettingsChangeCallbacks =
+ new ArrayList<LocationChangeCallback>();
private final H mHandler = new H();
- public final String mSlotLocation;
public LocationControllerImpl(Context context, Looper bgLooper) {
mContext = context;
- mSlotLocation = mContext.getString(com.android.internal.R.string.status_bar_location);
// Register to listen for changes in location settings.
IntentFilter filter = new IntentFilter();
@@ -76,18 +71,17 @@
// Examine the current location state and initialize the status view.
updateActiveLocationRequests();
- refreshViews();
}
/**
* Add a callback to listen for changes in location settings.
*/
- public void addCallback(LocationSettingsChangeCallback cb) {
+ public void addCallback(LocationChangeCallback cb) {
mSettingsChangeCallbacks.add(cb);
mHandler.sendEmptyMessage(H.MSG_LOCATION_SETTINGS_CHANGED);
}
- public void removeCallback(LocationSettingsChangeCallback cb) {
+ public void removeCallback(LocationChangeCallback cb) {
mSettingsChangeCallbacks.remove(cb);
}
@@ -130,6 +124,11 @@
return mode != Settings.Secure.LOCATION_MODE_OFF;
}
+ @Override
+ public boolean isLocationActive() {
+ return mAreActiveLocationRequests;
+ }
+
/**
* Returns true if the current user is restricted from using location.
*/
@@ -170,22 +169,12 @@
return false;
}
- // Updates the status view based on the current state of location requests.
- private void refreshViews() {
- if (mAreActiveLocationRequests) {
- mStatusBarManager.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID,
- 0, mContext.getString(R.string.accessibility_location_active));
- } else {
- mStatusBarManager.removeIcon(mSlotLocation);
- }
- }
-
// Reads the active location requests and updates the status view if necessary.
private void updateActiveLocationRequests() {
boolean hadActiveLocationRequests = mAreActiveLocationRequests;
mAreActiveLocationRequests = areActiveHighPowerLocationRequests();
if (mAreActiveLocationRequests != hadActiveLocationRequests) {
- refreshViews();
+ mHandler.sendEmptyMessage(H.MSG_LOCATION_ACTIVE_CHANGED);
}
}
@@ -201,6 +190,7 @@
private final class H extends Handler {
private static final int MSG_LOCATION_SETTINGS_CHANGED = 1;
+ private static final int MSG_LOCATION_ACTIVE_CHANGED = 2;
@Override
public void handleMessage(Message msg) {
@@ -208,12 +198,21 @@
case MSG_LOCATION_SETTINGS_CHANGED:
locationSettingsChanged();
break;
+ case MSG_LOCATION_ACTIVE_CHANGED:
+ locationActiveChanged();
+ break;
+ }
+ }
+
+ private void locationActiveChanged() {
+ for (LocationChangeCallback cb : mSettingsChangeCallbacks) {
+ cb.onLocationActiveChanged(mAreActiveLocationRequests);
}
}
private void locationSettingsChanged() {
boolean isEnabled = isLocationEnabled();
- for (LocationSettingsChangeCallback cb : mSettingsChangeCallbacks) {
+ for (LocationChangeCallback cb : mSettingsChangeCallbacks) {
cb.onLocationSettingsChanged(isEnabled);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 784f25e..37b0de4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -101,9 +101,9 @@
protected void onFinishInflate() {
super.onFinishInflate();
- mProgressBar = (ProgressBar) findViewById(R.id.remote_input_progress);
+ mProgressBar = findViewById(R.id.remote_input_progress);
- mSendButton = (ImageButton) findViewById(R.id.remote_input_send);
+ mSendButton = findViewById(R.id.remote_input_send);
mSendButton.setOnClickListener(this);
mEditText = (RemoteEditText) getChildAt(0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitClockView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitClockView.java
index faa1a28a..9f61574 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitClockView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitClockView.java
@@ -59,8 +59,8 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mTimeView = (TextClock) findViewById(R.id.time_view);
- mAmPmView = (TextClock) findViewById(R.id.am_pm_view);
+ mTimeView = findViewById(R.id.time_view);
+ mAmPmView = findViewById(R.id.am_pm_view);
mTimeView.setShowCurrentUserTime(true);
mAmPmView.setShowCurrentUserTime(true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index ba91ffd..b5db78d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -495,12 +495,12 @@
int childCount = algorithmState.visibleChildren.size();
float childrenOnTop = 0.0f;
for (int i = childCount - 1; i >= 0; i--) {
- updateChildZValue(i, childrenOnTop,
+ childrenOnTop = updateChildZValue(i, childrenOnTop,
resultState, algorithmState, ambientState);
}
}
- protected void updateChildZValue(int i, float childrenOnTop,
+ protected float updateChildZValue(int i, float childrenOnTop,
StackScrollState resultState, StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
ExpandableView child = algorithmState.visibleChildren.get(i);
@@ -538,6 +538,7 @@
} else {
childViewState.zTranslation = baseZ;
}
+ return childrenOnTop;
}
public void setIsExpanded(boolean isExpanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index cfe16dd..c3a53de 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -387,7 +387,7 @@
.addAction(new Action(R.drawable.ic_eject_24dp,
mContext.getString(R.string.ext_media_unmount_action),
buildUnmountPendingIntent(vol)))
- .setContentIntent(buildUnmountPendingIntent(vol))
+ .setContentIntent(browseIntent)
.setCategory(Notification.CATEGORY_SYSTEM);
// Non-adoptable disks can't be snoozed.
if (disk.isAdoptable()) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
index 4e4832c..10b6ff5 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
@@ -60,10 +60,10 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mIcon = (ImageView) findViewById(R.id.volume_zen_icon);
- mSummaryLine1 = (TextView) findViewById(R.id.volume_zen_summary_line_1);
- mSummaryLine2 = (TextView) findViewById(R.id.volume_zen_summary_line_2);
- mEndNowButton = (TextView) findViewById(R.id.volume_zen_end_now);
+ mIcon = findViewById(R.id.volume_zen_icon);
+ mSummaryLine1 = findViewById(R.id.volume_zen_summary_line_1);
+ mSummaryLine2 = findViewById(R.id.volume_zen_summary_line_2);
+ mEndNowButton = findViewById(R.id.volume_zen_end_now);
mConfigurableTexts.add(mSummaryLine1);
mConfigurableTexts.add(mSummaryLine2);
mConfigurableTexts.add(mEndNowButton, R.string.volume_zen_end_now);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index 98e89e4..f7dfc0a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -36,6 +36,7 @@
import android.service.notification.ZenModeConfig.ZenRule;
import android.text.TextUtils;
import android.text.format.DateFormat;
+import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
@@ -45,6 +46,7 @@
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
@@ -55,6 +57,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Prefs;
import com.android.systemui.R;
+import com.android.systemui.R.string;
import com.android.systemui.statusbar.policy.ZenModeController;
import java.io.FileDescriptor;
@@ -65,10 +68,14 @@
import java.util.Locale;
import java.util.Objects;
-public class ZenModePanel extends LinearLayout {
+public class ZenModePanel extends FrameLayout {
private static final String TAG = "ZenModePanel";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ public static final int STATE_MODIFY = 0;
+ public static final int STATE_AUTO_RULE = 1;
+ public static final int STATE_OFF = 2;
+
private static final int SECONDS_MS = 1000;
private static final int MINUTES_MS = 60 * SECONDS_MS;
@@ -86,6 +93,8 @@
public static final Intent ZEN_PRIORITY_SETTINGS
= new Intent(Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS);
+ private static final long TRANSITION_DURATION = 300;
+
private final Context mContext;
protected final LayoutInflater mInflater;
private final H mHandler = new H();
@@ -124,6 +133,13 @@
protected int mZenModeConditionLayoutId;
protected int mZenModeButtonLayoutId;
+ private View mEmpty;
+ private TextView mEmptyText;
+ private ImageView mEmptyIcon;
+ private View mAutoRule;
+ private TextView mAutoTitle;
+ private int mState = STATE_MODIFY;
+ private ViewGroup mEdit;
public ZenModePanel(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -156,7 +172,7 @@
}
protected void createZenButtons() {
- mZenButtons = (SegmentedButtons) findViewById(R.id.zen_buttons);
+ mZenButtons = findViewById(R.id.zen_buttons);
mZenButtons.addButton(R.string.interruption_level_none_twoline,
R.string.interruption_level_none_with_warning,
Global.ZEN_MODE_NO_INTERRUPTIONS);
@@ -174,30 +190,75 @@
super.onFinishInflate();
createZenButtons();
mZenIntroduction = findViewById(R.id.zen_introduction);
- mZenIntroductionMessage = (TextView) findViewById(R.id.zen_introduction_message);
+ mZenIntroductionMessage = findViewById(R.id.zen_introduction_message);
mZenIntroductionConfirm = findViewById(R.id.zen_introduction_confirm);
- mZenIntroductionConfirm.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- confirmZenIntroduction();
- }
- });
- mZenIntroductionCustomize = (TextView) findViewById(R.id.zen_introduction_customize);
- mZenIntroductionCustomize.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- confirmZenIntroduction();
- if (mCallback != null) {
- mCallback.onPrioritySettings();
- }
+ mZenIntroductionConfirm.setOnClickListener(v -> confirmZenIntroduction());
+ mZenIntroductionCustomize = findViewById(R.id.zen_introduction_customize);
+ mZenIntroductionCustomize.setOnClickListener(v -> {
+ confirmZenIntroduction();
+ if (mCallback != null) {
+ mCallback.onPrioritySettings();
}
});
mConfigurableTexts.add(mZenIntroductionCustomize, R.string.zen_priority_customize_button);
- mZenConditions = (LinearLayout) findViewById(R.id.zen_conditions);
- mZenAlarmWarning = (TextView) findViewById(R.id.zen_alarm_warning);
- mZenRadioGroup = (RadioGroup) findViewById(R.id.zen_radio_buttons);
- mZenRadioGroupContent = (LinearLayout) findViewById(R.id.zen_radio_buttons_content);
+ mZenConditions = findViewById(R.id.zen_conditions);
+ mZenAlarmWarning = findViewById(R.id.zen_alarm_warning);
+ mZenRadioGroup = findViewById(R.id.zen_radio_buttons);
+ mZenRadioGroupContent = findViewById(R.id.zen_radio_buttons_content);
+
+ mEdit = findViewById(R.id.edit_container);
+
+ mEmpty = findViewById(android.R.id.empty);
+ mEmpty.setVisibility(INVISIBLE);
+ mEmptyText = mEmpty.findViewById(android.R.id.title);
+ mEmptyIcon = mEmpty.findViewById(android.R.id.icon);
+
+ mAutoRule = findViewById(R.id.auto_rule);
+ mAutoTitle = mAutoRule.findViewById(android.R.id.title);
+ mAutoRule.setVisibility(INVISIBLE);
+ }
+
+ public void setEmptyState(int icon, int text) {
+ mEmptyIcon.post(() -> {
+ mEmptyIcon.setImageResource(icon);
+ mEmptyText.setText(text);
+ });
+ }
+
+ public void setAutoText(CharSequence text) {
+ mAutoTitle.post(() -> mAutoTitle.setText(text));
+ }
+
+ public void setState(int state) {
+ if (mState == state) return;
+ transitionFrom(getView(mState), getView(state));
+ mState = state;
+ }
+
+ private void transitionFrom(View from, View to) {
+ from.post(() -> {
+ // TODO: Better transitions
+ to.setAlpha(0);
+ to.setVisibility(VISIBLE);
+ to.bringToFront();
+ to.animate().cancel();
+ to.animate().alpha(1)
+ .setDuration(TRANSITION_DURATION)
+ .withEndAction(() -> from.setVisibility(INVISIBLE))
+ .start();
+ });
+ }
+
+ private View getView(int state) {
+ switch (state) {
+ case STATE_AUTO_RULE:
+ return mAutoRule;
+ case STATE_OFF:
+ return mEmpty;
+ default:
+ return mEdit;
+ }
}
@Override
@@ -232,6 +293,7 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (DEBUG) Log.d(mTag, "onAttachedToWindow");
+ setExpanded(true);
mAttached = true;
mAttachedZen = getSelectedZen(-1);
mSessionZen = mAttachedZen;
@@ -246,6 +308,7 @@
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (DEBUG) Log.d(mTag, "onDetachedFromWindow");
+ setExpanded(false);
checkForAttachedZenChange();
mAttached = false;
mAttachedZen = -1;
@@ -285,7 +348,7 @@
if (expanded == mExpanded) return;
if (DEBUG) Log.d(mTag, "setExpanded " + expanded);
mExpanded = expanded;
- if (mExpanded && isShown()) {
+ if (mExpanded) {
ensureSelection();
}
updateWidgets();
@@ -317,10 +380,10 @@
protected void addZenConditions(int count) {
for (int i = 0; i < count; i++) {
- final View rb = mInflater.inflate(mZenModeButtonLayoutId, this, false);
+ final View rb = mInflater.inflate(mZenModeButtonLayoutId, mEdit, false);
rb.setId(i);
mZenRadioGroup.addView(rb);
- final View rbc = mInflater.inflate(mZenModeConditionLayoutId, this, false);
+ final View rbc = mInflater.inflate(mZenModeConditionLayoutId, mEdit, false);
rbc.setId(i + count);
mZenRadioGroupContent.addView(rbc);
}
@@ -368,13 +431,26 @@
private void handleUpdateManualRule(ZenRule rule) {
final int zen = rule != null ? rule.zenMode : Global.ZEN_MODE_OFF;
handleUpdateZen(zen);
- final Condition c = rule != null ? rule.condition : null;
+ final Condition c = rule == null ? null
+ : rule.condition != null ? rule.condition
+ : createCondition(rule.conditionId);
handleExitConditionChanged(c);
}
+ private Condition createCondition(Uri conditionId) {
+ if (ZenModeConfig.isValidCountdownConditionId(conditionId)) {
+ long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
+ int mins = (int) ((time - System.currentTimeMillis() + DateUtils.MINUTE_IN_MILLIS / 2)
+ / DateUtils.MINUTE_IN_MILLIS);
+ Condition c = ZenModeConfig.toTimeCondition(mContext, time, mins,
+ ActivityManager.getCurrentUser(), false);
+ return c;
+ }
+ return null;
+ }
+
private void handleUpdateZen(int zen) {
if (mSessionZen != -1 && mSessionZen != zen) {
- setExpanded(isShown());
mSessionZen = zen;
}
mZenButtons.setSelectedValue(zen, false /* fromClick */);
@@ -391,15 +467,20 @@
private void handleExitConditionChanged(Condition exitCondition) {
setExitCondition(exitCondition);
if (DEBUG) Log.d(mTag, "handleExitConditionChanged " + mExitCondition);
+ if (exitCondition == null) return;
final int N = getVisibleConditions();
for (int i = 0; i < N; i++) {
final ConditionTag tag = getConditionTagAt(i);
- if (tag != null) {
- if (sameConditionId(tag.condition, mExitCondition)) {
- bind(exitCondition, mZenRadioGroupContent.getChildAt(i), i);
- }
+ if (tag != null && sameConditionId(tag.condition, mExitCondition)) {
+ bind(exitCondition, mZenRadioGroupContent.getChildAt(i), i);
+ return;
}
}
+ if (mCountdownConditionSupported && ZenModeConfig.isValidCountdownConditionId(
+ exitCondition.id)) {
+ bind(exitCondition, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
+ COUNTDOWN_CONDITION_INDEX);
+ }
}
private Condition getSelectedCondition() {
@@ -519,7 +600,7 @@
}
}
// ensure something is selected
- if (mExpanded && isShown()) {
+ if (mExpanded) {
ensureSelection();
}
mZenConditions.setVisibility(mSessionZen != Global.ZEN_MODE_OFF ? View.VISIBLE : View.GONE);
@@ -597,7 +678,9 @@
if (foreverTag == null) return;
if (DEBUG) Log.d(mTag, "Selecting a default");
final int favoriteIndex = mPrefs.getMinuteIndex();
- if (favoriteIndex == -1 || !mCountdownConditionSupported) {
+ if (mExitCondition != null && mExitCondition.equals(mTimeCondition)) {
+ getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);
+ } else if (favoriteIndex == -1 || !mCountdownConditionSupported) {
foreverTag.rb.setChecked(true);
} else {
mTimeCondition = ZenModeConfig.toTimeCondition(mContext,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java b/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java
index 6b47ada..e1f56a47 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java
@@ -53,7 +53,7 @@
@Test
public void testDrawImageButNoTextIfPluggedIn() {
mBatteryMeter.setBatteryLevel(0);
- mBatteryMeter.setPluggedIn(true);
+ mBatteryMeter.setCharging(true);
final Canvas canvas = mock(Canvas.class);
mBatteryMeter.draw(canvas);
verify(canvas, atLeastOnce()).drawPath(any(), any());
@@ -63,7 +63,7 @@
@Test
public void testDrawTextIfNotPluggedIn() {
mBatteryMeter.setBatteryLevel(0);
- mBatteryMeter.setPluggedIn(false);
+ mBatteryMeter.setCharging(false);
final Canvas canvas = mock(Canvas.class);
mBatteryMeter.draw(canvas);
verify(canvas, times(1)).drawText(anyString(), anyFloat(), anyFloat(), any());
@@ -72,7 +72,7 @@
@Test
public void testDrawNoTextIfPowerSaveEnabled() {
mBatteryMeter.setBatteryLevel(0);
- mBatteryMeter.setPluggedIn(false);
+ mBatteryMeter.setCharging(false);
mBatteryMeter.setPowerSave(true);
final Canvas canvas = mock(Canvas.class);
mBatteryMeter.draw(canvas);
@@ -84,7 +84,7 @@
int criticalLevel = mResources.getInteger(
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
mBatteryMeter.setBatteryLevel(criticalLevel);
- mBatteryMeter.setPluggedIn(false);
+ mBatteryMeter.setCharging(false);
final Canvas canvas = mock(Canvas.class);
mBatteryMeter.draw(canvas);
String warningString = mResources.getString(R.string.battery_meter_very_low_overlay_symbol);
@@ -96,7 +96,7 @@
int criticalLevel = mResources.getInteger(
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
mBatteryMeter.setBatteryLevel(criticalLevel + 1);
- mBatteryMeter.setPluggedIn(false);
+ mBatteryMeter.setCharging(false);
final Canvas canvas = mock(Canvas.class);
mBatteryMeter.draw(canvas);
String warningString = mResources.getString(R.string.battery_meter_very_low_overlay_symbol);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
new file mode 100644
index 0000000..1b5d4a4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui;
+
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationTestHelper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ExpandHelperTest extends SysuiTestCase {
+
+ private ExpandableNotificationRow mRow;
+ private ExpandHelper mExpandHelper;
+ private ExpandHelper.Callback mCallback;
+
+ @Before
+ @UiThreadTest
+ public void setUp() {
+ Context context = getContext();
+ mRow = new NotificationTestHelper(context).createRow();
+ mCallback = mock(ExpandHelper.Callback.class);
+ mExpandHelper = new ExpandHelper(context, mCallback, 10, 100);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testAnimationDoesntClearViewIfNewExpansionStarted() {
+ when(mCallback.getMaxExpandHeight(any())).thenReturn(100);
+ mExpandHelper.startExpanding(mRow, 0);
+ mExpandHelper.finishExpanding(false, 0);
+ mExpandHelper.startExpanding(mRow, 0);
+ ObjectAnimator scaleAnimation = mExpandHelper.getScaleAnimation();
+ scaleAnimation.end();
+ mExpandHelper.updateExpansion();
+ }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 2bb7f3b..66385a1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -61,6 +61,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import java.util.ArrayList;
import java.util.Arrays;
@@ -585,11 +586,16 @@
mNotificationChannel.getImportance(), mSbn, null, null, null,
null, Collections.singleton(TEST_PACKAGE_NAME));
- Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
+ Switch enabledSwitch = mNotificationInfo.findViewById(R.id.channel_enabled_switch);
enabledSwitch.setChecked(false);
mNotificationInfo.handleCloseControls(true);
+
+ ArgumentCaptor<NotificationChannel> updated =
+ ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
- eq(TEST_PACKAGE_NAME), anyInt(), eq(mNotificationChannel));
+ anyString(), anyInt(), updated.capture());
+ assertTrue((updated.getValue().getUserLockedFields()
+ & NotificationChannel.USER_LOCKED_IMPORTANCE) != 0);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
index efb9fea4..9249df6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
@@ -14,6 +14,8 @@
package com.android.systemui.statusbar;
+import static junit.framework.Assert.assertTrue;
+
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
@@ -49,6 +51,8 @@
public void testRecreateMenu() {
NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
row.createMenu(null);
+ assertTrue(row.getMenuView() != null);
row.createMenu(null);
+ assertTrue(row.getMenuView() != null);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index e7cdcb5..53d842a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -14,12 +14,14 @@
package com.android.systemui.statusbar.phone;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.Looper;
import android.testing.AndroidTestingRunner;
+import android.testing.LeakCheck.Tracker;
import android.view.Display;
import android.view.WindowManager;
@@ -29,11 +31,18 @@
import com.android.systemui.recents.Recents;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
+import com.android.systemui.utils.leaks.BaseLeakChecker;
+
import android.testing.TestableLooper.RunWithLooper;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
@RunWith(AndroidTestingRunner.class)
@RunWithLooper(setAsMainLooper = true)
@@ -56,6 +65,20 @@
when(windowManager.getDefaultDisplay()).thenReturn(
defaultDisplay);
mContext.addMockSystemService(Context.WINDOW_SERVICE, windowManager);
+
+ Tracker tracker = mLeakCheck.getTracker("accessibility_manager");
+ AccessibilityManagerWrapper wrapper = new AccessibilityManagerWrapper(mContext) {
+ @Override
+ public void addCallback(AccessibilityServicesStateChangeListener listener) {
+ tracker.getLeakInfo(listener).addAllocation(new Throwable());
+ }
+
+ @Override
+ public void removeCallback(AccessibilityServicesStateChangeListener listener) {
+ tracker.getLeakInfo(listener).clearAllocations();
+ }
+ };
+ mDependency.injectTestDependency(AccessibilityManagerWrapper.class, wrapper);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeLocationController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeLocationController.java
index 29d7f1c..838a273 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeLocationController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeLocationController.java
@@ -17,15 +17,20 @@
import android.testing.LeakCheck;
import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.LocationController.LocationSettingsChangeCallback;
+import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
-public class FakeLocationController extends BaseLeakChecker<LocationSettingsChangeCallback>
+public class FakeLocationController extends BaseLeakChecker<LocationChangeCallback>
implements LocationController {
public FakeLocationController(LeakCheck test) {
super(test, "location");
}
@Override
+ public boolean isLocationActive() {
+ return false;
+ }
+
+ @Override
public boolean isLocationEnabled() {
return false;
}
diff --git a/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ClientTest.java b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ClientTest.java
index 78fd174..63b6a11 100644
--- a/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ClientTest.java
+++ b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ClientTest.java
@@ -49,21 +49,21 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
- Button addpbtn = (Button) findViewById(R.id.addpkg);
- Button procbtn = (Button) findViewById(R.id.procmsg);
- Button delbtn = (Button) findViewById(R.id.delpkg);
+ Button addpbtn = findViewById(R.id.addpkg);
+ Button procbtn = findViewById(R.id.procmsg);
+ Button delbtn = findViewById(R.id.delpkg);
Log.v(LOG_TAG, "activity created!!");
addpbtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
- EditText app_id = (EditText) findViewById(R.id.app_id);
- EditText cont = (EditText) findViewById(R.id.cont);
- EditText pkg = (EditText) findViewById(R.id.pkg);
- EditText cls = (EditText) findViewById(R.id.cls);
- RadioButton act = (RadioButton) findViewById(R.id.act);
- CheckBox sig = (CheckBox) findViewById(R.id.sig);
- CheckBox ftr = (CheckBox) findViewById(R.id.ftr);
+ EditText app_id = findViewById(R.id.app_id);
+ EditText cont = findViewById(R.id.cont);
+ EditText pkg = findViewById(R.id.pkg);
+ EditText cls = findViewById(R.id.cls);
+ RadioButton act = findViewById(R.id.act);
+ CheckBox sig = findViewById(R.id.sig);
+ CheckBox ftr = findViewById(R.id.ftr);
try {
if (!mWapPushMan.addPackage(
@@ -93,11 +93,11 @@
delbtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
- EditText app_id = (EditText) findViewById(R.id.app_id);
- EditText cont = (EditText) findViewById(R.id.cont);
- EditText pkg = (EditText) findViewById(R.id.pkg);
- EditText cls = (EditText) findViewById(R.id.cls);
- // CheckBox delall = (CheckBox) findViewById(R.id.delall);
+ EditText app_id = findViewById(R.id.app_id);
+ EditText cont = findViewById(R.id.cont);
+ EditText pkg = findViewById(R.id.pkg);
+ EditText cls = findViewById(R.id.cls);
+ // CheckBox delall = findViewById(R.id.delall);
// Log.d(LOG_TAG, "button clicked");
try {
@@ -115,9 +115,9 @@
procbtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
- EditText pdu = (EditText) findViewById(R.id.pdu);
- EditText app_id = (EditText) findViewById(R.id.app_id);
- EditText cont = (EditText) findViewById(R.id.cont);
+ EditText pdu = findViewById(R.id.pdu);
+ EditText app_id = findViewById(R.id.app_id);
+ EditText cont = findViewById(R.id.cont);
// WapPushOverSms wap = new WapPushOverSms();
// wap.dispatchWapPdu(strToHex(pdu.getText().toString()));
diff --git a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
index a319beb..f878b4d 100644
--- a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
+++ b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
@@ -88,7 +88,7 @@
protected void init() {
setContentView(R.layout.wallpaper_cropper);
- mCropView = (CropView) findViewById(R.id.cropView);
+ mCropView = findViewById(R.id.cropView);
Intent cropIntent = getIntent();
final Uri imageUri = cropIntent.getData();
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 579c54c..f56cbdd 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3906,6 +3906,11 @@
// OS: O
FINGERPRINT_REMOVE_SIDECAR = 934;
+ // OPEN: Settings > Storage > Movies & TV
+ // CATEGORY: SETTINGS
+ // OS: O
+ APPLICATIONS_STORAGE_MOVIES = 935;
+
// ---- End O Constants, all O constants go above this line ----
// Add new aosp constants above this line.
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index c4a2831..65cc17e 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -173,6 +173,9 @@
// Package: android
NOTE_ACCOUNT_CREDENTIAL_PERMISSION = 38;
+ // Inform the user their phone recently shut down due to high temperature
+ NOTE_THERMAL_SHUTDOWN = 39;
+
// ADD_NEW_IDS_ABOVE_THIS_LINE
// Legacy IDs with arbitrary values appear below
// Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/samples/training/network-usage/src/com/example/android/networkusage/NetworkActivity.java b/samples/training/network-usage/src/com/example/android/networkusage/NetworkActivity.java
index b7ed331..27d230b 100644
--- a/samples/training/network-usage/src/com/example/android/networkusage/NetworkActivity.java
+++ b/samples/training/network-usage/src/com/example/android/networkusage/NetworkActivity.java
@@ -158,7 +158,7 @@
setContentView(R.layout.main);
// The specified network connection is not available. Displays error message.
- WebView myWebView = (WebView) findViewById(R.id.webview);
+ WebView myWebView = findViewById(R.id.webview);
myWebView.loadData(getResources().getString(R.string.connection_error),
"text/html", null);
}
@@ -205,7 +205,7 @@
protected void onPostExecute(String result) {
setContentView(R.layout.main);
// Displays the HTML string in the UI via a WebView
- WebView myWebView = (WebView) findViewById(R.id.webview);
+ WebView myWebView = findViewById(R.id.webview);
myWebView.loadData(result, "text/html", null);
}
}
diff --git a/services/Android.mk b/services/Android.mk
index 4452543..a4c891b 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -40,8 +40,8 @@
# The convention is to name each service module 'services.$(module_name)'
LOCAL_STATIC_JAVA_LIBRARIES := $(addprefix services.,$(services)) \
- android.hidl.base@1.0-java-static \
- android.hardware.biometrics.fingerprint@2.1-java-static
+ android.hidl.base-V1.0-java-static \
+ android.hardware.biometrics.fingerprint-V2.1-java-static
ifeq ($(EMMA_INSTRUMENT_FRAMEWORK),true)
LOCAL_EMMA_INSTRUMENT := true
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index cb6d4df..0003941 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1586,7 +1586,7 @@
private void showAccessibilityButtonTargetSelection() {
Intent intent = new Intent(AccessibilityManager.ACTION_CHOOSE_ACCESSIBILITY_BUTTON);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- mContext.startActivity(intent);
+ mContext.startActivityAsUser(intent, UserHandle.of(mCurrentUserId));
}
private void scheduleNotifyClientsOfServicesStateChange(UserState userState) {
@@ -2036,10 +2036,16 @@
}
if (!shortcutServiceIsInstalled) {
userState.mServiceToEnableWithShortcut = null;
- Settings.Secure.putStringForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, null, userState.mUserId);
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 0, userState.mUserId);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, null, userState.mUserId);
+
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 0, userState.mUserId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 89645f4..d6f5256 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -24,6 +24,8 @@
import static com.android.server.autofill.Helper.bundleToString;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -35,6 +37,7 @@
import android.database.ContentObserver;
import android.graphics.Rect;
import android.net.Uri;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -194,15 +197,29 @@
*/
@NonNull
AutofillManagerServiceImpl getServiceForUserLocked(int userId) {
- AutofillManagerServiceImpl service = mServicesCache.get(userId);
+ final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, false, false, null, null);
+ AutofillManagerServiceImpl service = mServicesCache.get(resolvedUserId);
if (service == null) {
- service = new AutofillManagerServiceImpl(mContext, mLock,
- mRequestsHistory, userId, mUi, mDisabledUsers.get(userId));
+ service = new AutofillManagerServiceImpl(mContext, mLock, mRequestsHistory,
+ resolvedUserId, mUi, mDisabledUsers.get(resolvedUserId));
mServicesCache.put(userId, service);
}
return service;
}
+ /**
+ * Peeks the service instance for a user.
+ *
+ * @return service instance or null if not already present
+ */
+ @Nullable
+ AutofillManagerServiceImpl peekServiceForUserLocked(int userId) {
+ final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, false, false, null, null);
+ return mServicesCache.get(resolvedUserId);
+ }
+
// Called by Shell command.
void requestSaveForUser(int userId) {
Slog.i(TAG, "requestSaveForUser(): " + userId);
@@ -210,7 +227,7 @@
final IBinder activityToken = getTopActivityForUser();
if (activityToken != null) {
synchronized (mLock) {
- final AutofillManagerServiceImpl service = mServicesCache.get(userId);
+ final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
if (service == null) {
Log.w(TAG, "handleSaveForUser(): no cached service for userId " + userId);
return;
@@ -228,7 +245,10 @@
synchronized (mLock) {
if (userId != UserHandle.USER_ALL) {
- mServicesCache.get(userId).destroySessionsLocked();
+ AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ if (service != null) {
+ service.destroySessionsLocked();
+ }
} else {
final int size = mServicesCache.size();
for (int i = 0; i < size; i++) {
@@ -253,7 +273,10 @@
synchronized (mLock) {
if (userId != UserHandle.USER_ALL) {
- mServicesCache.get(userId).listSessionsLocked(sessions);
+ AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ if (service != null) {
+ service.listSessionsLocked(sessions);
+ }
} else {
final int size = mServicesCache.size();
for (int i = 0; i < size; i++) {
@@ -287,7 +310,7 @@
* Removes a cached service for a given user.
*/
private void removeCachedServiceLocked(int userId) {
- final AutofillManagerServiceImpl service = mServicesCache.get(userId);
+ final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
if (service != null) {
mServicesCache.delete(userId);
service.destroyLocked();
@@ -305,7 +328,7 @@
* Updates a cached service for a given user.
*/
private void updateCachedServiceLocked(int userId, boolean disabled) {
- AutofillManagerServiceImpl service = mServicesCache.get(userId);
+ AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
if (service != null) {
service.updateLocked(disabled);
}
@@ -409,8 +432,7 @@
public void updateSession(int sessionId, AutofillId id, Rect bounds,
AutofillValue value, int flags, int userId) {
synchronized (mLock) {
- final AutofillManagerServiceImpl service = mServicesCache.get(
- UserHandle.getCallingUserId());
+ final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
if (service != null) {
service.updateSessionLocked(sessionId, getCallingUid(), id, bounds, value,
flags);
@@ -421,8 +443,7 @@
@Override
public void finishSession(int sessionId, int userId) {
synchronized (mLock) {
- final AutofillManagerServiceImpl service = mServicesCache.get(
- UserHandle.getCallingUserId());
+ final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
if (service != null) {
service.finishSessionLocked(sessionId, getCallingUid());
}
@@ -432,8 +453,7 @@
@Override
public void cancelSession(int sessionId, int userId) {
synchronized (mLock) {
- final AutofillManagerServiceImpl service = mServicesCache.get(
- UserHandle.getCallingUserId());
+ final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
if (service != null) {
service.cancelSessionLocked(sessionId, getCallingUid());
}
@@ -441,6 +461,16 @@
}
@Override
+ public void disableOwnedAutofillServices(int userId) {
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+ if (service != null) {
+ service.disableOwnedAutofillServicesLocked(Binder.getCallingUid());
+ }
+ }
+ }
+
+ @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
synchronized (mLock) {
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 94d534a..63bf373 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -43,6 +43,7 @@
import android.os.Looper;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.service.autofill.AutofillService;
@@ -348,6 +349,25 @@
session.removeSelfLocked();
}
+ void disableOwnedAutofillServicesLocked(int uid) {
+ if (mInfo == null || mInfo.getServiceInfo().applicationInfo.uid
+ != UserHandle.getAppId(uid)) {
+ return;
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ final String autoFillService = getComponentNameFromSettings();
+ if (mInfo.getServiceInfo().getComponentName().equals(
+ ComponentName.unflattenFromString(autoFillService))) {
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ Settings.Secure.AUTOFILL_SERVICE, null, mUserId);
+ destroySessionsLocked();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
private Session createSessionByTokenLocked(@NonNull IBinder activityToken, int uid,
@Nullable IBinder windowToken, @NonNull IBinder appCallbackToken, boolean hasCallback,
int flags, @NonNull String packageName) {
@@ -474,20 +494,6 @@
mSessions.clear();
}
- void disableSelf() {
- final long identity = Binder.clearCallingIdentity();
- try {
- final String autoFillService = getComponentNameFromSettings();
- if (mInfo.getServiceInfo().getComponentName().equals(
- ComponentName.unflattenFromString(autoFillService))) {
- Settings.Secure.putStringForUser(mContext.getContentResolver(),
- Settings.Secure.AUTOFILL_SERVICE, null, mUserId);
- }
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
CharSequence getServiceLabel() {
return mInfo.getServiceInfo().loadLabel(mContext.getPackageManager());
}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index 003c8f1..dd520ac 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -35,7 +35,6 @@
import android.service.autofill.AutofillService;
import android.service.autofill.FillResponse;
import android.service.autofill.IAutoFillService;
-import android.service.autofill.IAutoFillServiceConnection;
import android.service.autofill.IFillCallback;
import android.service.autofill.ISaveCallback;
import android.text.format.DateUtils;
@@ -96,7 +95,6 @@
void onSaveRequestFailure(@Nullable CharSequence message,
@NonNull String servicePackageName);
void onServiceDied(RemoteFillService service);
- void onDisableSelf();
}
public RemoteFillService(Context context, ComponentName componentName,
@@ -203,10 +201,6 @@
}
}
- private void handleDisableSelf() {
- mCallbacks.onDisableSelf();
- }
-
private boolean isBound() {
return mAutoFillService != null;
}
@@ -246,7 +240,7 @@
mBinding = false;
if (isBound()) {
try {
- mAutoFillService.onInit(null);
+ mAutoFillService.onConnectedStateChanged(false);
} catch (Exception e) {
Slog.w(LOG_TAG, "Exception calling onDisconnected(): " + e);
}
@@ -322,12 +316,7 @@
return;
}
try {
- mAutoFillService.onInit(new IAutoFillServiceConnection.Stub() {
- @Override
- public void disableSelf() {
- mHandler.obtainMessage(MyHandler.MSG_ON_DISABLE_SELF).sendToTarget();
- }
- });
+ mAutoFillService.onConnectedStateChanged(true);
} catch (RemoteException e) {
Slog.w(LOG_TAG, "Exception calling onConnected(): " + e);
}
@@ -353,7 +342,6 @@
public static final int MSG_BINDER_DIED = 2;
public static final int MSG_UNBIND = 3;
public static final int MSG_ON_PENDING_REQUEST = 4;
- public static final int MSG_ON_DISABLE_SELF = 5;
public MyHandler(Context context) {
// Cannot use lambda - doesn't compile
@@ -381,10 +369,6 @@
case MSG_ON_PENDING_REQUEST: {
handlePendingRequest((PendingRequest) message.obj);
} break;
-
- case MSG_ON_DISABLE_SELF: {
- handleDisableSelf();
- } break;
}
}
}, false);
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 3ef9cd5..0b1381e 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -311,15 +311,6 @@
// FillServiceCallbacks
@Override
- public void onDisableSelf() {
- mService.disableSelf();
- synchronized (mLock) {
- removeSelfLocked();
- }
- }
-
- // FillServiceCallbacks
- @Override
public void onServiceDied(RemoteFillService service) {
// TODO(b/33197203): implement
}
@@ -379,6 +370,23 @@
}
}
+ // AutoFillUiCallback
+ @Override
+ public void startIntentSender(IntentSender intentSender) {
+ synchronized (mLock) {
+ removeSelfLocked();
+ }
+ mHandlerCaller.getHandler().post(() -> {
+ try {
+ synchronized (mLock) {
+ mClient.startIntentSender(intentSender);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error launching auth intent", e);
+ }
+ });
+ }
+
public void setAuthenticationResultLocked(Bundle data) {
if ((mResponseWaitingAuth == null && mDatasetWaitingAuth == null) || data == null) {
removeSelf();
@@ -578,7 +586,7 @@
}
viewState = new ViewState(this, id, value, this, ViewState.STATE_INITIAL);
mViewStates.put(id, viewState);
- } else if ((flags & FLAG_VIEW_ENTERED) != 0) {
+ } else if (mStructure != null && (flags & FLAG_VIEW_ENTERED) != 0) {
viewState = startPartitionLocked(id, value);
} else {
if (VERBOSE) Slog.v(TAG, "Ignored " + getFlagAsString(flags) + " for " + id);
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 64dee58..4449da9 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -28,7 +28,6 @@
import android.service.autofill.FillResponse;
import android.service.autofill.SaveInfo;
import android.text.TextUtils;
-import android.text.format.DateUtils;
import android.util.Slog;
import android.view.autofill.AutofillId;
import android.view.autofill.IAutofillWindowPresenter;
@@ -50,8 +49,6 @@
public final class AutoFillUI {
private static final String TAG = "AutoFillUI";
- private static final int MAX_SAVE_TIMEOUT_MS = (int) (30 * DateUtils.SECOND_IN_MILLIS);
-
private final Handler mHandler = UiThread.getHandler();
private final @NonNull Context mContext;
@@ -60,7 +57,6 @@
private @Nullable AutoFillUiCallback mCallback;
- private int mSaveTimeoutMs = (int) (5 * DateUtils.SECOND_IN_MILLIS);
private final MetricsLogger mMetricsLogger = new MetricsLogger();
public interface AutoFillUiCallback {
@@ -71,6 +67,7 @@
void requestShowFillUi(AutofillId id, int width, int height,
IAutofillWindowPresenter presenter);
void requestHideFillUi(AutofillId id);
+ void startIntentSender(IntentSender intentSender);
}
public AutoFillUI(@NonNull Context context) {
@@ -205,6 +202,13 @@
mCallback.requestHideFillUi(focusedId);
}
}
+
+ @Override
+ public void startIntentSender(IntentSender intentSender) {
+ if (mCallback != null) {
+ mCallback.startIntentSender(intentSender);
+ }
+ }
});
});
}
@@ -273,22 +277,11 @@
mHandler.post(this::hideAllUiThread);
}
- public void setSaveTimeout(int timeout) {
- if (timeout > MAX_SAVE_TIMEOUT_MS) {
- throw new IllegalArgumentException("Maximum value is " + MAX_SAVE_TIMEOUT_MS + "ms");
- }
- if (timeout <= 0) {
- throw new IllegalArgumentException("Must be a positive value");
- }
- mSaveTimeoutMs = timeout;
- }
-
public void dump(PrintWriter pw) {
pw.println("Autofill UI");
final String prefix = " ";
final String prefix2 = " ";
pw.print(prefix); pw.print("showsSaveUi: "); pw.println(mSaveUi != null);
- pw.print(prefix); pw.print("save timeout: "); pw.println(mSaveTimeoutMs);
if (mFillUi != null) {
pw.print(prefix); pw.println("showsFillUi: true");
mFillUi.dump(pw, prefix2);
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index b69d1dc..b68e3b1 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -17,7 +17,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.PendingIntent;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentSender;
import android.graphics.Rect;
import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
@@ -55,6 +58,7 @@
void requestShowFillUi(int width, int height,
IAutofillWindowPresenter windowPresenter);
void requestHideFillUi();
+ void startIntentSender(IntentSender intentSender);
}
private final @NonNull AutofillWindowPresenter mWindowPresenter =
@@ -69,7 +73,6 @@
private final @Nullable ArrayAdapter<ViewItem> mAdapter;
private @Nullable String mFilterText;
- private final String mAccessibilityTitle;
private int mContentWidth;
private int mContentHeight;
@@ -81,7 +84,20 @@
@NonNull Callback callback) {
mCallback = callback;
- mAccessibilityTitle = context.getString(R.string.autofill_picker_accessibility_title);
+ final LayoutInflater inflater = LayoutInflater.from(context);
+ final ViewGroup decor = (ViewGroup) inflater.inflate(
+ R.layout.autofill_dataset_picker, null);
+
+ final RemoteViews.OnClickHandler interceptionHandler = new RemoteViews.OnClickHandler() {
+ @Override
+ public boolean onClickHandler(View view, PendingIntent pendingIntent,
+ Intent fillInIntent) {
+ if (pendingIntent != null) {
+ mCallback.startIntentSender(pendingIntent.getIntentSender());
+ }
+ return true;
+ }
+ };
if (response.getAuthentication() != null) {
mListView = null;
@@ -89,23 +105,23 @@
final View content;
try {
- content = response.getPresentation().apply(context, null);
+ content = response.getPresentation().apply(context, decor, interceptionHandler);
+ decor.addView(content);
} catch (RuntimeException e) {
callback.onCanceled();
Slog.e(TAG, "Error inflating remote views", e);
mWindow = null;
return;
}
- final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
- final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
content.measure(widthMeasureSpec, heightMeasureSpec);
- content.setOnClickListener(v -> mCallback.onResponsePicked(response));
- content.setElevation(context.getResources().getDimension(R.dimen.floating_window_z));
+ decor.setOnClickListener(v -> mCallback.onResponsePicked(response));
// TODO(b/33197203 , b/36660292): temporary limiting maximum height and minimum width
mContentWidth = Math.max(content.getMeasuredWidth(), 1000);
mContentHeight = Math.min(content.getMeasuredHeight(), 500);
- mWindow = new AnchoredWindow(content);
+ mWindow = new AnchoredWindow(decor);
mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
} else {
final int datasetCount = response.getDatasets().size();
@@ -117,7 +133,7 @@
final RemoteViews presentation = dataset.getFieldPresentation(index);
final View view;
try {
- view = presentation.apply(context, null);
+ view = presentation.apply(context, null, interceptionHandler);
} catch (RuntimeException e) {
Slog.e(TAG, "Error inflating remote views", e);
continue;
@@ -139,9 +155,9 @@
}
};
- final LayoutInflater inflater = LayoutInflater.from(context);
- mListView = (ListView) inflater.inflate(R.layout.autofill_dataset_picker, null);
+ mListView = decor.findViewById(R.id.autofill_dataset_list);
mListView.setAdapter(mAdapter);
+ mListView.setVisibility(View.VISIBLE);
mListView.setOnItemClickListener((adapter, view, position, id) -> {
final ViewItem vi = mAdapter.getItem(position);
mCallback.onDatasetPicked(vi.getDataset());
@@ -154,11 +170,12 @@
}
applyNewFilterText();
- mWindow = new AnchoredWindow(mListView);
+ mWindow = new AnchoredWindow(decor);
}
}
private void applyNewFilterText() {
+ final int oldCount = mAdapter.getCount();
mAdapter.getFilter().filter(mFilterText, (count) -> {
if (mDestroyed) {
return;
@@ -175,6 +192,9 @@
} else {
mListView.setVerticalScrollBarEnabled(false);
}
+ if (mAdapter.getCount() != oldCount) {
+ mListView.requestLayout();
+ }
}
});
}
@@ -312,7 +332,8 @@
public void show(WindowManager.LayoutParams params) {
try {
if (!mShowing) {
- params.accessibilityTitle = mAccessibilityTitle;
+ params.accessibilityTitle = mContentView.getContext()
+ .getString(R.string.autofill_picker_accessibility_title);
mWm.addView(mContentView, params);
mContentView.setOnTouchListener(this);
mShowing = true;
@@ -352,7 +373,6 @@
pw.print(prefix); pw.print("mListView: "); pw.println(mListView);
pw.print(prefix); pw.print("mAdapter: "); pw.println(mAdapter != null);
pw.print(prefix); pw.print("mFilterText: "); pw.println(mFilterText);
- pw.print(prefix); pw.print("mAccessibilityTitle: "); pw.println(mAccessibilityTitle);
pw.print(prefix); pw.print("mContentWidth: "); pw.println(mContentWidth);
pw.print(prefix); pw.print("mContentHeight: "); pw.println(mContentHeight);
pw.print(prefix); pw.print("mDestroyed: "); pw.println(mDestroyed);
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 8003d21..f896478 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -20,17 +20,17 @@
LOCAL_JAVA_LIBRARIES := \
services.net \
- android.hardware.light@2.0-java \
- android.hardware.power@1.0-java \
- android.hardware.tv.cec@1.0-java \
- android.hidl.manager@1.0-java
+ android.hardware.light-V2.0-java \
+ android.hardware.power-V1.0-java \
+ android.hardware.tv.cec-V1.0-java \
+ android.hidl.manager-V1.0-java
LOCAL_STATIC_JAVA_LIBRARIES := \
tzdata_shared2 \
tzdata_update2 \
- android.hidl.base@1.0-java-static \
- android.hardware.biometrics.fingerprint@2.1-java-static \
- android.hardware.vibrator@1.0-java-constants \
+ android.hidl.base-V1.0-java-static \
+ android.hardware.biometrics.fingerprint-V2.1-java-static \
+ android.hardware.vibrator-V1.0-java-constants \
ifneq ($(INCREMENTAL_BUILDS),)
LOCAL_PROGUARD_ENABLED := disabled
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 8b32c16..21dae4f 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -36,6 +36,7 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
+import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
@@ -949,6 +950,16 @@
// because kernel doesn't keep this after reboot
setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
+ // Also sure that we're booting with a halfway sensible current time
+ if (mNativeData != 0) {
+ final long systemBuildTime = Environment.getRootDirectory().lastModified();
+ if (System.currentTimeMillis() < systemBuildTime) {
+ Slog.i(TAG, "Current time only " + System.currentTimeMillis()
+ + ", advancing to build time " + systemBuildTime);
+ setKernelTime(mNativeData, systemBuildTime);
+ }
+ }
+
PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index dcf6fd7..1a5ec61 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -416,6 +416,29 @@
return resOps;
}
+ private ArrayList<AppOpsManager.OpEntry> collectOps(SparseIntArray uidOps, int[] ops) {
+ ArrayList<AppOpsManager.OpEntry> resOps = null;
+ if (ops == null) {
+ resOps = new ArrayList<>();
+ for (int j=0; j<uidOps.size(); j++) {
+ resOps.add(new AppOpsManager.OpEntry(uidOps.keyAt(j), uidOps.valueAt(j),
+ 0, 0, 0, -1, null));
+ }
+ } else {
+ for (int j=0; j<ops.length; j++) {
+ int index = uidOps.indexOfKey(ops[j]);
+ if (index >= 0) {
+ if (resOps == null) {
+ resOps = new ArrayList<>();
+ }
+ resOps.add(new AppOpsManager.OpEntry(uidOps.keyAt(index), uidOps.valueAt(index),
+ 0, 0, 0, -1, null));
+ }
+ }
+ }
+ return resOps;
+ }
+
@Override
public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
@@ -473,6 +496,27 @@
}
}
+ @Override
+ public List<AppOpsManager.PackageOps> getUidOps(int uid, int[] ops) {
+ mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
+ Binder.getCallingPid(), Binder.getCallingUid(), null);
+ synchronized (this) {
+ UidState uidState = getUidStateLocked(uid, false);
+ if (uidState == null) {
+ return null;
+ }
+ ArrayList<AppOpsManager.OpEntry> resOps = collectOps(uidState.opModes, ops);
+ if (resOps == null) {
+ return null;
+ }
+ ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
+ AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
+ null, uidState.uid, resOps);
+ res.add(resPackage);
+ return res;
+ }
+ }
+
private void pruneOp(Op op, int uid, String packageName) {
if (op.time == 0 && op.rejectTime == 0) {
Ops ops = getOpsRawLocked(uid, packageName, false);
@@ -1669,6 +1713,7 @@
int op;
int mode;
int packageUid;
+ int nonpackageUid;
Shell(IAppOpsService iface, AppOpsService internal) {
mInterface = iface;
@@ -1790,15 +1835,59 @@
if (userId == UserHandle.USER_CURRENT) {
userId = ActivityManager.getCurrentUser();
}
- if ("root".equals(packageName)) {
- packageUid = 0;
- } else {
- packageUid = AppGlobals.getPackageManager().getPackageUid(packageName,
- PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+ nonpackageUid = -1;
+ try {
+ nonpackageUid = Integer.parseInt(packageName);
+ } catch (NumberFormatException e) {
}
- if (packageUid < 0) {
- err.println("Error: No UID for " + packageName + " in user " + userId);
- return -1;
+ if (nonpackageUid == -1 && packageName.length() > 1 && packageName.charAt(0) == 'u'
+ && packageName.indexOf('.') < 0) {
+ int i = 1;
+ while (i < packageName.length() && packageName.charAt(i) >= '0'
+ && packageName.charAt(i) <= '9') {
+ i++;
+ }
+ if (i > 1 && i < packageName.length()) {
+ String userStr = packageName.substring(1, i);
+ try {
+ int user = Integer.parseInt(userStr);
+ char type = packageName.charAt(i);
+ i++;
+ int startTypeVal = i;
+ while (i < packageName.length() && packageName.charAt(i) >= '0'
+ && packageName.charAt(i) <= '9') {
+ i++;
+ }
+ if (i > startTypeVal) {
+ String typeValStr = packageName.substring(startTypeVal, i);
+ try {
+ int typeVal = Integer.parseInt(typeValStr);
+ if (type == 'a') {
+ nonpackageUid = UserHandle.getUid(user,
+ typeVal + Process.FIRST_APPLICATION_UID);
+ } else if (type == 's') {
+ nonpackageUid = UserHandle.getUid(user, typeVal);
+ }
+ } catch (NumberFormatException e) {
+ }
+ }
+ } catch (NumberFormatException e) {
+ }
+ }
+ }
+ if (nonpackageUid != -1) {
+ packageName = null;
+ } else {
+ if ("root".equals(packageName)) {
+ packageUid = 0;
+ } else {
+ packageUid = AppGlobals.getPackageManager().getPackageUid(packageName,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+ }
+ if (packageUid < 0) {
+ err.println("Error: No UID for " + packageName + " in user " + userId);
+ return -1;
+ }
}
return 0;
}
@@ -1814,9 +1903,9 @@
pw.println("AppOps service (appops) commands:");
pw.println(" help");
pw.println(" Print this help text.");
- pw.println(" set [--user <USER_ID>] <PACKAGE> <OP> <MODE>");
+ pw.println(" set [--user <USER_ID>] <PACKAGE | UID> <OP> <MODE>");
pw.println(" Set the mode for a particular application and operation.");
- pw.println(" get [--user <USER_ID>] <PACKAGE> [<OP>]");
+ pw.println(" get [--user <USER_ID>] <PACKAGE | UID> [<OP>]");
pw.println(" Return the mode for a particular application and optional operation.");
pw.println(" query-op [--user <USER_ID>] <OP> [<MODE>]");
pw.println(" Print all packages that currently have the given op in the given mode.");
@@ -1858,7 +1947,12 @@
return -1;
}
- shell.mInterface.setMode(shell.op, shell.packageUid, shell.packageName, mode);
+ if (shell.packageName != null) {
+ shell.mInterface.setMode(shell.op, shell.packageUid, shell.packageName,
+ mode);
+ } else {
+ shell.mInterface.setUidMode(shell.op, shell.nonpackageUid, mode);
+ }
return 0;
}
case "get": {
@@ -1867,9 +1961,16 @@
return res;
}
- List<AppOpsManager.PackageOps> ops = shell.mInterface.getOpsForPackage(
- shell.packageUid, shell.packageName,
- shell.op != AppOpsManager.OP_NONE ? new int[] {shell.op} : null);
+ List<AppOpsManager.PackageOps> ops;
+ if (shell.packageName != null) {
+ ops = shell.mInterface.getOpsForPackage(
+ shell.packageUid, shell.packageName,
+ shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null);
+ } else {
+ ops = shell.mInterface.getUidOps(
+ shell.nonpackageUid,
+ shell.op != AppOpsManager.OP_NONE ? new int[]{shell.op} : null);
+ }
if (ops == null || ops.size() <= 0) {
pw.println("No operations.");
return 0;
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index f0720f3..9e054c3 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -146,6 +146,9 @@
// The maximum interval a location request can have and still be considered "high power".
private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
+ private static final int FOREGROUND_IMPORTANCE_CUTOFF
+ = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
+
// default background throttling interval if not overriden in settings
private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
@@ -375,7 +378,7 @@
}
};
mActivityManager.addOnUidImportanceListener(uidImportanceListener,
- ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE);
+ FOREGROUND_IMPORTANCE_CUTOFF);
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
updateUserProfiles(mCurrentUserId);
@@ -452,7 +455,7 @@
}
private static boolean isImportanceForeground(int importance) {
- return importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
+ return importance <= FOREGROUND_IMPORTANCE_CUTOFF;
}
/**
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 9218c25..d25b3cc 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -84,6 +84,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
+import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
@@ -106,6 +107,7 @@
private final Object mServiceConnectionLock = new Object();
private final Handler mHandler;
private final DispatchingContentObserver mContentObserver;
+ private final Function<NetworkScorerAppData, ScoringServiceConnection> mServiceConnProducer;
@GuardedBy("mPackageMonitorLock")
private NetworkScorerPackageMonitor mPackageMonitor;
@@ -238,11 +240,13 @@
}
public NetworkScoreService(Context context) {
- this(context, new NetworkScorerAppManager(context), Looper.myLooper());
+ this(context, new NetworkScorerAppManager(context),
+ ScoringServiceConnection::new, Looper.myLooper());
}
@VisibleForTesting
NetworkScoreService(Context context, NetworkScorerAppManager networkScoreAppManager,
+ Function<NetworkScorerAppData, ScoringServiceConnection> serviceConnProducer,
Looper looper) {
mContext = context;
mNetworkScorerAppManager = networkScoreAppManager;
@@ -257,6 +261,7 @@
mRecommendationRequestTimeoutMs = TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS;
mHandler = new ServiceHandler(looper);
mContentObserver = new DispatchingContentObserver(context, mHandler);
+ mServiceConnProducer = serviceConnProducer;
}
/** Called when the system is ready to run third-party code but before it actually does so. */
@@ -356,17 +361,17 @@
synchronized (mServiceConnectionLock) {
// If we're connected to a different component then drop it.
if (mServiceConnection != null
- && !mServiceConnection.mAppData.equals(appData)) {
+ && !mServiceConnection.getAppData().equals(appData)) {
unbindFromScoringServiceIfNeeded();
}
// If we're not connected at all then create a new connection.
if (mServiceConnection == null) {
- mServiceConnection = new ScoringServiceConnection(appData);
+ mServiceConnection = mServiceConnProducer.apply(appData);
}
// Make sure the connection is connected (idempotent)
- mServiceConnection.connect(mContext);
+ mServiceConnection.bind(mContext);
}
} else { // otherwise make sure it isn't bound.
unbindFromScoringServiceIfNeeded();
@@ -377,9 +382,9 @@
if (DBG) Log.d(TAG, "unbindFromScoringServiceIfNeeded");
synchronized (mServiceConnectionLock) {
if (mServiceConnection != null) {
- mServiceConnection.disconnect(mContext);
+ mServiceConnection.unbind(mContext);
if (DBG) Log.d(TAG, "Disconnected from: "
- + mServiceConnection.mAppData.getRecommendationServiceComponent());
+ + mServiceConnection.getAppData().getRecommendationServiceComponent());
}
mServiceConnection = null;
}
@@ -687,7 +692,7 @@
public boolean isCallerActiveScorer(int callingUid) {
synchronized (mServiceConnectionLock) {
return mServiceConnection != null
- && mServiceConnection.mAppData.packageUid == callingUid;
+ && mServiceConnection.getAppData().packageUid == callingUid;
}
}
@@ -720,7 +725,7 @@
if (isCallerSystemProcess(getCallingUid()) || callerCanRequestScores()) {
synchronized (mServiceConnectionLock) {
if (mServiceConnection != null) {
- return mServiceConnection.mAppData;
+ return mServiceConnection.getAppData();
}
}
} else {
@@ -1020,7 +1025,9 @@
mReqRecommendationCallerRef.set(new RequestRecommendationCaller(timeoutMs));
}
- private static class ScoringServiceConnection implements ServiceConnection {
+ // The class and methods need to be public for Mockito to work.
+ @VisibleForTesting
+ public static class ScoringServiceConnection implements ServiceConnection {
private final NetworkScorerAppData mAppData;
private volatile boolean mBound = false;
private volatile boolean mConnected = false;
@@ -1030,7 +1037,8 @@
mAppData = appData;
}
- void connect(Context context) {
+ @VisibleForTesting
+ public void bind(Context context) {
if (!mBound) {
Intent service = new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS);
service.setComponent(mAppData.getRecommendationServiceComponent());
@@ -1039,13 +1047,15 @@
UserHandle.SYSTEM);
if (!mBound) {
Log.w(TAG, "Bind call failed for " + service);
+ context.unbindService(this);
} else {
if (DBG) Log.d(TAG, "ScoringServiceConnection bound.");
}
}
}
- void disconnect(Context context) {
+ @VisibleForTesting
+ public void unbind(Context context) {
try {
if (mBound) {
mBound = false;
@@ -1056,17 +1066,30 @@
Log.e(TAG, "Unbind failed.", e);
}
+ mConnected = false;
mRecommendationProvider = null;
}
- INetworkRecommendationProvider getRecommendationProvider() {
+ @VisibleForTesting
+ public NetworkScorerAppData getAppData() {
+ return mAppData;
+ }
+
+ @VisibleForTesting
+ public INetworkRecommendationProvider getRecommendationProvider() {
return mRecommendationProvider;
}
- String getPackageName() {
+ @VisibleForTesting
+ public String getPackageName() {
return mAppData.getRecommendationServiceComponent().getPackageName();
}
+ @VisibleForTesting
+ public boolean isAlive() {
+ return mBound && mConnected;
+ }
+
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DBG) Log.d(TAG, "ScoringServiceConnection: " + name.flattenToString());
diff --git a/services/core/java/com/android/server/OemLockService.java b/services/core/java/com/android/server/OemLockService.java
new file mode 100644
index 0000000..03f82a8
--- /dev/null
+++ b/services/core/java/com/android/server/OemLockService.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.Manifest;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.service.oemlock.IOemLockService;
+import android.service.persistentdata.PersistentDataBlockManager;
+
+/**
+ * Service for managing the OEM lock state of the device.
+ *
+ * The current implementation is a wrapper around the previous implementation of OEM lock.
+ * - the DISALLOW_OEM_UNLOCK user restriction was set if the carrier disallowed unlock
+ * - the user allows unlock in settings which calls PDBM.setOemUnlockEnabled()
+ */
+public class OemLockService extends SystemService {
+ private Context mContext;
+
+ public OemLockService(Context context) {
+ super(context);
+ mContext = context;
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.OEM_LOCK_SERVICE, mService);
+ }
+
+ private boolean doIsOemUnlockAllowedByCarrier() {
+ return !UserManager.get(mContext).hasUserRestriction(UserManager.DISALLOW_OEM_UNLOCK);
+ }
+
+ private boolean doIsOemUnlockAllowedByUser() {
+ final PersistentDataBlockManager pdbm = (PersistentDataBlockManager)
+ mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return pdbm.getOemUnlockEnabled();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Implements the binder interface for the service.
+ */
+ private final IBinder mService = new IOemLockService.Stub() {
+ @Override
+ public void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
+ enforceManageCarrierOemUnlockPermission();
+ enforceUserIsAdmin();
+
+ // Note: this implementation does not require a signature
+
+ // Continue using user restriction for backwards compatibility
+ final UserHandle userHandle = UserHandle.of(UserHandle.getCallingUserId());
+ final long token = Binder.clearCallingIdentity();
+ try {
+ UserManager.get(mContext)
+ .setUserRestriction(UserManager.DISALLOW_OEM_UNLOCK, !allowed, userHandle);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public boolean isOemUnlockAllowedByCarrier() {
+ enforceManageCarrierOemUnlockPermission();
+ return doIsOemUnlockAllowedByCarrier();
+ }
+
+ @Override
+ public void setOemUnlockAllowedByUser(boolean allowedByUser) {
+ if (ActivityManager.isUserAMonkey()) {
+ // Prevent a monkey from changing this
+ return;
+ }
+
+ enforceManageUserOemUnlockPermission();
+ enforceUserIsAdmin();
+
+ final PersistentDataBlockManager pdbm = (PersistentDataBlockManager)
+ mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ // The method name is misleading as it really just means whether or not the device
+ // can be unlocked but doesn't actually do any unlocking.
+ pdbm.setOemUnlockEnabled(allowedByUser);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public boolean isOemUnlockAllowedByUser() {
+ enforceManageUserOemUnlockPermission();
+ return doIsOemUnlockAllowedByUser();
+ }
+ };
+
+ private void enforceManageCarrierOemUnlockPermission() {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE,
+ "Can't manage OEM unlock allowed by carrier");
+ }
+
+ private void enforceManageUserOemUnlockPermission() {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE,
+ "Can't manage OEM unlock allowed by user");
+ }
+
+ private void enforceUserIsAdmin() {
+ final int userId = UserHandle.getCallingUserId();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (!UserManager.get(mContext).isUserAdmin(userId)) {
+ throw new SecurityException("Must be an admin user");
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 5f585cc..eb58e4c 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -959,6 +959,12 @@
mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId));
}
+ private void sendAccountRemovedBroadcast(int userId) {
+ Intent intent = new Intent(AccountManager.ACTION_ACCOUNT_REMOVED);
+ intent.setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ mContext.sendBroadcastAsUser(intent, new UserHandle(userId));
+ }
+
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
@@ -1111,6 +1117,7 @@
notifyPackage(packageToVisibility.getKey(), accounts);
}
}
+ sendAccountRemovedBroadcast(accounts.userId);
} else {
ArrayList<String> accountNames = accountNamesByType.get(account.type);
if (accountNames == null) {
@@ -1971,6 +1978,7 @@
sendNotificationAccountUpdated(resultAccount, accounts);
sendAccountsChangedBroadcast(accounts.userId);
+ sendAccountRemovedBroadcast(accounts.userId);
}
}
return resultAccount;
@@ -2206,6 +2214,7 @@
// Only broadcast LOGIN_ACCOUNTS_CHANGED if a change occurred.
sendAccountsChangedBroadcast(accounts.userId);
+ sendAccountRemovedBroadcast(accounts.userId);
String action = userUnlocked ? AccountsDb.DEBUG_ACTION_ACCOUNT_REMOVE
: AccountsDb.DEBUG_ACTION_ACCOUNT_REMOVE_DE;
logRecord(action, AccountsDb.TABLE_ACCOUNTS, accountId, accounts);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 7dd75df..c77820b 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -324,7 +324,7 @@
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
- + " (pid=" + Binder.getCallingPid()
+ + " (pid=" + callingPid
+ ") when starting service " + service);
}
callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
@@ -353,29 +353,24 @@
// If this isn't a direct-to-foreground start, check our ability to kick off an
// arbitrary service
if (!r.startRequested && !fgRequired) {
- final long token = Binder.clearCallingIdentity();
- try {
- // Before going further -- if this app is not allowed to start services in the
- // background, then at this point we aren't going to let it period.
- final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
- r.appInfo.targetSdkVersion, callingPid, false, false);
- if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
- Slog.w(TAG, "Background start not allowed: service "
- + service + " to " + r.name.flattenToShortString()
- + " from pid=" + callingPid + " uid=" + callingUid
- + " pkg=" + callingPackage);
- if (allowed == ActivityManager.APP_START_MODE_DELAYED) {
- // In this case we are silently disabling the app, to disrupt as
- // little as possible existing apps.
- return null;
- }
- // This app knows it is in the new model where this operation is not
- // allowed, so tell it what has happened.
- UidRecord uidRec = mAm.mActiveUids.get(r.appInfo.uid);
- return new ComponentName("?", "app is in background uid " + uidRec);
+ // Before going further -- if this app is not allowed to start services in the
+ // background, then at this point we aren't going to let it period.
+ final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
+ r.appInfo.targetSdkVersion, callingPid, false, false);
+ if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
+ Slog.w(TAG, "Background start not allowed: service "
+ + service + " to " + r.name.flattenToShortString()
+ + " from pid=" + callingPid + " uid=" + callingUid
+ + " pkg=" + callingPackage);
+ if (allowed == ActivityManager.APP_START_MODE_DELAYED) {
+ // In this case we are silently disabling the app, to disrupt as
+ // little as possible existing apps.
+ return null;
}
- } finally {
- Binder.restoreCallingIdentity(token);
+ // This app knows it is in the new model where this operation is not
+ // allowed, so tell it what has happened.
+ UidRecord uidRec = mAm.mActiveUids.get(r.appInfo.uid);
+ return new ComponentName("?", "app is in background uid " + uidRec);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index df250b1..55ee183 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -32,16 +32,10 @@
*/
final class ActivityManagerConstants extends ContentObserver {
// Key names stored in the settings value.
- private static final String KEY_ENFORCE_BG_CHECK = "enforce_bg_check";
private static final String KEY_MAX_CACHED_PROCESSES = "max_cached_processes";
- private static final boolean DEFAULT_ENFORCE_BG_CHECK = SystemProperties.getBoolean(
- "debug.bgcheck", true);
private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
- // Enforce background check on apps targeting O?
- public boolean ENFORCE_BG_CHECK = DEFAULT_ENFORCE_BG_CHECK;
-
// Maximum number of cached processes we will allow.
public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
@@ -115,7 +109,6 @@
// with defaults.
Slog.e("ActivityManagerConstants", "Bad activity manager config settings", e);
}
- ENFORCE_BG_CHECK = mParser.getBoolean(KEY_ENFORCE_BG_CHECK, DEFAULT_ENFORCE_BG_CHECK);
MAX_CACHED_PROCESSES = mParser.getInt(KEY_MAX_CACHED_PROCESSES,
DEFAULT_MAX_CACHED_PROCESSES);
updateMaxCachedProcesses();
@@ -139,9 +132,6 @@
pw.println("ACTIVITY MANAGER SETTINGS (dumpsys activity settings) "
+ Settings.Global.ACTIVITY_MANAGER_CONSTANTS + ":");
- pw.print(" "); pw.print(KEY_ENFORCE_BG_CHECK); pw.print("=");
- pw.println(ENFORCE_BG_CHECK);
-
pw.print(" "); pw.print(KEY_MAX_CACHED_PROCESSES); pw.print("=");
pw.println(MAX_CACHED_PROCESSES);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 35654d7..2be5313 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -71,7 +71,6 @@
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
import static android.os.Process.getFreeMemory;
-import static android.os.Process.getThreadPriority;
import static android.os.Process.getTotalMemory;
import static android.os.Process.isThreadInProcess;
import static android.os.Process.killProcess;
@@ -1688,6 +1687,7 @@
static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 64;
static final int NOTIFY_VR_SLEEPING_MSG = 65;
static final int SERVICE_FOREGROUND_TIMEOUT_MSG = 66;
+ static final int DISPATCH_PENDING_INTENT_CANCEL_MSG = 67;
static final int START_USER_SWITCH_FG_MSG = 712;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
@@ -1956,6 +1956,18 @@
case SERVICE_FOREGROUND_TIMEOUT_MSG: {
mServices.serviceForegroundTimeout((ServiceRecord)msg.obj);
} break;
+ case DISPATCH_PENDING_INTENT_CANCEL_MSG: {
+ RemoteCallbackList<IResultReceiver> callbacks
+ = (RemoteCallbackList<IResultReceiver>)msg.obj;
+ int N = callbacks.beginBroadcast();
+ for (int i = 0; i < N; i++) {
+ try {
+ callbacks.getBroadcastItem(i).send(Activity.RESULT_CANCELED, null);
+ } catch (RemoteException e) {
+ }
+ }
+ callbacks.finishBroadcast();
+ } break;
case UPDATE_TIME_ZONE: {
synchronized (ActivityManagerService.this) {
for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
@@ -2705,17 +2717,6 @@
mConstants = new ActivityManagerConstants(this, mHandler);
- if (DEBUG_BACKGROUND_CHECK) {
- Slog.d(TAG, "Enforcing O+ bg restrictions: " + mConstants.ENFORCE_BG_CHECK);
- StringBuilder sb = new StringBuilder(200);
- sb.append(" ");
- for (String a : getBackgroundLaunchBroadcasts()) {
- sb.append(' '); sb.append(a);
- }
- Slog.d(TAG, "Background implicit broadcasts:");
- Slog.d(TAG, sb.toString());
- }
-
/* static; one-time init here */
if (sKillHandler == null) {
sKillThread = new ServiceThread(TAG + ":kill",
@@ -3878,7 +3879,8 @@
// the per-user SELinux context must be set
if (TextUtils.isEmpty(app.info.seInfoUser)) {
Slog.wtf(TAG, "SELinux tag not defined",
- new IllegalStateException("SELinux tag not defined"));
+ new IllegalStateException("SELinux tag not defined for "
+ + app.info.packageName + " (uid " + app.uid + ")"));
}
final String seInfo = app.info.seInfo
+ (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);
@@ -5243,10 +5245,10 @@
}
private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
- IBinder threadBinder = thread.asBinder();
+ final IBinder threadBinder = thread.asBinder();
// Find the application record.
for (int i=mLruProcesses.size()-1; i>=0; i--) {
- ProcessRecord rec = mLruProcesses.get(i);
+ final ProcessRecord rec = mLruProcesses.get(i);
if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
return i;
}
@@ -5261,7 +5263,27 @@
}
int appIndex = getLRURecordIndexForAppLocked(thread);
- return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
+ if (appIndex >= 0) {
+ return mLruProcesses.get(appIndex);
+ }
+
+ // Validation: if it isn't in the LRU list, it shouldn't exist, but let's
+ // double-check that.
+ final IBinder threadBinder = thread.asBinder();
+ final ArrayMap<String, SparseArray<ProcessRecord>> pmap = mProcessNames.getMap();
+ for (int i = pmap.size()-1; i >= 0; i--) {
+ final SparseArray<ProcessRecord> procs = pmap.valueAt(i);
+ for (int j = procs.size()-1; j >= 0; j--) {
+ final ProcessRecord proc = procs.valueAt(j);
+ if (proc.thread != null && proc.thread.asBinder() == threadBinder) {
+ Slog.wtf(TAG, "getRecordForApp: exists in name list but not in LRU list: "
+ + proc);
+ return proc;
+ }
+ }
+ }
+
+ return null;
}
final void doLowMemReportIfNeededLocked(ProcessRecord dyingProc) {
@@ -6402,7 +6424,7 @@
}
didSomething = true;
it.remove();
- pir.canceled = true;
+ makeIntentSenderCanceledLocked(pir);
if (pir.key.activity != null && pir.key.activity.pendingResults != null) {
pir.key.activity.pendingResults.remove(pir.ref);
}
@@ -7412,7 +7434,7 @@
}
return rec;
}
- rec.canceled = true;
+ makeIntentSenderCanceledLocked(rec);
mIntentSenderRecords.remove(key);
}
if (noCreate) {
@@ -7516,7 +7538,7 @@
String msg = "Permission Denial: cancelIntentSender() from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid()
- + " is not allowed to cancel packges "
+ + " is not allowed to cancel package "
+ rec.key.packageName;
Slog.w(TAG, msg);
throw new SecurityException(msg);
@@ -7529,13 +7551,21 @@
}
void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
- rec.canceled = true;
+ makeIntentSenderCanceledLocked(rec);
mIntentSenderRecords.remove(rec.key);
if (cleanActivity && rec.key.activity != null) {
rec.key.activity.pendingResults.remove(rec.ref);
}
}
+ void makeIntentSenderCanceledLocked(PendingIntentRecord rec) {
+ rec.canceled = true;
+ RemoteCallbackList<IResultReceiver> callbacks = rec.detachCancelListenersLocked();
+ if (callbacks != null) {
+ mHandler.obtainMessage(DISPATCH_PENDING_INTENT_CANCEL_MSG, callbacks).sendToTarget();
+ }
+ }
+
@Override
public String getPackageForIntentSender(IIntentSender pendingResult) {
if (!(pendingResult instanceof PendingIntentRecord)) {
@@ -7550,6 +7580,27 @@
}
@Override
+ public void registerIntentSenderCancelListener(IIntentSender sender, IResultReceiver receiver) {
+ if (!(sender instanceof PendingIntentRecord)) {
+ return;
+ }
+ synchronized(this) {
+ ((PendingIntentRecord)sender).registerCancelListenerLocked(receiver);
+ }
+ }
+
+ @Override
+ public void unregisterIntentSenderCancelListener(IIntentSender sender,
+ IResultReceiver receiver) {
+ if (!(sender instanceof PendingIntentRecord)) {
+ return;
+ }
+ synchronized(this) {
+ ((PendingIntentRecord)sender).unregisterCancelListenerLocked(receiver);
+ }
+ }
+
+ @Override
public int getUidForIntentSender(IIntentSender sender) {
if (sender instanceof PendingIntentRecord) {
try {
@@ -7803,7 +7854,7 @@
// Activity supports picture-in-picture, now check that we can enter PiP at this
// point, if it is
if (!r.checkEnterPictureInPictureState("enterPictureInPictureMode",
- false /* noThrow */)) {
+ false /* noThrow */, false /* beforeStopping */)) {
return false;
}
@@ -7813,9 +7864,7 @@
final float aspectRatio = r.pictureInPictureArgs.getAspectRatio();
final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
final Rect sourceBounds = r.pictureInPictureArgs.getSourceRectHint();
- final Rect destBounds = mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY,
- aspectRatio);
- mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, destBounds,
+ mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, aspectRatio,
true /* moveHomeStackToFront */, "enterPictureInPictureMode");
final PinnedActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID);
stack.setPictureInPictureAspectRatio(aspectRatio);
@@ -7876,7 +7925,7 @@
// if it is not already expanding to fullscreen. Otherwise, the arguments will
// be used the next time the activity enters PiP
final PinnedActivityStack stack = r.getStack();
- if (!stack.isBoundsAnimatingToFullscreen()) {
+ if (!stack.isAnimatingBoundsToFullscreen()) {
stack.setPictureInPictureAspectRatio(
r.pictureInPictureArgs.getAspectRatio());
stack.setPictureInPictureActions(r.pictureInPictureArgs.getActions());
@@ -8247,7 +8296,7 @@
// Unified app-op and target sdk check
int appRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) {
// Apps that target O+ are always subject to background check
- if (mConstants.ENFORCE_BG_CHECK && packageTargetSdk >= Build.VERSION_CODES.O) {
+ if (packageTargetSdk >= Build.VERSION_CODES.O) {
if (DEBUG_BACKGROUND_CHECK) {
Slog.i(TAG, "App " + uid + "/" + packageName + " targets O+, restricted");
}
@@ -10485,8 +10534,10 @@
if (stackId == PINNED_STACK_ID) {
final PinnedActivityStack pinnedStack =
mStackSupervisor.getStack(PINNED_STACK_ID);
- pinnedStack.animateResizePinnedStack(null /* sourceBounds */, destBounds,
- animationDuration);
+ if (pinnedStack != null) {
+ pinnedStack.animateResizePinnedStack(null /* sourceBounds */,
+ destBounds, animationDuration);
+ }
} else {
throw new IllegalArgumentException("Stack: " + stackId
+ " doesn't support animated resize.");
@@ -13025,6 +13076,19 @@
}
@Override
+ public int getUidProcessState(int uid, String callingPackage) {
+ if (!hasUsageStatsPermission(callingPackage)) {
+ enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS,
+ "getUidProcessState");
+ }
+
+ synchronized (this) {
+ UidRecord uidRec = mActiveUids.get(uid);
+ return uidRec != null ? uidRec.curProcState : ActivityManager.PROCESS_STATE_NONEXISTENT;
+ }
+ }
+
+ @Override
public void registerUidObserver(IUidObserver observer, int which, int cutpoint,
String callingPackage) {
if (!hasUsageStatsPermission(callingPackage)) {
@@ -16178,23 +16242,45 @@
pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
if (mIntentSenderRecords.size() > 0) {
- Iterator<WeakReference<PendingIntentRecord>> it
+ // Organize these by package name, so they are easier to read.
+ final ArrayMap<String, ArrayList<PendingIntentRecord>> byPackage = new ArrayMap<>();
+ final ArrayList<WeakReference<PendingIntentRecord>> weakRefs = new ArrayList<>();
+ final Iterator<WeakReference<PendingIntentRecord>> it
= mIntentSenderRecords.values().iterator();
while (it.hasNext()) {
WeakReference<PendingIntentRecord> ref = it.next();
- PendingIntentRecord rec = ref != null ? ref.get(): null;
- if (dumpPackage != null && (rec == null
- || !dumpPackage.equals(rec.key.packageName))) {
+ PendingIntentRecord rec = ref != null ? ref.get() : null;
+ if (rec == null) {
+ weakRefs.add(ref);
continue;
}
+ if (dumpPackage != null && !dumpPackage.equals(rec.key.packageName)) {
+ continue;
+ }
+ ArrayList<PendingIntentRecord> list = byPackage.get(rec.key.packageName);
+ if (list == null) {
+ list = new ArrayList<>();
+ byPackage.put(rec.key.packageName, list);
+ }
+ list.add(rec);
+ }
+ for (int i = 0; i < byPackage.size(); i++) {
+ ArrayList<PendingIntentRecord> intents = byPackage.valueAt(i);
printed = true;
- if (rec != null) {
- pw.print(" * "); pw.println(rec);
+ pw.print(" * "); pw.print(byPackage.keyAt(i));
+ pw.print(": "); pw.print(intents.size()); pw.println(" items");
+ for (int j = 0; j < intents.size(); j++) {
+ pw.print(" #"); pw.print(j); pw.print(": "); pw.println(intents.get(j));
if (dumpAll) {
- rec.dump(pw, " ");
+ intents.get(j).dump(pw, " ");
}
- } else {
- pw.print(" * "); pw.println(ref);
+ }
+ }
+ if (weakRefs.size() > 0) {
+ printed = true;
+ pw.println(" * WEAK REFS:");
+ for (int i = 0; i < weakRefs.size(); i++) {
+ pw.print(" #"); pw.print(i); pw.print(": "); pw.println(weakRefs.get(i));
}
}
}
@@ -17861,10 +17947,14 @@
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
- ComponentName res = mServices.startServiceLocked(caller, service,
- resolvedType, id, notification, callingPid, callingUid,
- requireForeground, callingPackage, userId);
- Binder.restoreCallingIdentity(origId);
+ ComponentName res;
+ try {
+ res = mServices.startServiceLocked(caller, service,
+ resolvedType, id, notification, callingPid, callingUid,
+ requireForeground, callingPackage, userId);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
return res;
}
}
@@ -17876,9 +17966,13 @@
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"startServiceInPackage: " + service + " type=" + resolvedType);
final long origId = Binder.clearCallingIdentity();
- ComponentName res = mServices.startServiceLocked(null, service,
- resolvedType, 0, null, -1, uid, fgRequired, callingPackage, userId);
- Binder.restoreCallingIdentity(origId);
+ ComponentName res;
+ try {
+ res = mServices.startServiceLocked(null, service,
+ resolvedType, 0, null, -1, uid, fgRequired, callingPackage, userId);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
return res;
}
}
@@ -23315,7 +23409,7 @@
Slog.w(TAG, "markAsSentFromNotification(): not a PendingIntentRecord: " + target);
return;
}
- ((PendingIntentRecord) target).setWhitelistDuration(duration);
+ ((PendingIntentRecord) target).setWhitelistDurationLocked(duration);
}
@Override
@@ -23761,24 +23855,6 @@
}
@Override
- public boolean canBypassWorkChallenge(PendingIntent intent) throws RemoteException {
- final int userId = intent.getCreatorUserHandle().getIdentifier();
- if (!mUserController.isUserRunningLocked(userId, ActivityManager.FLAG_AND_LOCKED)) {
- return false;
- }
- IIntentSender target = intent.getTarget();
- if (!(target instanceof PendingIntentRecord)) {
- return false;
- }
- final PendingIntentRecord record = (PendingIntentRecord) target;
- final ResolveInfo rInfo = mStackSupervisor.resolveIntent(record.key.requestIntent,
- record.key.requestResolvedType, userId, PackageManager.MATCH_DIRECT_BOOT_AWARE);
- // For direct boot aware activities, they can be shown without triggering a work challenge
- // before the profile user is unlocked.
- return rInfo != null && rInfo.activityInfo != null;
- }
-
- @Override
public void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback)
throws RemoteException {
final long callingId = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 04c2af5..0fcf3e6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -2498,6 +2498,10 @@
pw.println(" Start a Service. Options are:");
pw.println(" --user <USER_ID> | current: Specify which user to run as; if not");
pw.println(" specified then run as the current user.");
+ pw.println(" start-foreground-service [--user <USER_ID> | current] <INTENT>");
+ pw.println(" Start a foreground Service. Options are:");
+ pw.println(" --user <USER_ID> | current: Specify which user to run as; if not");
+ pw.println(" specified then run as the current user.");
pw.println(" stop-service [--user <USER_ID> | current] <INTENT>");
pw.println(" Stop a Service. Options are:");
pw.println(" --user <USER_ID> | current: Specify which user to run as; if not");
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 2b953ad..276b267 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -97,6 +97,7 @@
import static com.android.server.am.ActivityStack.LAUNCH_TICK;
import static com.android.server.am.ActivityStack.LAUNCH_TICK_MSG;
import static com.android.server.am.ActivityStack.PAUSE_TIMEOUT_MSG;
+import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
import static com.android.server.am.ActivityStack.STOP_TIMEOUT_MSG;
import static com.android.server.am.EventLogTags.AM_ACTIVITY_FULLY_DRAWN_TIME;
import static com.android.server.am.EventLogTags.AM_ACTIVITY_LAUNCH_TIME;
@@ -420,8 +421,14 @@
pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
pw.print(" label=\""); pw.print(taskDescription.getLabel());
pw.print("\"");
- pw.print(" color=");
+ pw.print(" primaryColor=");
pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
+ pw.print(prefix + " backgroundColor=");
+ pw.println(Integer.toHexString(taskDescription.getBackgroundColor()));
+ pw.print(prefix + " statusBarColor=");
+ pw.println(Integer.toHexString(taskDescription.getStatusBarColor()));
+ pw.print(prefix + " navigationBarColor=");
+ pw.println(Integer.toHexString(taskDescription.getNavigationBarColor()));
}
if (iconFilename == null && taskDescription.getIcon() != null) {
pw.print(prefix); pw.println("taskDescription contains Bitmap");
@@ -1156,10 +1163,13 @@
}
/**
+ * @param beforeStopping Whether this check is for an auto-enter-pip operation, that is to say
+ * the activity has requested to enter PiP when it would otherwise be stopped.
+ *
* @return whether this activity is currently allowed to enter PIP, throwing an exception if
* the activity is not currently visible and {@param noThrow} is not set.
*/
- boolean checkEnterPictureInPictureState(String caller, boolean noThrow) {
+ boolean checkEnterPictureInPictureState(String caller, boolean noThrow, boolean beforeStopping) {
// Check app-ops and see if PiP is supported for this package
if (!checkEnterPictureInPictureAppOpsState()) {
return false;
@@ -1170,17 +1180,24 @@
return false;
}
- boolean isCurrentAppLocked = mStackSupervisor.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
boolean isKeyguardLocked = service.isKeyguardLocked();
+ boolean isCurrentAppLocked = mStackSupervisor.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
boolean hasPinnedStack = mStackSupervisor.getStack(PINNED_STACK_ID) != null;
// Don't return early if !isNotLocked, since we want to throw an exception if the activity
// is in an incorrect state
boolean isNotLockedOrOnKeyguard = !isKeyguardLocked && !isCurrentAppLocked;
+
+ // We don't allow auto-PiP when something else is already pipped.
+ if (beforeStopping && hasPinnedStack) {
+ return false;
+ }
+
switch (state) {
case RESUMED:
// When visible, allow entering PiP if the app is not locked. If it is over the
// keyguard, then we will prompt to unlock in the caller before entering PiP.
- return !isCurrentAppLocked;
+ return !isCurrentAppLocked &&
+ (supportsPictureInPictureWhilePausing || !beforeStopping);
case PAUSING:
case PAUSED:
// When pausing, then only allow enter PiP as in the resume state, and in addition,
@@ -1554,8 +1571,8 @@
mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
}
- void notifyAppResumed(boolean wasStopped, boolean allowSavedSurface) {
- mWindowContainerController.notifyAppResumed(wasStopped, allowSavedSurface);
+ void notifyAppResumed(boolean wasStopped) {
+ mWindowContainerController.notifyAppResumed(wasStopped);
}
void notifyUnknownVisibilityLaunched() {
@@ -2105,7 +2122,8 @@
service.compatibilityInfoForPackageLocked(info.applicationInfo);
final boolean shown = mWindowContainerController.addStartingWindow(packageName, theme,
compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
- prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning());
+ prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
+ allowTaskSnapshot());
if (shown) {
mStartingWindowState = STARTING_WINDOW_SHOWN;
}
@@ -2269,6 +2287,20 @@
return true;
}
+ // Skip updating configuration for activity that are stopping or stopped.
+ if (state == STOPPING || state == STOPPED) {
+ if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+ "Skipping config check stopped or stopping: " + this);
+ return true;
+ }
+
+ // Skip updating configuration for activity is a stack that shouldn't be visible.
+ if (stack.shouldBeVisible(null /* starting */) == STACK_INVISIBLE) {
+ if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+ "Skipping config check invisible stack: " + this);
+ return true;
+ }
+
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Ensuring correct configuration: " + this);
@@ -2531,7 +2563,7 @@
preserveWindowOnDeferredRelaunch = false;
}
- boolean isProcessRunning() {
+ private boolean isProcessRunning() {
ProcessRecord proc = app;
if (proc == null) {
proc = service.mProcessNames.get(processName, info.applicationInfo.uid);
@@ -2539,6 +2571,26 @@
return proc != null && proc.thread != null;
}
+ /**
+ * @return Whether a task snapshot starting window may be shown.
+ */
+ private boolean allowTaskSnapshot() {
+ if (newIntents == null) {
+ return true;
+ }
+
+ // Restrict task snapshot starting window to launcher start, or there is no intent at all
+ // (eg. task being brought to front). If the intent is something else, likely the app is
+ // going to show some specific page or view, instead of what's left last time.
+ for (int i = newIntents.size() - 1; i >= 0; i--) {
+ final Intent intent = newIntents.get(i);
+ if (intent != null && !ActivityRecord.isMainIntent(intent)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
out.attribute(null, ATTR_ID, String.valueOf(createTime));
out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 78887c6..4c84d98 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -116,6 +116,7 @@
import android.util.SparseArray;
import android.view.Display;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.Watchdog;
@@ -230,9 +231,10 @@
// activities and there is a specific combination of stacks.
private static final int STACK_VISIBLE_ACTIVITY_BEHIND = 2;
+ @VisibleForTesting
/* The various modes for the method {@link #removeTask}. */
// Task is being completely removed from all stacks in the system.
- private static final int REMOVE_TASK_MODE_DESTROYING = 0;
+ protected static final int REMOVE_TASK_MODE_DESTROYING = 0;
// Task is being removed from this stack so we can add it to another stack. In the case we are
// moving we don't want to perform some operations on the task like removing it from window
// manager or recents.
@@ -644,9 +646,13 @@
}
final ActivityRecord topRunningActivityLocked() {
+ return topRunningActivityLocked(false /* focusableOnly */);
+ }
+
+ final ActivityRecord topRunningActivityLocked(boolean focusableOnly) {
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked();
- if (r != null) {
+ if (r != null && (!focusableOnly || r.isFocusable())) {
return r;
}
}
@@ -1321,7 +1327,7 @@
+ (timeout ? " (due to timeout)" : " (pause complete)"));
mService.mWindowManager.deferSurfaceLayout();
try {
- completePauseLocked(true, null);
+ completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
} finally {
mService.mWindowManager.continueSurfaceLayout();
}
@@ -1989,10 +1995,10 @@
// keeping the screen frozen.
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Making invisible: " + r + " " + r.state);
try {
- r.setVisible(false);
switch (r.state) {
case STOPPING:
case STOPPED:
+ r.setVisible(false);
if (r.app != null && r.app.thread != null) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
"Scheduling invisibility: " + r);
@@ -2011,6 +2017,7 @@
// This case created for transitioning activities from
// translucent to opaque {@link Activity#convertToOpaque}.
if (visibleBehind == r) {
+ r.setVisible(false);
releaseBackgroundResources(r);
} else {
// If this activity is in a state where it can currently enter
@@ -2018,7 +2025,18 @@
// the activity tries to enterPictureInPictureMode() later. Otherwise,
// we will try and stop the activity next time idle is processed.
final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
- "makeInvisible", true /* noThrow */);
+ "makeInvisible", true /* noThrow */, true /* beforeStopping */);
+
+ if (canEnterPictureInPicture) {
+ // We set r.visible=false so that Stop will later
+ // call setVisible for us. In this case
+ // we don't want to call setVisible(false) to avoid
+ // notifying the client of this intermittent invisible
+ // state.
+ r.visible = false;
+ } else {
+ r.setVisible(false);
+ }
addToStopping(r, true /* scheduleIdle */,
canEnterPictureInPicture /* idleDelayed */);
}
@@ -2186,8 +2204,10 @@
return false;
}
- // Find the topmost activity in this stack that is not finishing.
- final ActivityRecord next = topRunningActivityLocked();
+ // Find the next top-most activity to resume in this stack that is not finishing and is
+ // focusable. If it is not focusable, we will fall into the case below to resume the
+ // top activity in the next focusable task.
+ final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
final boolean hasRunningActivity = next != null;
@@ -2519,26 +2539,14 @@
}
}
- boolean allowSavedSurface = true;
if (next.newIntents != null) {
- // Restrict saved surface to launcher start, or there is no intent at all
- // (eg. task being brought to front). If the intent is something else,
- // likely the app is going to show some specific page or view, instead of
- // what's left last time.
- for (int i = next.newIntents.size() - 1; i >= 0; i--) {
- final Intent intent = next.newIntents.get(i);
- if (intent != null && !ActivityRecord.isMainIntent(intent)) {
- allowSavedSurface = false;
- break;
- }
- }
next.app.thread.scheduleNewIntent(
next.newIntents, next.appToken, false /* andPause */);
}
// Well the app will no longer be stopped.
// Clear app token stopped state in window manager if needed.
- next.notifyAppResumed(next.stopped, allowSavedSurface);
+ next.notifyAppResumed(next.stopped);
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
System.identityHashCode(next), next.getTask().taskId,
@@ -3973,6 +3981,18 @@
task.isOverHomeStack()) {
mStackSupervisor.moveHomeStackTaskToTop(reason);
}
+
+ if (onlyHasTaskOverlays) {
+ // When destroying a task, tell the supervisor to remove it so that any activity it
+ // has can be cleaned up correctly. This is currently the only place where we remove
+ // a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
+ // state into removeTask(), we just clear the task here before the other residual
+ // work.
+ // TODO: If the callers to removeTask() changes such that we have multiple places
+ // where we are destroying the task, move this back into removeTask()
+ mStackSupervisor.removeTaskByIdLocked(task.taskId, false /* killProcess */,
+ !REMOVE_FROM_RECENTS, PAUSE_IMMEDIATELY);
+ }
removeTask(task, reason, REMOVE_TASK_MODE_DESTROYING);
}
cleanUpActivityServicesLocked(r);
@@ -5032,14 +5052,6 @@
* {@link #REMOVE_TASK_MODE_MOVING}, {@link #REMOVE_TASK_MODE_MOVING_TO_TOP}.
*/
void removeTask(TaskRecord task, String reason, int mode) {
- if (mode == REMOVE_TASK_MODE_DESTROYING) {
- // When destroying a task, tell the supervisor to remove it so that any activity it has
- // can be cleaned up correctly
- mStackSupervisor.removeTaskByIdLocked(task.taskId, false /* killProcess */,
- !REMOVE_FROM_RECENTS, PAUSE_IMMEDIATELY);
- task.removeWindowContainer();
- }
-
for (ActivityRecord record : task.mActivities) {
onActivityRemovedFromStack(record);
}
@@ -5071,6 +5083,8 @@
mRecentTasks.remove(task);
task.removedFromRecents();
}
+
+ task.removeWindowContainer();
}
if (mTaskHistory.isEmpty()) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 68e25c3..4d16e33 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -174,6 +174,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.wm.PinnedStackWindowController;
import com.android.server.wm.WindowManagerService;
import java.io.FileDescriptor;
@@ -2492,11 +2493,21 @@
}
void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
- final ActivityStack stack = getStack(PINNED_STACK_ID);
+ final PinnedActivityStack stack = getStack(PINNED_STACK_ID);
if (stack == null) {
Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found");
return;
}
+
+ // It is possible for the bounds animation from the WM to call this but be delayed by
+ // another AM call that is holding the AMS lock. In such a case, the pinnedBounds may be
+ // incorrect if AMS.resizeStackWithBoundsFromWindowManager() is already called while waiting
+ // for the AMS lock to be freed. So check and make sure these bounds are still good.
+ final PinnedStackWindowController stackController = stack.getWindowContainerController();
+ if (stackController.pinnedStackResizeAllowed()) {
+ return;
+ }
+
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizePinnedStack");
mWindowManager.deferSurfaceLayout();
try {
@@ -2857,12 +2868,12 @@
return false;
}
- moveActivityToPinnedStackLocked(r, null /* sourceBounds */, destBounds,
+ moveActivityToPinnedStackLocked(r, null /* sourceBounds */, 0f /* aspectRatio */,
true /* moveHomeStackToFront */, "moveTopActivityToPinnedStack");
return true;
}
- void moveActivityToPinnedStackLocked(ActivityRecord r, Rect sourceBounds, Rect destBounds,
+ void moveActivityToPinnedStackLocked(ActivityRecord r, Rect sourceBounds, float aspectRatio,
boolean moveHomeStackToFront, String reason) {
mWindowManager.deferSurfaceLayout();
@@ -2932,6 +2943,11 @@
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
resumeFocusedStackTopActivityLocked();
+ // Calculate the default bounds (don't use existing stack bounds as we may have just created
+ // the stack
+ final Rect destBounds = mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY,
+ aspectRatio, false /* useExistingStackBounds */);
+
// TODO(b/36099777): Schedule the PiP mode change here immediately until we can defer all
// callbacks until after the bounds animation
scheduleUpdatePictureInPictureModeIfNeeded(r.getTask(), destBounds, true /* immediate */);
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index cafc4f0..b91c7b1 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -210,11 +210,7 @@
if (!mService.mUserController.shouldConfirmCredentials(userId)) {
return null;
}
- // Allow direct boot aware activity to be displayed before the user is unlocked.
- if (aInfo.directBootAware && mService.mUserController.isUserRunningLocked(userId,
- ActivityManager.FLAG_AND_LOCKED)) {
- return null;
- }
+ // TODO(b/28935539): should allow certain activities to bypass work challenge
final IIntentSender target = mService.getIntentSenderLocked(
INTENT_SENDER_ACTIVITY, callingPackage,
Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
index 646f6ce..02ec075 100644
--- a/services/core/java/com/android/server/am/AppErrorDialog.java
+++ b/services/core/java/com/android/server/am/AppErrorDialog.java
@@ -106,7 +106,7 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final FrameLayout frame = (FrameLayout) findViewById(android.R.id.custom);
+ final FrameLayout frame = findViewById(android.R.id.custom);
final Context context = getContext();
LayoutInflater.from(context).inflate(
com.android.internal.R.layout.app_error_dialog, frame, true);
@@ -114,19 +114,19 @@
boolean hasRestart = !mRepeating && mIsRestartable;
final boolean hasReceiver = mProc.errorReportReceiver != null;
- final TextView restart = (TextView) findViewById(com.android.internal.R.id.aerr_restart);
+ final TextView restart = findViewById(com.android.internal.R.id.aerr_restart);
restart.setOnClickListener(this);
restart.setVisibility(hasRestart ? View.VISIBLE : View.GONE);
- final TextView report = (TextView) findViewById(com.android.internal.R.id.aerr_report);
+ final TextView report = findViewById(com.android.internal.R.id.aerr_report);
report.setOnClickListener(this);
report.setVisibility(hasReceiver ? View.VISIBLE : View.GONE);
- final TextView close = (TextView) findViewById(com.android.internal.R.id.aerr_close);
+ final TextView close = findViewById(com.android.internal.R.id.aerr_close);
close.setVisibility(!hasRestart ? View.VISIBLE : View.GONE);
close.setOnClickListener(this);
boolean showMute = !IS_USER_BUILD && Settings.Global.getInt(context.getContentResolver(),
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
- final TextView mute = (TextView) findViewById(com.android.internal.R.id.aerr_mute);
+ final TextView mute = findViewById(com.android.internal.R.id.aerr_mute);
mute.setOnClickListener(this);
mute.setVisibility(showMute ? View.VISIBLE : View.GONE);
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index 9e29725..a3a6778 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -104,18 +104,18 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final FrameLayout frame = (FrameLayout) findViewById(android.R.id.custom);
+ final FrameLayout frame = findViewById(android.R.id.custom);
final Context context = getContext();
LayoutInflater.from(context).inflate(
com.android.internal.R.layout.app_anr_dialog, frame, true);
- final TextView report = (TextView) findViewById(com.android.internal.R.id.aerr_report);
+ final TextView report = findViewById(com.android.internal.R.id.aerr_report);
report.setOnClickListener(this);
final boolean hasReceiver = mProc.errorReportReceiver != null;
report.setVisibility(hasReceiver ? View.VISIBLE : View.GONE);
- final TextView close = (TextView) findViewById(com.android.internal.R.id.aerr_close);
+ final TextView close = findViewById(com.android.internal.R.id.aerr_close);
close.setOnClickListener(this);
- final TextView wait = (TextView) findViewById(com.android.internal.R.id.aerr_wait);
+ final TextView wait = findViewById(com.android.internal.R.id.aerr_wait);
wait.setOnClickListener(this);
findViewById(com.android.internal.R.id.customPanel).setVisibility(View.VISIBLE);
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index dd3d4e0..baa71d7 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -16,6 +16,8 @@
package com.android.server.am;
+import android.content.pm.IPackageManager;
+import android.content.pm.PermissionInfo;
import android.os.Trace;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -795,6 +797,31 @@
.sendToTarget();
}
+ /**
+ * Return true if all given permissions are signature-only perms.
+ */
+ final boolean isSignaturePerm(String[] perms) {
+ if (perms == null) {
+ return false;
+ }
+ IPackageManager pm = AppGlobals.getPackageManager();
+ for (int i = perms.length-1; i >= 0; i--) {
+ try {
+ PermissionInfo pi = pm.getPermissionInfo(perms[i], 0);
+ if ((pi.protectionLevel & (PermissionInfo.PROTECTION_MASK_BASE
+ | PermissionInfo.PROTECTION_FLAG_PRIVILEGED))
+ != PermissionInfo.PROTECTION_SIGNATURE) {
+ // If this a signature permission and NOT allowed for privileged apps, it
+ // is okay... otherwise, nope!
+ return false;
+ }
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+ return true;
+ }
+
final void processNextBroadcast(boolean fromMsg) {
synchronized(mService) {
BroadcastRecord r;
@@ -1246,7 +1273,8 @@
|| (r.intent.getComponent() == null
&& r.intent.getPackage() == null
&& ((r.intent.getFlags()
- & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0))) {
+ & Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0)
+ && !isSignaturePerm(r.requiredPermissions))) {
mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
component.getPackageName());
Slog.w(TAG, "Background execution not allowed: receiving "
diff --git a/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
index 4a87941..c2f1890 100644
--- a/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
+++ b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
@@ -46,6 +46,7 @@
/**
* Writes the contents of a BatteryStats.Uid into a HealthStatsWriter.
*/
+ @SuppressWarnings("deprecation")
public void writeUid(HealthStatsWriter uidWriter, BatteryStats bs, BatteryStats.Uid uid) {
int N;
BatteryStats.Timer timer;
@@ -365,8 +366,7 @@
uid.getSystemCpuTimeUs(STATS_SINCE_UNPLUGGED)/1000);
// MEASUREMENT_CPU_POWER_MAMS
- uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_CPU_POWER_MAMS,
- uid.getCpuPowerMaUs(STATS_SINCE_UNPLUGGED)/1000);
+ uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_CPU_POWER_MAMS, 0);
}
/**
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index f05bfb6..c697f28 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -28,12 +28,14 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.TransactionTooLargeException;
import android.os.UserHandle;
import android.util.Slog;
import android.util.TimeUtils;
+import com.android.internal.os.IResultReceiver;
import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
import java.io.PrintWriter;
@@ -50,6 +52,7 @@
boolean sent = false;
boolean canceled = false;
private long whitelistDuration = 0;
+ private RemoteCallbackList<IResultReceiver> mCancelCallbacks;
String stringName;
String lastTagPrefix;
@@ -191,11 +194,31 @@
ref = new WeakReference<PendingIntentRecord>(this);
}
- void setWhitelistDuration(long duration) {
+ void setWhitelistDurationLocked(long duration) {
this.whitelistDuration = duration;
this.stringName = null;
}
+ public void registerCancelListenerLocked(IResultReceiver receiver) {
+ if (mCancelCallbacks == null) {
+ mCancelCallbacks = new RemoteCallbackList<>();
+ }
+ mCancelCallbacks.register(receiver);
+ }
+
+ public void unregisterCancelListenerLocked(IResultReceiver receiver) {
+ mCancelCallbacks.unregister(receiver);
+ if (mCancelCallbacks.getRegisteredCallbackCount() <= 0) {
+ mCancelCallbacks = null;
+ }
+ }
+
+ public RemoteCallbackList<IResultReceiver> detachCancelListenersLocked() {
+ RemoteCallbackList<IResultReceiver> listeners = mCancelCallbacks;
+ mCancelCallbacks = null;
+ return listeners;
+ }
+
public void send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
String requiredPermission, Bundle options) {
sendInner(code, intent, resolvedType, finishedReceiver,
@@ -234,7 +257,6 @@
sent = true;
if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) {
owner.cancelIntentSenderLocked(this, true);
- canceled = true;
}
Intent finalIntent = key.requestIntent != null
@@ -398,6 +420,13 @@
TimeUtils.formatDuration(whitelistDuration, pw);
pw.println();
}
+ if (mCancelCallbacks != null) {
+ pw.print(prefix); pw.println("mCancelCallbacks:");
+ for (int i = 0; i < mCancelCallbacks.getRegisteredCallbackCount(); i++) {
+ pw.print(prefix); pw.print(" #"); pw.print(i); pw.print(": ");
+ pw.println(mCancelCallbacks.getRegisteredCallbackItem(i));
+ }
+ }
}
public String toString() {
diff --git a/services/core/java/com/android/server/am/PinnedActivityStack.java b/services/core/java/com/android/server/am/PinnedActivityStack.java
index 394e902..cd9c42c 100644
--- a/services/core/java/com/android/server/am/PinnedActivityStack.java
+++ b/services/core/java/com/android/server/am/PinnedActivityStack.java
@@ -21,7 +21,7 @@
import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
import com.android.server.wm.PinnedStackWindowController;
-import com.android.server.wm.StackWindowController;
+import com.android.server.wm.PinnedStackWindowListener;
import java.util.ArrayList;
import java.util.List;
@@ -29,7 +29,8 @@
/**
* State and management of the pinned stack of activities.
*/
-class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> {
+class PinnedActivityStack extends ActivityStack<PinnedStackWindowController>
+ implements PinnedStackWindowListener {
PinnedActivityStack(ActivityContainer activityContainer,
RecentTasks recentTasks, boolean onTop) {
@@ -55,8 +56,8 @@
getWindowContainerController().setPictureInPictureActions(actions);
}
- boolean isBoundsAnimatingToFullscreen() {
- return getWindowContainerController().isBoundsAnimatingToFullscreen();
+ boolean isAnimatingBoundsToFullscreen() {
+ return getWindowContainerController().isAnimatingBoundsToFullscreen();
}
@Override
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 0c2c204..f8a4d4b 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -658,7 +658,8 @@
// Must reparent first in window manager to avoid a situation where AM can delete the
// we are coming from in WM before we reparent because it became empty.
- mWindowContainerController.reparent(toStack.getWindowContainerController(), position);
+ mWindowContainerController.reparent(toStack.getWindowContainerController(), position,
+ moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
// Move the task
sourceStack.removeTask(this, reason, REMOVE_TASK_MODE_MOVING);
@@ -1613,6 +1614,9 @@
String iconFilename = null;
int colorPrimary = 0;
int colorBackground = 0;
+ int statusBarColor = 0;
+ int navigationBarColor = 0;
+ boolean topActivity = true;
for (--activityNdx; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = mActivities.get(activityNdx);
if (r.taskDescription != null) {
@@ -1625,13 +1629,16 @@
if (colorPrimary == 0) {
colorPrimary = r.taskDescription.getPrimaryColor();
}
- if (colorBackground == 0) {
+ if (topActivity) {
colorBackground = r.taskDescription.getBackgroundColor();
+ statusBarColor = r.taskDescription.getStatusBarColor();
+ navigationBarColor = r.taskDescription.getNavigationBarColor();
}
}
+ topActivity = false;
}
lastTaskDescription = new TaskDescription(label, null, iconFilename, colorPrimary,
- colorBackground);
+ colorBackground, statusBarColor, navigationBarColor);
if (mWindowContainerController != null) {
mWindowContainerController.setTaskDescription(lastTaskDescription);
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index c11f531..2687242 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -23,6 +23,7 @@
import static android.os.Process.FIRST_APPLICATION_UID;
import android.Manifest;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppGlobals;
@@ -968,7 +969,8 @@
VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
for (int i = 0; i < numStreamTypes; i++) {
- streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[mStreamVolumeAlias[i]], i);
+ streams[i] =
+ new VolumeStreamState(System.VOLUME_SETTINGS_INT[mStreamVolumeAlias[i]], i);
}
checkAllFixedVolumeDevices();
@@ -1020,7 +1022,14 @@
}
mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
- mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY] = a11yStreamAlias;
+ final int oldStreamA11yAlias = mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY];
+ if (oldStreamA11yAlias != a11yStreamAlias) {
+ mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY] = a11yStreamAlias;
+ mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
+ System.VOLUME_SETTINGS_INT[a11yStreamAlias];
+ // restore the value from the settings when the alias changes
+ mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].readSettings();
+ }
if (updateVolumes) {
mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias],
@@ -3992,13 +4001,19 @@
return devices;
}
- public String getSettingNameForDevice(int device) {
- String name = mVolumeIndexSettingName;
- String suffix = AudioSystem.getOutputDeviceName(device);
- if (suffix.isEmpty()) {
- return name;
+ public @Nullable String getSettingNameForDevice(int device) {
+ if (!hasValidSettingsName()) {
+ return null;
}
- return name + "_" + suffix;
+ final String suffix = AudioSystem.getOutputDeviceName(device);
+ if (suffix.isEmpty()) {
+ return mVolumeIndexSettingName;
+ }
+ return mVolumeIndexSettingName + "_" + suffix;
+ }
+
+ private boolean hasValidSettingsName() {
+ return (mVolumeIndexSettingName != null && !mVolumeIndexSettingName.isEmpty());
}
public void readSettings() {
@@ -4033,13 +4048,18 @@
remainingDevices &= ~device;
// retrieve current volume for device
- String name = getSettingNameForDevice(device);
// if no volume stored for current stream and device, use default volume if default
// device, continue otherwise
int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
- int index = Settings.System.getIntForUser(
- mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
+ int index;
+ if (!hasValidSettingsName()) {
+ index = defaultIndex;
+ } else {
+ String name = getSettingNameForDevice(device);
+ index = Settings.System.getIntForUser(
+ mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
+ }
if (index == -1) {
continue;
}
@@ -4420,10 +4440,12 @@
if (mIsSingleVolume && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) {
return;
}
- System.putIntForUser(mContentResolver,
- streamState.getSettingNameForDevice(device),
- (streamState.getIndex(device) + 5)/ 10,
- UserHandle.USER_CURRENT);
+ if (streamState.hasValidSettingsName()) {
+ System.putIntForUser(mContentResolver,
+ streamState.getSettingNameForDevice(device),
+ (streamState.getIndex(device) + 5)/ 10,
+ UserHandle.USER_CURRENT);
+ }
}
private void persistRingerMode(int ringerMode) {
@@ -6059,6 +6081,7 @@
mVolumeController.setA11yMode(sIndependentA11yVolume ?
VolumePolicy.A11Y_MODE_INDEPENDENT_A11Y_VOLUME :
VolumePolicy.A11Y_MODE_MEDIA_A11Y_VOLUME);
+ mVolumeController.postVolumeChanged(AudioManager.STREAM_ACCESSIBILITY, 0);
}
}
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 51aa4f8..9eda929 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -57,7 +57,7 @@
.setCurve(new float[] { 0.f, 1.f } /* times */,
new float[] { 1.f, 0.2f } /* volumes */)
.setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
- .setDurationMs(MediaFocusControl.getFocusRampTimeMs(
+ .setDurationMillis(MediaFocusControl.getFocusRampTimeMs(
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build()))
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
index ad66faa..5dee91d 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
@@ -23,9 +23,6 @@
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
-import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
-import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
-import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.NetworkId;
import android.net.ConnectivityMetricsEvent;
import android.net.metrics.ApfProgramEvent;
@@ -34,6 +31,7 @@
import android.net.metrics.DhcpClientEvent;
import android.net.metrics.DhcpErrorEvent;
import android.net.metrics.DnsEvent;
+import android.net.metrics.ConnectStats;
import android.net.metrics.IpManagerEvent;
import android.net.metrics.IpReachabilityEvent;
import android.net.metrics.NetworkEvent;
@@ -41,7 +39,12 @@
import android.net.metrics.ValidationProbeEvent;
import android.os.Parcelable;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.NetworkId;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.Pair;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -77,20 +80,51 @@
}
public static IpConnectivityEvent toProto(ConnectivityMetricsEvent ev) {
- final IpConnectivityEvent out = new IpConnectivityEvent();
+ final IpConnectivityEvent out = buildEvent(ev.netId, ev.transports, ev.ifname);
+ out.timeMs = ev.timestamp;
if (!setEvent(out, ev.data)) {
return null;
}
- out.timeMs = ev.timestamp;
- out.networkId = ev.netId;
- out.transports = ev.transports;
- if (ev.ifname != null) {
- out.ifName = ev.ifname;
- }
- inferLinkLayer(out);
return out;
}
+ public static IpConnectivityEvent toProto(ConnectStats in) {
+ IpConnectivityLogClass.ConnectStatistics stats =
+ new IpConnectivityLogClass.ConnectStatistics();
+ stats.connectCount = in.connectCount;
+ stats.connectBlockingCount = in.connectBlockingCount;
+ stats.ipv6AddrCount = in.ipv6ConnectCount;
+ stats.latenciesMs = in.latencies.toArray();
+ stats.errnosCounters = toPairArray(in.errnos);
+ final IpConnectivityEvent out = buildEvent(in.netId, in.transports, null);
+ out.setConnectStatistics(stats);
+ return out;
+ }
+
+
+ public static IpConnectivityEvent toProto(DnsEvent in) {
+ IpConnectivityLogClass.DNSLookupBatch dnsLookupBatch =
+ new IpConnectivityLogClass.DNSLookupBatch();
+ in.resize(in.eventCount);
+ dnsLookupBatch.eventTypes = bytesToInts(in.eventTypes);
+ dnsLookupBatch.returnCodes = bytesToInts(in.returnCodes);
+ dnsLookupBatch.latenciesMs = in.latenciesMs;
+ final IpConnectivityEvent out = buildEvent(in.netId, in.transports, null);
+ out.setDnsLookupBatch(dnsLookupBatch);
+ return out;
+ }
+
+ private static IpConnectivityEvent buildEvent(int netId, long transports, String ifname) {
+ final IpConnectivityEvent ev = new IpConnectivityEvent();
+ ev.networkId = netId;
+ ev.transports = transports;
+ if (ifname != null) {
+ ev.ifName = ifname;
+ }
+ inferLinkLayer(ev);
+ return ev;
+ }
+
private static boolean setEvent(IpConnectivityEvent out, Parcelable in) {
if (in instanceof DhcpErrorEvent) {
setDhcpErrorEvent(out, (DhcpErrorEvent) in);
@@ -102,11 +136,6 @@
return true;
}
- if (in instanceof DnsEvent) {
- setDnsEvent(out, (DnsEvent) in);
- return true;
- }
-
if (in instanceof IpManagerEvent) {
setIpManagerEvent(out, (IpManagerEvent) in);
return true;
@@ -163,16 +192,6 @@
out.setDhcpEvent(dhcpEvent);
}
- private static void setDnsEvent(IpConnectivityEvent out, DnsEvent in) {
- IpConnectivityLogClass.DNSLookupBatch dnsLookupBatch =
- new IpConnectivityLogClass.DNSLookupBatch();
- dnsLookupBatch.networkId = netIdOf(in.netId);
- dnsLookupBatch.eventTypes = bytesToInts(in.eventTypes);
- dnsLookupBatch.returnCodes = bytesToInts(in.returnCodes);
- dnsLookupBatch.latenciesMs = in.latenciesMs;
- out.setDnsLookupBatch(dnsLookupBatch);
- }
-
private static void setIpManagerEvent(IpConnectivityEvent out, IpManagerEvent in) {
IpConnectivityLogClass.IpProvisioningEvent ipProvisioningEvent =
new IpConnectivityLogClass.IpProvisioningEvent();
@@ -268,6 +287,18 @@
return out;
}
+ private static Pair[] toPairArray(SparseIntArray counts) {
+ final int s = counts.size();
+ Pair[] pairs = new Pair[s];
+ for (int i = 0; i < s; i++) {
+ Pair p = new Pair();
+ p.key = counts.keyAt(i);
+ p.value = counts.valueAt(i);
+ pairs[i] = p;
+ }
+ return pairs;
+ }
+
private static NetworkId netIdOf(int netid) {
final NetworkId ni = new NetworkId();
ni.networkId = netid;
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
index da56a07..475d786 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
@@ -76,7 +76,8 @@
@VisibleForTesting
public final Impl impl = new Impl();
- private NetdEventListenerService mNetdListener;
+ @VisibleForTesting
+ NetdEventListenerService mNetdListener;
@GuardedBy("mLock")
private ArrayList<ConnectivityMetricsEvent> mBuffer;
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index 7b9c60c..214cfce 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -18,10 +18,9 @@
import android.content.Context;
import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
import android.net.INetdEventCallback;
import android.net.Network;
-import android.net.NetworkRequest;
+import android.net.NetworkCapabilities;
import android.net.metrics.ConnectStats;
import android.net.metrics.DnsEvent;
import android.net.metrics.INetdEventListener;
@@ -29,17 +28,17 @@
import android.os.RemoteException;
import android.text.format.DateUtils;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.BitUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.TokenBucket;
-import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.ConnectStatistics;
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
import java.io.PrintWriter;
-import java.util.Arrays;
import java.util.List;
-import java.util.SortedMap;
-import java.util.TreeMap;
+import java.util.function.Function;
+import java.util.function.IntFunction;
/**
* Implementation of the INetdEventListener interface.
@@ -52,8 +51,7 @@
private static final boolean DBG = false;
private static final boolean VDBG = false;
- // TODO: read this constant from system property
- private static final int MAX_LOOKUPS_PER_DNS_EVENT = 100;
+ private static final int INITIAL_DNS_BATCH_SIZE = 100;
// Rate limit connect latency logging to 1 measurement per 15 seconds (5760 / day) with maximum
// bursts of 5000 measurements.
@@ -61,81 +59,17 @@
private static final int CONNECT_LATENCY_FILL_RATE = 15 * (int) DateUtils.SECOND_IN_MILLIS;
private static final int CONNECT_LATENCY_MAXIMUM_RECORDS = 20000;
- // Stores the results of a number of consecutive DNS lookups on the same network.
- // This class is not thread-safe and it is the responsibility of the service to call its methods
- // on one thread at a time.
- private class DnsEventBatch {
- private final int mNetId;
-
- private final byte[] mEventTypes = new byte[MAX_LOOKUPS_PER_DNS_EVENT];
- private final byte[] mReturnCodes = new byte[MAX_LOOKUPS_PER_DNS_EVENT];
- private final int[] mLatenciesMs = new int[MAX_LOOKUPS_PER_DNS_EVENT];
- private int mEventCount;
-
- public DnsEventBatch(int netId) {
- mNetId = netId;
- }
-
- public void addResult(byte eventType, byte returnCode, int latencyMs) {
- mEventTypes[mEventCount] = eventType;
- mReturnCodes[mEventCount] = returnCode;
- mLatenciesMs[mEventCount] = latencyMs;
- mEventCount++;
- if (mEventCount == MAX_LOOKUPS_PER_DNS_EVENT) {
- logAndClear();
- }
- }
-
- public void logAndClear() {
- // Did we lose a race with addResult?
- if (mEventCount == 0) {
- return;
- }
-
- // Only log as many events as we actually have.
- byte[] eventTypes = Arrays.copyOf(mEventTypes, mEventCount);
- byte[] returnCodes = Arrays.copyOf(mReturnCodes, mEventCount);
- int[] latenciesMs = Arrays.copyOf(mLatenciesMs, mEventCount);
- mMetricsLog.log(new DnsEvent(mNetId, eventTypes, returnCodes, latenciesMs));
- maybeLog("Logging %d results for netId %d", mEventCount, mNetId);
- mEventCount = 0;
- }
-
- // For debugging and unit tests only.
- public String toString() {
- return String.format("%s %d %d", getClass().getSimpleName(), mNetId, mEventCount);
- }
- }
-
- // Only sorted for ease of debugging. Because we only typically have a handful of networks up
- // at any given time, performance is not a concern.
+ // Sparse arrays of DNS and connect events, grouped by net id.
@GuardedBy("this")
- private final SortedMap<Integer, DnsEventBatch> mEventBatches = new TreeMap<>();
+ private final SparseArray<DnsEvent> mDnsEvents = new SparseArray<>();
+ @GuardedBy("this")
+ private final SparseArray<ConnectStats> mConnectEvents = new SparseArray<>();
- // We register a NetworkCallback to ensure that when a network disconnects, we flush the DNS
- // queries we've logged on that network. Because we do not do this periodically, we might lose
- // up to MAX_LOOKUPS_PER_DNS_EVENT lookup stats on each network when the system is shutting
- // down. We believe this to be sufficient for now.
private final ConnectivityManager mCm;
- private final IpConnectivityLog mMetricsLog;
- private final NetworkCallback mNetworkCallback = new NetworkCallback() {
- @Override
- public void onLost(Network network) {
- synchronized (NetdEventListenerService.this) {
- DnsEventBatch batch = mEventBatches.remove(network.netId);
- if (batch != null) {
- batch.logAndClear();
- }
- }
- }
- };
@GuardedBy("this")
private final TokenBucket mConnectTb =
new TokenBucket(CONNECT_LATENCY_FILL_RATE, CONNECT_LATENCY_BURST_LIMIT);
- @GuardedBy("this")
- private ConnectStats mConnectStats = makeConnectStats();
-
// Callback should only be registered/unregistered when logging is being enabled/disabled in DPM
// by the device owner. It's DevicePolicyManager's responsibility to ensure that.
@GuardedBy("this")
@@ -152,16 +86,13 @@
}
public NetdEventListenerService(Context context) {
- this(context.getSystemService(ConnectivityManager.class), new IpConnectivityLog());
+ this(context.getSystemService(ConnectivityManager.class));
}
@VisibleForTesting
- public NetdEventListenerService(ConnectivityManager cm, IpConnectivityLog log) {
+ public NetdEventListenerService(ConnectivityManager cm) {
// We are started when boot is complete, so ConnectivityService should already be running.
mCm = cm;
- mMetricsLog = log;
- final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
- mCm.registerNetworkCallback(request, mNetworkCallback);
}
@Override
@@ -172,16 +103,16 @@
throws RemoteException {
maybeVerboseLog("onDnsEvent(%d, %d, %d, %dms)", netId, eventType, returnCode, latencyMs);
- DnsEventBatch batch = mEventBatches.get(netId);
- if (batch == null) {
- batch = new DnsEventBatch(netId);
- mEventBatches.put(netId, batch);
+ DnsEvent dnsEvent = mDnsEvents.get(netId);
+ if (dnsEvent == null) {
+ dnsEvent = makeDnsEvent(netId);
+ mDnsEvents.put(netId, dnsEvent);
}
- batch.addResult((byte) eventType, (byte) returnCode, latencyMs);
+ dnsEvent.addResult((byte) eventType, (byte) returnCode, latencyMs);
if (mNetdEventCallback != null) {
- mNetdEventCallback.onDnsEvent(hostname, ipAddresses, ipAddressesCount,
- System.currentTimeMillis(), uid);
+ long timestamp = System.currentTimeMillis();
+ mNetdEventCallback.onDnsEvent(hostname, ipAddresses, ipAddressesCount, timestamp, uid);
}
}
@@ -192,7 +123,12 @@
int port, int uid) throws RemoteException {
maybeVerboseLog("onConnectEvent(%d, %d, %dms)", netId, error, latencyMs);
- mConnectStats.addEvent(error, latencyMs, ipAddr);
+ ConnectStats connectStats = mConnectEvents.get(netId);
+ if (connectStats == null) {
+ connectStats = makeConnectStats(netId);
+ mConnectEvents.put(netId, connectStats);
+ }
+ connectStats.addEvent(error, latencyMs, ipAddr);
if (mNetdEventCallback != null) {
mNetdEventCallback.onConnectEvent(ipAddr, port, System.currentTimeMillis(), uid);
@@ -200,21 +136,8 @@
}
public synchronized void flushStatistics(List<IpConnectivityEvent> events) {
- events.add(flushConnectStats());
- // TODO: migrate DnsEventBatch to IpConnectivityLogClass.DNSLatencies
- }
-
- private IpConnectivityEvent connectStatsProto() {
- // TODO: add transport information
- IpConnectivityEvent ev = new IpConnectivityEvent();
- ev.setConnectStatistics(mConnectStats.toProto());
- return ev;
- }
-
- private IpConnectivityEvent flushConnectStats() {
- IpConnectivityEvent ev = connectStatsProto();
- mConnectStats = makeConnectStats();
- return ev;
+ flushProtos(events, mConnectEvents, IpConnectivityEventBuilder::toProto);
+ flushProtos(events, mDnsEvents, IpConnectivityEventBuilder::toProto);
}
public synchronized void dump(PrintWriter writer) {
@@ -226,18 +149,47 @@
}
public synchronized void list(PrintWriter pw) {
- for (DnsEventBatch batch : mEventBatches.values()) {
- pw.println(batch.toString());
- }
- pw.println(mConnectStats.toString());
+ listEvents(pw, mConnectEvents, (x) -> x);
+ listEvents(pw, mDnsEvents, (x) -> x);
}
public synchronized void listAsProtos(PrintWriter pw) {
- pw.println(connectStatsProto().toString());
+ listEvents(pw, mConnectEvents, IpConnectivityEventBuilder::toProto);
+ listEvents(pw, mDnsEvents, IpConnectivityEventBuilder::toProto);
}
- private ConnectStats makeConnectStats() {
- return new ConnectStats(mConnectTb, CONNECT_LATENCY_MAXIMUM_RECORDS);
+ private static <T> void flushProtos(List<IpConnectivityEvent> out, SparseArray<T> in,
+ Function<T, IpConnectivityEvent> mapper) {
+ for (int i = 0; i < in.size(); i++) {
+ out.add(mapper.apply(in.valueAt(i)));
+ }
+ in.clear();
+ }
+
+ public static <T> void listEvents(
+ PrintWriter pw, SparseArray<T> events, Function<T, Object> mapper) {
+ for (int i = 0; i < events.size(); i++) {
+ pw.println(mapper.apply(events.valueAt(i)).toString());
+ }
+ }
+
+ private ConnectStats makeConnectStats(int netId) {
+ long transports = getTransports(netId);
+ return new ConnectStats(netId, transports, mConnectTb, CONNECT_LATENCY_MAXIMUM_RECORDS);
+ }
+
+ private DnsEvent makeDnsEvent(int netId) {
+ long transports = getTransports(netId);
+ return new DnsEvent(netId, transports, INITIAL_DNS_BATCH_SIZE);
+ }
+
+ private long getTransports(int netId) {
+ // TODO: directly query ConnectivityService instead of going through Binder interface.
+ NetworkCapabilities nc = mCm.getNetworkCapabilities(new Network(netId));
+ if (nc == null) {
+ return 0;
+ }
+ return BitUtils.packBits(nc.getTransportTypes());
}
private static void maybeLog(String s, Object... args) {
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index d591858..d3c74e6 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -70,6 +70,7 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
+import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
@@ -90,6 +91,8 @@
private static final String DEFAULT_HTTP_URL =
"http://connectivitycheck.gstatic.com/generate_204";
private static final String DEFAULT_FALLBACK_URL = "http://www.google.com/gen_204";
+ private static final String DEFAULT_OTHER_FALLBACK_URLS =
+ "http://play.googleapis.com/generate_204";
private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) "
+ "AppleWebKit/537.36 (KHTML, like Gecko) "
+ "Chrome/52.0.2743.82 Safari/537.36";
@@ -259,6 +262,13 @@
// This variable is set before transitioning to the mCaptivePortalState.
private CaptivePortalProbeResult mLastPortalProbeResult = CaptivePortalProbeResult.FAILED;
+ // Configuration values for captive portal detection probes.
+ private final String mCaptivePortalUserAgent;
+ private final URL mCaptivePortalHttpsUrl;
+ private final URL mCaptivePortalHttpUrl;
+ private final URL[] mCaptivePortalFallbackUrls;
+ private int mNextFallbackUrlIndex = 0;
+
public NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo,
NetworkRequest defaultRequest) {
this(context, handler, networkAgentInfo, defaultRequest, new IpConnectivityLog());
@@ -293,6 +303,11 @@
mUseHttps = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.CAPTIVE_PORTAL_USE_HTTPS, 1) == 1;
+ mCaptivePortalUserAgent = getCaptivePortalUserAgent(context);
+ mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl(context));
+ mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl(context));
+ mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls(context);
+
start();
}
@@ -301,6 +316,11 @@
if (DBG) Log.d(TAG + "/" + mNetworkAgentInfo.name(), s);
}
+ private void validationLog(int probeType, Object url, String msg) {
+ String probeName = ValidationProbeEvent.getProbeName(probeType);
+ validationLog(String.format("%s %s %s", probeName, url, msg));
+ }
+
private void validationLog(String s) {
if (DBG) log(s);
validationLogs.log(s);
@@ -434,7 +454,7 @@
intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL,
mLastPortalProbeResult.detectUrl);
intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT,
- getCaptivePortalUserAgent(mContext));
+ mCaptivePortalUserAgent);
intent.setFlags(
Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
@@ -650,9 +670,24 @@
return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTP_URL, DEFAULT_HTTP_URL);
}
- private static String getCaptivePortalFallbackUrl(Context context) {
- return getSetting(context,
+ private URL[] makeCaptivePortalFallbackUrls(Context context) {
+ String separator = ",";
+ String firstUrl = getSetting(context,
Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL, DEFAULT_FALLBACK_URL);
+ String joinedUrls = firstUrl + separator + getSetting(context,
+ Settings.Global.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS, DEFAULT_OTHER_FALLBACK_URLS);
+ List<URL> urls = new ArrayList<>();
+ for (String s : joinedUrls.split(separator)) {
+ URL u = makeURL(s);
+ if (u == null) {
+ continue;
+ }
+ urls.add(u);
+ }
+ if (urls.isEmpty()) {
+ Log.e(TAG, String.format("could not create any url from %s", joinedUrls));
+ }
+ return urls.toArray(new URL[urls.size()]);
}
private static String getCaptivePortalUserAgent(Context context) {
@@ -664,6 +699,15 @@
return value != null ? value : defaultValue;
}
+ private URL nextFallbackUrl() {
+ if (mCaptivePortalFallbackUrls.length == 0) {
+ return null;
+ }
+ int idx = Math.abs(mNextFallbackUrlIndex) % mCaptivePortalFallbackUrls.length;
+ mNextFallbackUrlIndex += new Random().nextInt(); // randomely change url without memory.
+ return mCaptivePortalFallbackUrls[idx];
+ }
+
@VisibleForTesting
protected CaptivePortalProbeResult isCaptivePortal() {
if (!mIsCaptivePortalCheckEnabled) {
@@ -671,7 +715,9 @@
return new CaptivePortalProbeResult(204);
}
- URL pacUrl = null, httpsUrl = null, httpUrl = null, fallbackUrl = null;
+ URL pacUrl = null;
+ URL httpsUrl = mCaptivePortalHttpsUrl;
+ URL httpUrl = mCaptivePortalHttpUrl;
// On networks with a PAC instead of fetching a URL that should result in a 204
// response, we instead simply fetch the PAC script. This is done for a few reasons:
@@ -698,13 +744,8 @@
}
}
- if (pacUrl == null) {
- httpsUrl = makeURL(getCaptivePortalServerHttpsUrl(mContext));
- httpUrl = makeURL(getCaptivePortalServerHttpUrl(mContext));
- fallbackUrl = makeURL(getCaptivePortalFallbackUrl(mContext));
- if (httpUrl == null || httpsUrl == null) {
- return CaptivePortalProbeResult.FAILED;
- }
+ if ((pacUrl == null) && (httpUrl == null || httpsUrl == null)) {
+ return CaptivePortalProbeResult.FAILED;
}
long startTime = SystemClock.elapsedRealtime();
@@ -713,7 +754,7 @@
if (pacUrl != null) {
result = sendDnsAndHttpProbes(null, pacUrl, ValidationProbeEvent.PROBE_PAC);
} else if (mUseHttps) {
- result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl, fallbackUrl);
+ result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl);
} else {
result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP);
}
@@ -752,20 +793,19 @@
String connectInfo;
try {
InetAddress[] addresses = mNetworkAgentInfo.network.getAllByName(host);
- result = ValidationProbeEvent.DNS_SUCCESS;
- StringBuffer buffer = new StringBuffer(host).append("=");
+ StringBuffer buffer = new StringBuffer();
for (InetAddress address : addresses) {
- buffer.append(address.getHostAddress());
- if (address != addresses[addresses.length-1]) buffer.append(",");
+ buffer.append(',').append(address.getHostAddress());
}
- connectInfo = buffer.toString();
+ result = ValidationProbeEvent.DNS_SUCCESS;
+ connectInfo = "OK " + buffer.substring(1);
} catch (UnknownHostException e) {
result = ValidationProbeEvent.DNS_FAILURE;
- connectInfo = host;
+ connectInfo = "FAIL";
}
final long latency = watch.stop();
- String resultString = (ValidationProbeEvent.DNS_SUCCESS == result) ? "OK" : "FAIL";
- validationLog(String.format("%s %s %dms, %s", name, resultString, latency, connectInfo));
+ validationLog(ValidationProbeEvent.PROBE_DNS, host,
+ String.format("%dms %s", latency, connectInfo));
logValidationProbe(latency, ValidationProbeEvent.PROBE_DNS, result);
}
@@ -786,9 +826,8 @@
urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
urlConnection.setUseCaches(false);
- final String userAgent = getCaptivePortalUserAgent(mContext);
- if (userAgent != null) {
- urlConnection.setRequestProperty("User-Agent", userAgent);
+ if (mCaptivePortalUserAgent != null) {
+ urlConnection.setRequestProperty("User-Agent", mCaptivePortalUserAgent);
}
// cannot read request header after connection
String requestHeader = urlConnection.getRequestProperties().toString();
@@ -802,8 +841,7 @@
// Time how long it takes to get a response to our request
long responseTimestamp = SystemClock.elapsedRealtime();
- validationLog(ValidationProbeEvent.getProbeName(probeType) + " " + url +
- " time=" + (responseTimestamp - requestTimestamp) + "ms" +
+ validationLog(probeType, url, "time=" + (responseTimestamp - requestTimestamp) + "ms" +
" ret=" + httpResponseCode +
" request=" + requestHeader +
" headers=" + urlConnection.getHeaderFields());
@@ -815,27 +853,29 @@
// proxy server.
if (httpResponseCode == 200) {
if (probeType == ValidationProbeEvent.PROBE_PAC) {
- validationLog("PAC fetch 200 response interpreted as 204 response.");
+ validationLog(
+ probeType, url, "PAC fetch 200 response interpreted as 204 response.");
httpResponseCode = 204;
} else if (urlConnection.getContentLengthLong() == 0) {
// Consider 200 response with "Content-length=0" to not be a captive portal.
// There's no point in considering this a captive portal as the user cannot
// sign-in to an empty page. Probably the result of a broken transparent proxy.
// See http://b/9972012.
- validationLog(
+ validationLog(probeType, url,
"200 response with Content-length=0 interpreted as 204 response.");
httpResponseCode = 204;
} else if (urlConnection.getContentLengthLong() == -1) {
// When no Content-length (default value == -1), attempt to read a byte from the
// response. Do not use available() as it is unreliable. See http://b/33498325.
if (urlConnection.getInputStream().read() == -1) {
- validationLog("Empty 200 response interpreted as 204 response.");
+ validationLog(
+ probeType, url, "Empty 200 response interpreted as 204 response.");
httpResponseCode = 204;
}
}
}
} catch (IOException e) {
- validationLog("Probably not a portal: exception " + e);
+ validationLog(probeType, url, "Probably not a portal: exception " + e);
if (httpResponseCode == 599) {
// TODO: Ping gateway and DNS server and log results.
}
@@ -850,7 +890,7 @@
}
private CaptivePortalProbeResult sendParallelHttpProbes(
- ProxyInfo proxy, URL httpsUrl, URL httpUrl, URL fallbackUrl) {
+ ProxyInfo proxy, URL httpsUrl, URL httpUrl) {
// Number of probes to wait for. If a probe completes with a conclusive answer
// it shortcuts the latch immediately by forcing the count to 0.
final CountDownLatch latch = new CountDownLatch(2);
@@ -909,7 +949,8 @@
if (httpsResult.isPortal() || httpsResult.isSuccessful()) {
return httpsResult;
}
- // If a fallback url is specified, use a fallback probe to try again portal detection.
+ // If a fallback url exists, use a fallback probe to try again portal detection.
+ URL fallbackUrl = nextFallbackUrl();
if (fallbackUrl != null) {
CaptivePortalProbeResult result =
sendHttpProbe(fallbackUrl, ValidationProbeEvent.PROBE_FALLBACK);
@@ -1048,7 +1089,7 @@
}
private void logValidationProbe(long durationMs, int probeType, int probeResult) {
- long transports = mNetworkAgentInfo.networkCapabilities.getTransports();
+ int[] transports = mNetworkAgentInfo.networkCapabilities.getTransportTypes();
boolean isFirstValidation = validationStage().isFirstValidation;
ValidationProbeEvent ev = new ValidationProbeEvent();
ev.probeType = ValidationProbeEvent.makeProbeType(probeType, isFirstValidation);
diff --git a/services/core/java/com/android/server/fingerprint/EnumerateClient.java b/services/core/java/com/android/server/fingerprint/EnumerateClient.java
index 34f245f..1b8b89c 100644
--- a/services/core/java/com/android/server/fingerprint/EnumerateClient.java
+++ b/services/core/java/com/android/server/fingerprint/EnumerateClient.java
@@ -58,7 +58,7 @@
public int stop(boolean initiatedByClient) {
IBiometricsFingerprint daemon = getFingerprintDaemon();
if (daemon == null) {
- Slog.w(TAG, "stopAuthentication: no fingerprint HAL!");
+ Slog.w(TAG, "stopEnumeration: no fingerprint HAL!");
return ERROR_ESRCH;
}
try {
@@ -102,12 +102,12 @@
@Override
public boolean onEnrollResult(int fingerId, int groupId, int rem) {
if (DEBUG) Slog.w(TAG, "onEnrollResult() called for enumerate!");
- return true; // Invalid for Remove
+ return true; // Invalid for Enumerate.
}
@Override
public boolean onRemoved(int fingerId, int groupId, int remaining) {
if (DEBUG) Slog.w(TAG, "onRemoved() called for enumerate!");
- return true; // Invalid for Authenticate
+ return true; // Invalid for Enumerate.
}
}
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 85f7056..9b984c1 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -85,6 +85,7 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.LinkedList;
/**
* A service to manage multiple clients that want to access the fingerprint HAL API.
@@ -96,6 +97,7 @@
public class FingerprintService extends SystemService implements IHwBinder.DeathRecipient {
static final String TAG = "FingerprintService";
static final boolean DEBUG = true;
+ private static final boolean CLEANUP_UNUSED_FP = false;
private static final String FP_DATA_DIR = "fpdata";
private static final int MSG_USER_SWITCHING = 10;
private static final String ACTION_LOCKOUT_RESET =
@@ -134,6 +136,20 @@
private ClientMonitor mPendingClient;
private PerformanceStats mPerformanceStats;
+
+ private IBinder mToken = new Binder(); // used for internal FingerprintService enumeration
+ private LinkedList<Integer> mEnumeratingUserIds = new LinkedList<>();
+ private ArrayList<UserFingerprint> mUnknownFingerprints = new ArrayList<>(); // hw finterprints
+
+ private class UserFingerprint {
+ Fingerprint f;
+ int userId;
+ public UserFingerprint(Fingerprint f, int userId) {
+ this.f = f;
+ this.userId = userId;
+ }
+ }
+
// Normal fingerprint authentications are tracked by mPerformanceMap.
private HashMap<Integer, PerformanceStats> mPerformanceMap = new HashMap<>();
@@ -185,6 +201,7 @@
+ (mCurrentClient != null ? mCurrentClient.getOwnerString() : "null")
+ " failed to respond to cancel, starting client "
+ (mPendingClient != null ? mPendingClient.getOwnerString() : "null"));
+
mCurrentClient = null;
startClient(mPendingClient, false);
}
@@ -239,6 +256,7 @@
if (mHalDeviceId != 0) {
loadAuthenticatorIds();
updateActiveGroup(ActivityManager.getCurrentUser(), null);
+ doFingerprintCleanup(ActivityManager.getCurrentUser());
} else {
Slog.w(TAG, "Failed to open Fingerprint HAL!");
MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1);
@@ -253,7 +271,6 @@
// This operation can be expensive, so keep track of the elapsed time. Might need to move to
// background if it takes too long.
long t = System.currentTimeMillis();
-
mAuthenticatorIds.clear();
for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) {
int userId = getUserOrWorkProfileId(null, user.id);
@@ -268,14 +285,88 @@
}
}
+ private void doFingerprintCleanup(int userId) {
+ if (CLEANUP_UNUSED_FP) {
+ resetEnumerateState();
+ mEnumeratingUserIds.push(userId);
+ enumerateNextUser();
+ }
+ }
+
+ private void resetEnumerateState() {
+ if (DEBUG) Slog.v(TAG, "Enumerate cleaning up");
+ mEnumeratingUserIds.clear();
+ mUnknownFingerprints.clear();
+ }
+
+ private void enumerateNextUser() {
+ int nextUser = mEnumeratingUserIds.getFirst();
+ updateActiveGroup(nextUser, null);
+ boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
+
+ if (DEBUG) Slog.v(TAG, "Enumerating user id " + nextUser + " of "
+ + mEnumeratingUserIds.size() + " remaining users");
+
+ startEnumerate(mToken, nextUser, null, restricted, true /* internal */);
+ }
+
+ // Remove unknown fingerprints from hardware
+ private void cleanupUnknownFingerprints() {
+ if (!mUnknownFingerprints.isEmpty()) {
+ Slog.w(TAG, "unknown fingerprint size: " + mUnknownFingerprints.size());
+ UserFingerprint uf = mUnknownFingerprints.get(0);
+ mUnknownFingerprints.remove(uf);
+ boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
+ updateActiveGroup(uf.userId, null);
+ startRemove(mToken, uf.f.getFingerId(), uf.f.getGroupId(), uf.userId, null,
+ restricted, true /* internal */);
+ } else {
+ resetEnumerateState();
+ }
+ }
+
protected void handleEnumerate(long deviceId, int fingerId, int groupId, int remaining) {
- if (DEBUG) Slog.w(TAG, "Enumerate: fid=" + fingerId + ", gid="
- + groupId + "rem=" + remaining);
- // TODO: coordinate names with framework
+ if (DEBUG) Slog.w(TAG, "Enumerate: fid=" + fingerId
+ + ", gid=" + groupId
+ + ", dev=" + deviceId
+ + ", rem=" + remaining);
+
+ ClientMonitor client = mCurrentClient;
+
+ if ( !(client instanceof InternalRemovalClient) && !(client instanceof EnumerateClient) ) {
+ return;
+ }
+ client.onEnumerationResult(fingerId, groupId, remaining);
+
+ // All fingerprints in hardware for this user were enumerated
+ if (remaining == 0) {
+ mEnumeratingUserIds.poll();
+
+ if (client instanceof InternalEnumerateClient) {
+ List<Fingerprint> enrolled = ((InternalEnumerateClient) client).getEnumeratedList();
+ Slog.w(TAG, "Added " + enrolled.size() + " enumerated fingerprints for deletion");
+ for (Fingerprint f : enrolled) {
+ mUnknownFingerprints.add(new UserFingerprint(f, client.getTargetUserId()));
+ }
+ }
+
+ removeClient(client);
+
+ if (!mEnumeratingUserIds.isEmpty()) {
+ enumerateNextUser();
+ } else if (client instanceof InternalEnumerateClient) {
+ if (DEBUG) Slog.v(TAG, "Finished enumerating all users");
+ // This will start a chain of InternalRemovalClients
+ cleanupUnknownFingerprints();
+ }
+ }
}
protected void handleError(long deviceId, int error, int vendorCode) {
ClientMonitor client = mCurrentClient;
+ if (client instanceof InternalRemovalClient || client instanceof InternalEnumerateClient) {
+ resetEnumerateState();
+ }
if (client != null && client.onError(error, vendorCode)) {
removeClient(client);
}
@@ -301,10 +392,20 @@
}
protected void handleRemoved(long deviceId, int fingerId, int groupId, int remaining) {
+ if (DEBUG) Slog.w(TAG, "Removed: fid=" + fingerId
+ + ", gid=" + groupId
+ + ", dev=" + deviceId
+ + ", rem=" + remaining);
+
ClientMonitor client = mCurrentClient;
if (client != null && client.onRemoved(fingerId, groupId, remaining)) {
removeClient(client);
}
+ if (client instanceof InternalRemovalClient && !mUnknownFingerprints.isEmpty()) {
+ cleanupUnknownFingerprints();
+ } else if (client instanceof InternalRemovalClient){
+ resetEnumerateState();
+ }
}
protected void handleAuthenticated(long deviceId, int fingerId, int groupId,
@@ -355,6 +456,7 @@
void handleUserSwitching(int userId) {
updateActiveGroup(userId, null);
+ doFingerprintCleanup(userId);
}
private void removeClient(ClientMonitor client) {
@@ -431,7 +533,15 @@
ClientMonitor currentClient = mCurrentClient;
if (currentClient != null) {
if (DEBUG) Slog.v(TAG, "request stop current client " + currentClient.getOwnerString());
- currentClient.stop(initiatedByClient);
+ if (currentClient instanceof InternalEnumerateClient ||
+ currentClient instanceof InternalRemovalClient) {
+ // This condition means we're currently running internal diagnostics to
+ // remove extra fingerprints in the hardware and/or the software
+ // TODO: design an escape hatch in case client never finishes
+ }
+ else {
+ currentClient.stop(initiatedByClient);
+ }
mPendingClient = newClient;
mHandler.removeCallbacks(mResetClientState);
mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
@@ -448,47 +558,86 @@
}
void startRemove(IBinder token, int fingerId, int groupId, int userId,
- IFingerprintServiceReceiver receiver, boolean restricted) {
+ IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) {
IBiometricsFingerprint daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "startRemove: no fingerprint HAL!");
return;
}
- RemovalClient client = new RemovalClient(getContext(), mHalDeviceId, token,
- receiver, fingerId, groupId, userId, restricted, token.toString()) {
- @Override
- public void notifyUserActivity() {
- FingerprintService.this.userActivity();
- }
- @Override
- public IBiometricsFingerprint getFingerprintDaemon() {
- return FingerprintService.this.getFingerprintDaemon();
- }
- };
- startClient(client, true);
+ if (internal) {
+ Context context = getContext();
+ InternalRemovalClient client = new InternalRemovalClient(context, mHalDeviceId,
+ token, receiver, fingerId, groupId, userId, restricted,
+ context.getOpPackageName()) {
+ @Override
+ public void notifyUserActivity() {
+
+ }
+ @Override
+ public IBiometricsFingerprint getFingerprintDaemon() {
+ return FingerprintService.this.getFingerprintDaemon();
+ }
+ };
+ startClient(client, true);
+ }
+ else {
+ RemovalClient client = new RemovalClient(getContext(), mHalDeviceId, token,
+ receiver, fingerId, groupId, userId, restricted, token.toString()) {
+ @Override
+ public void notifyUserActivity() {
+ FingerprintService.this.userActivity();
+ }
+
+ @Override
+ public IBiometricsFingerprint getFingerprintDaemon() {
+ return FingerprintService.this.getFingerprintDaemon();
+ }
+ };
+ startClient(client, true);
+ }
}
void startEnumerate(IBinder token, int userId,
- IFingerprintServiceReceiver receiver, boolean restricted) {
+ IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) {
IBiometricsFingerprint daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "startEnumerate: no fingerprint HAL!");
return;
}
- EnumerateClient client = new EnumerateClient(getContext(), mHalDeviceId, token,
- receiver, userId, userId, restricted, token.toString()) {
- @Override
- public void notifyUserActivity() {
- FingerprintService.this.userActivity();
- }
+ if (internal) {
+ List<Fingerprint> enrolledList = getEnrolledFingerprints(userId);
+ Context context = getContext();
+ InternalEnumerateClient client = new InternalEnumerateClient(context, mHalDeviceId,
+ token, receiver, userId, userId, restricted, context.getOpPackageName(),
+ enrolledList) {
+ @Override
+ public void notifyUserActivity() {
- @Override
- public IBiometricsFingerprint getFingerprintDaemon() {
- return FingerprintService.this.getFingerprintDaemon();
- }
- };
- startClient(client, true);
+ }
+
+ @Override
+ public IBiometricsFingerprint getFingerprintDaemon() {
+ return FingerprintService.this.getFingerprintDaemon();
+ }
+ };
+ startClient(client, true);
+ }
+ else {
+ EnumerateClient client = new EnumerateClient(getContext(), mHalDeviceId, token,
+ receiver, userId, userId, restricted, token.toString()) {
+ @Override
+ public void notifyUserActivity() {
+ FingerprintService.this.userActivity();
+ }
+
+ @Override
+ public IBiometricsFingerprint getFingerprintDaemon() {
+ return FingerprintService.this.getFingerprintDaemon();
+ }
+ };
+ startClient(client, true);
+ }
}
public List<Fingerprint> getEnrolledFingerprints(int userId) {
@@ -978,11 +1127,13 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- startRemove(token, fingerId, groupId, userId, receiver, restricted);
+ startRemove(token, fingerId, groupId, userId, receiver,
+ restricted, false /* internal */);
}
});
}
+ @Override // Binder call
public void enumerate(final IBinder token, final int userId,
final IFingerprintServiceReceiver receiver) {
checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
@@ -990,7 +1141,7 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- startEnumerate(token, userId, receiver, restricted);
+ startEnumerate(token, userId, receiver, restricted, false /* internal */);
}
});
}
diff --git a/services/core/java/com/android/server/fingerprint/InternalEnumerateClient.java b/services/core/java/com/android/server/fingerprint/InternalEnumerateClient.java
new file mode 100644
index 0000000..f4d2596
--- /dev/null
+++ b/services/core/java/com/android/server/fingerprint/InternalEnumerateClient.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.fingerprint;
+
+import android.content.Context;
+import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.IFingerprintServiceReceiver;
+import android.os.IBinder;
+import android.util.Slog;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An internal class to help clean up unknown fingerprints in the hardware and software
+ */
+public abstract class InternalEnumerateClient extends EnumerateClient {
+
+ private List<Fingerprint> mEnrolledList;
+ private List<Fingerprint> mEnumeratedList = new ArrayList<>(); // list of fp to delete
+
+ public InternalEnumerateClient(Context context, long halDeviceId, IBinder token,
+ IFingerprintServiceReceiver receiver, int groupId, int userId,
+ boolean restricted, String owner, List<Fingerprint> enrolledList) {
+
+ super(context, halDeviceId, token, receiver, userId, groupId, restricted, owner);
+ mEnrolledList = enrolledList;
+ }
+
+ private void handleEnumeratedFingerprint(int fingerId, int groupId, int remaining) {
+
+ boolean matched = false;
+ for (int i=0; i<mEnrolledList.size(); i++) {
+ if (mEnrolledList.get(i).getFingerId() == fingerId) {
+ mEnrolledList.remove(i);
+ matched = true;
+ Slog.e(TAG, "Matched fingerprint fid=" + fingerId);
+ break;
+ }
+ }
+
+ // fingerId 0 means no fingerprints are in hardware
+ if (!matched && fingerId != 0) {
+ Fingerprint fingerprint = new Fingerprint("", groupId, fingerId, getHalDeviceId());
+ mEnumeratedList.add(fingerprint);
+ }
+ }
+
+ private void doFingerprintCleanup() {
+
+ if (mEnrolledList == null) {
+ return;
+ }
+
+ for (Fingerprint f : mEnrolledList) {
+ Slog.e(TAG, "Internal Enumerate: Removing dangling enrolled fingerprint: "
+ + f.getName() + " " + f.getFingerId() + " " + f.getGroupId()
+ + " " + f.getDeviceId());
+
+ FingerprintUtils.getInstance().removeFingerprintIdForUser(getContext(),
+ f.getFingerId(), getTargetUserId());
+ }
+ mEnrolledList.clear();
+ }
+
+ public List<Fingerprint> getEnumeratedList() {
+ return mEnumeratedList;
+ }
+
+ @Override
+ public boolean onEnumerationResult(int fingerId, int groupId, int remaining) {
+
+ handleEnumeratedFingerprint(fingerId, groupId, remaining);
+ if (remaining == 0) {
+ doFingerprintCleanup();
+ }
+
+ return fingerId == 0; // done when id hits 0
+ }
+
+}
diff --git a/services/core/java/com/android/server/fingerprint/InternalRemovalClient.java b/services/core/java/com/android/server/fingerprint/InternalRemovalClient.java
new file mode 100644
index 0000000..19f61fe
--- /dev/null
+++ b/services/core/java/com/android/server/fingerprint/InternalRemovalClient.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.fingerprint;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.hardware.fingerprint.IFingerprintServiceReceiver;
+import com.android.server.fingerprint.RemovalClient;
+
+public abstract class InternalRemovalClient extends RemovalClient {
+
+ public InternalRemovalClient(Context context, long halDeviceId, IBinder token,
+ IFingerprintServiceReceiver receiver, int fingerId, int groupId, int userId,
+ boolean restricted, String owner) {
+
+ super(context, halDeviceId, token, receiver, fingerId, groupId, userId, restricted, owner);
+
+ }
+}
diff --git a/services/core/java/com/android/server/fingerprint/RemovalClient.java b/services/core/java/com/android/server/fingerprint/RemovalClient.java
index ab1b9728..6610634 100644
--- a/services/core/java/com/android/server/fingerprint/RemovalClient.java
+++ b/services/core/java/com/android/server/fingerprint/RemovalClient.java
@@ -59,12 +59,23 @@
@Override
public int stop(boolean initiatedByClient) {
- // We don't actually stop remove, but inform the client that the cancel operation succeeded
- // so we can start the next operation.
- if (initiatedByClient) {
- onError(FingerprintManager.FINGERPRINT_ERROR_CANCELED, 0 /* vendorCode */);
+ IBiometricsFingerprint daemon = getFingerprintDaemon();
+ if (daemon == null) {
+ Slog.w(TAG, "stopRemoval: no fingerprint HAL!");
+ return ERROR_ESRCH;
}
- return 0;
+ try {
+ final int result = daemon.cancel();
+ if (result != 0) {
+ Slog.w(TAG, "stopRemoval failed, result=" + result);
+ return result;
+ }
+ if (DEBUG) Slog.w(TAG, "client " + getOwnerString() + " is no longer removing");
+ } catch (RemoteException e) {
+ Slog.e(TAG, "stopRemoval failed", e);
+ return ERROR_ESRCH;
+ }
+ return 0; // success
}
/*
diff --git a/services/core/java/com/android/server/job/JobCompletedListener.java b/services/core/java/com/android/server/job/JobCompletedListener.java
index 655abd7..34ba753b3 100644
--- a/services/core/java/com/android/server/job/JobCompletedListener.java
+++ b/services/core/java/com/android/server/job/JobCompletedListener.java
@@ -27,5 +27,5 @@
* Callback for when a job is completed.
* @param needsReschedule Whether the implementing class should reschedule this job.
*/
- void onJobCompleted(JobStatus jobStatus, boolean needsReschedule);
+ void onJobCompletedLocked(JobStatus jobStatus, boolean needsReschedule);
}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index cd3ba4c..d01de3c 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -37,6 +37,7 @@
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.app.job.IJobScheduler;
+import android.app.job.JobWorkItem;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -582,20 +583,8 @@
mStartedUsers = ArrayUtils.removeInt(mStartedUsers, userHandle);
}
- /**
- * Entry point from client to schedule the provided job.
- * This cancels the job if it's already been scheduled, and replaces it with the one provided.
- * @param job JobInfo object containing execution parameters
- * @param uId The package identifier of the application this job is for.
- * @return Result of this operation. See <code>JobScheduler#RESULT_*</code> return codes.
- */
- public int schedule(JobInfo job, int uId) {
- return scheduleAsPackage(job, uId, null, -1, null);
- }
-
- public int scheduleAsPackage(JobInfo job, int uId, String packageName, int userId,
- String tag) {
- JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag);
+ public int scheduleAsPackage(JobInfo job, JobWorkItem work, int uId, String packageName,
+ int userId, String tag) {
try {
if (ActivityManager.getService().isAppStartModeDisabled(uId,
job.getService().getPackageName())) {
@@ -605,9 +594,20 @@
}
} catch (RemoteException e) {
}
- if (DEBUG) Slog.d(TAG, "SCHEDULE: " + jobStatus.toShortString());
- JobStatus toCancel;
synchronized (mLock) {
+ final JobStatus toCancel = mJobs.getJobByUidAndJobId(uId, job.getId());
+
+ if (work != null && toCancel != null) {
+ // Fast path: we are adding work to an existing job, and the JobInfo is not
+ // changing. We can just directly enqueue this work in to the job.
+ if (toCancel.getJob().equals(job)) {
+ toCancel.enqueueWorkLocked(work);
+ return JobScheduler.RESULT_SUCCESS;
+ }
+ }
+
+ JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag);
+ if (DEBUG) Slog.d(TAG, "SCHEDULE: " + jobStatus.toShortString());
// Jobs on behalf of others don't apply to the per-app job cap
if (ENFORCE_MAX_JOBS && packageName == null) {
if (mJobs.countJobsForUid(uId) > MAX_JOBS_PER_APP) {
@@ -618,15 +618,18 @@
}
// This may throw a SecurityException.
- jobStatus.prepare(ActivityManager.getService());
+ jobStatus.prepareLocked(ActivityManager.getService());
- toCancel = mJobs.getJobByUidAndJobId(uId, job.getId());
if (toCancel != null) {
cancelJobImpl(toCancel, jobStatus);
}
- startTrackingJob(jobStatus, toCancel);
+ if (work != null) {
+ // If work has been supplied, enqueue it into the new job.
+ jobStatus.enqueueWorkLocked(work);
+ }
+ startTrackingJobLocked(jobStatus, toCancel);
+ mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
}
- mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
return JobScheduler.RESULT_SUCCESS;
}
@@ -715,17 +718,17 @@
}
private void cancelJobImpl(JobStatus cancelled, JobStatus incomingJob) {
- if (DEBUG) Slog.d(TAG, "CANCEL: " + cancelled.toShortString());
- cancelled.unprepare(ActivityManager.getService());
- stopTrackingJob(cancelled, incomingJob, true /* writeBack */);
synchronized (mLock) {
+ if (DEBUG) Slog.d(TAG, "CANCEL: " + cancelled.toShortString());
+ cancelled.unprepareLocked(ActivityManager.getService());
+ stopTrackingJobLocked(cancelled, incomingJob, true /* writeBack */);
// Remove from pending queue.
if (mPendingJobs.remove(cancelled)) {
mJobPackageTracker.noteNonpending(cancelled);
}
// Cancel if running.
stopJobOnServiceContextLocked(cancelled, JobParameters.REASON_CANCELED);
- reportActive();
+ reportActiveLocked();
}
}
@@ -773,7 +776,7 @@
}
}
- void reportActive() {
+ void reportActiveLocked() {
// active is true if pending queue contains jobs OR some job is running.
boolean active = mPendingJobs.size() > 0;
if (mPendingJobs.size() <= 0) {
@@ -895,20 +898,18 @@
* {@link com.android.server.job.JobStore}, and make sure all the relevant controllers know
* about.
*/
- private void startTrackingJob(JobStatus jobStatus, JobStatus lastJob) {
- synchronized (mLock) {
- if (!jobStatus.isPrepared()) {
- Slog.wtf(TAG, "Not yet prepared when started tracking: " + jobStatus);
- }
- final boolean update = mJobs.add(jobStatus);
- if (mReadyToRock) {
- for (int i = 0; i < mControllers.size(); i++) {
- StateController controller = mControllers.get(i);
- if (update) {
- controller.maybeStopTrackingJobLocked(jobStatus, null, true);
- }
- controller.maybeStartTrackingJobLocked(jobStatus, lastJob);
+ private void startTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
+ if (!jobStatus.isPreparedLocked()) {
+ Slog.wtf(TAG, "Not yet prepared when started tracking: " + jobStatus);
+ }
+ final boolean update = mJobs.add(jobStatus);
+ if (mReadyToRock) {
+ for (int i = 0; i < mControllers.size(); i++) {
+ StateController controller = mControllers.get(i);
+ if (update) {
+ controller.maybeStopTrackingJobLocked(jobStatus, null, true);
}
+ controller.maybeStartTrackingJobLocked(jobStatus, lastJob);
}
}
}
@@ -917,19 +918,20 @@
* Called when we want to remove a JobStatus object that we've finished executing. Returns the
* object removed.
*/
- private boolean stopTrackingJob(JobStatus jobStatus, JobStatus incomingJob,
+ private boolean stopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
boolean writeBack) {
- synchronized (mLock) {
- // Remove from store as well as controllers.
- final boolean removed = mJobs.remove(jobStatus, writeBack);
- if (removed && mReadyToRock) {
- for (int i=0; i<mControllers.size(); i++) {
- StateController controller = mControllers.get(i);
- controller.maybeStopTrackingJobLocked(jobStatus, incomingJob, false);
- }
+ // Deal with any remaining work items in the old job.
+ jobStatus.stopTrackingJobLocked(incomingJob);
+
+ // Remove from store as well as controllers.
+ final boolean removed = mJobs.remove(jobStatus, writeBack);
+ if (removed && mReadyToRock) {
+ for (int i=0; i<mControllers.size(); i++) {
+ StateController controller = mControllers.get(i);
+ controller.maybeStopTrackingJobLocked(jobStatus, incomingJob, false);
}
- return removed;
}
+ return removed;
}
private boolean stopJobOnServiceContextLocked(JobStatus job, int reason) {
@@ -990,7 +992,7 @@
*
* @see JobHandler#maybeQueueReadyJobsForExecutionLockedH
*/
- private JobStatus getRescheduleJobForFailure(JobStatus failureToReschedule) {
+ private JobStatus getRescheduleJobForFailureLocked(JobStatus failureToReschedule) {
final long elapsedNowMillis = SystemClock.elapsedRealtime();
final JobInfo job = failureToReschedule.getJob();
@@ -1017,7 +1019,7 @@
JobStatus.NO_LATEST_RUNTIME, backoffAttempts);
for (int ic=0; ic<mControllers.size(); ic++) {
StateController controller = mControllers.get(ic);
- controller.rescheduleForFailure(newJob, failureToReschedule);
+ controller.rescheduleForFailureLocked(newJob, failureToReschedule);
}
return newJob;
}
@@ -1065,13 +1067,13 @@
* @param needsReschedule Whether the implementing class should reschedule this job.
*/
@Override
- public void onJobCompleted(JobStatus jobStatus, boolean needsReschedule) {
+ public void onJobCompletedLocked(JobStatus jobStatus, boolean needsReschedule) {
if (DEBUG) {
Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule);
}
// Do not write back immediately if this is a periodic job. The job may get lost if system
// shuts down before it is added back.
- if (!stopTrackingJob(jobStatus, null, !jobStatus.getJob().isPeriodic())) {
+ if (!stopTrackingJobLocked(jobStatus, null, !jobStatus.getJob().isPeriodic())) {
if (DEBUG) {
Slog.d(TAG, "Could not find job to remove. Was job removed while executing?");
}
@@ -1085,24 +1087,24 @@
// the old job after scheduling the new one, but since we have no lock held here
// that may cause ordering problems if the app removes jobStatus while in here.
if (needsReschedule) {
- JobStatus rescheduled = getRescheduleJobForFailure(jobStatus);
+ JobStatus rescheduled = getRescheduleJobForFailureLocked(jobStatus);
try {
- rescheduled.prepare(ActivityManager.getService());
+ rescheduled.prepareLocked(ActivityManager.getService());
} catch (SecurityException e) {
Slog.w(TAG, "Unable to regrant job permissions for " + rescheduled);
}
- startTrackingJob(rescheduled, jobStatus);
+ startTrackingJobLocked(rescheduled, jobStatus);
} else if (jobStatus.getJob().isPeriodic()) {
JobStatus rescheduledPeriodic = getRescheduleJobForPeriodic(jobStatus);
try {
- rescheduledPeriodic.prepare(ActivityManager.getService());
+ rescheduledPeriodic.prepareLocked(ActivityManager.getService());
} catch (SecurityException e) {
Slog.w(TAG, "Unable to regrant job permissions for " + rescheduledPeriodic);
}
- startTrackingJob(rescheduledPeriodic, jobStatus);
+ startTrackingJobLocked(rescheduledPeriodic, jobStatus);
}
- jobStatus.unprepare(ActivityManager.getService());
- reportActive();
+ jobStatus.unprepareLocked(ActivityManager.getService());
+ reportActiveLocked();
mHandler.obtainMessage(MSG_CHECK_JOB_GREEDY).sendToTarget();
}
@@ -1269,8 +1271,7 @@
if (job.hasIdleConstraint()) {
idleCount++;
}
- if (job.hasConnectivityConstraint() || job.hasUnmeteredConstraint()
- || job.hasNotRoamingConstraint()) {
+ if (job.hasConnectivityConstraint()) {
connectivityCount++;
}
if (job.hasChargingConstraint()) {
@@ -1410,7 +1411,7 @@
Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs.");
}
assignJobsToContextsLocked();
- reportActive();
+ reportActiveLocked();
}
}
}
@@ -1698,7 +1699,37 @@
long ident = Binder.clearCallingIdentity();
try {
- return JobSchedulerService.this.schedule(job, uid);
+ return JobSchedulerService.this.scheduleAsPackage(job, null, uid, null, -1, null);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ // IJobScheduler implementation
+ @Override
+ public int enqueue(JobInfo job, JobWorkItem work) throws RemoteException {
+ if (DEBUG) {
+ Slog.d(TAG, "Enqueueing job: " + job.toString() + " work: " + work);
+ }
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+
+ enforceValidJobRequest(uid, job);
+ if (job.isPersisted()) {
+ throw new IllegalArgumentException("Can't enqueue work for persisted jobs");
+ }
+ if (work == null) {
+ throw new NullPointerException("work is null");
+ }
+
+ if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
+ }
+
+ long ident = Binder.clearCallingIdentity();
+ try {
+ return JobSchedulerService.this.scheduleAsPackage(job, work, uid, null, -1, null);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -1731,7 +1762,7 @@
long ident = Binder.clearCallingIdentity();
try {
- return JobSchedulerService.this.scheduleAsPackage(job, callerUid,
+ return JobSchedulerService.this.scheduleAsPackage(job, null, callerUid,
packageName, userId, tag);
} finally {
Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 728ed72d..c7ef0e2 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -21,11 +21,11 @@
import android.app.job.JobParameters;
import android.app.job.IJobCallback;
import android.app.job.IJobService;
+import android.app.job.JobWorkItem;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
-import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
@@ -195,7 +195,7 @@
mExecutionStartTimeElapsed = SystemClock.elapsedRealtime();
mVerb = VERB_BINDING;
- scheduleOpTimeOut();
+ scheduleOpTimeOutLocked();
final Intent intent = new Intent().setComponent(job.getServiceComponent());
boolean binding = mContext.bindServiceAsUser(intent, this,
Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND,
@@ -208,7 +208,7 @@
mParams = null;
mExecutionStartTimeElapsed = 0L;
mVerb = VERB_FINISHED;
- removeOpTimeOut();
+ removeOpTimeOutLocked();
return false;
}
try {
@@ -297,6 +297,38 @@
mCallbackHandler.obtainMessage(MSG_CALLBACK, jobId, ongoing ? 1 : 0).sendToTarget();
}
+ @Override
+ public JobWorkItem dequeueWork(int jobId) {
+ if (!verifyCallingUid()) {
+ throw new SecurityException("Bad calling uid: " + Binder.getCallingUid());
+ }
+ JobWorkItem work = null;
+ boolean stillWorking = false;
+ synchronized (mLock) {
+ if (mRunningJob != null) {
+ work = mRunningJob.dequeueWorkLocked();
+ stillWorking = mRunningJob.hasExecutingWorkLocked();
+ }
+ }
+ if (work == null && !stillWorking) {
+ jobFinished(jobId, false);
+ }
+ return work;
+ }
+
+ @Override
+ public boolean completeWork(int jobId, int workId) {
+ if (!verifyCallingUid()) {
+ throw new SecurityException("Bad calling uid: " + Binder.getCallingUid());
+ }
+ synchronized (mLock) {
+ if (mRunningJob != null) {
+ return mRunningJob.completeWorkLocked(workId);
+ }
+ return false;
+ }
+ }
+
/**
* We acquire/release a wakelock on onServiceConnected/unbindService. This mirrors the work
* we intend to send to the client - we stop sending work when the service is unbound so until
@@ -378,46 +410,18 @@
public void handleMessage(Message message) {
switch (message.what) {
case MSG_SERVICE_BOUND:
- removeOpTimeOut();
- handleServiceBoundH();
+ doServiceBound();
break;
case MSG_CALLBACK:
- if (DEBUG) {
- Slog.d(TAG, "MSG_CALLBACK of : " + mRunningJob
- + " v:" + VERB_STRINGS[mVerb]);
- }
- removeOpTimeOut();
-
- if (mVerb == VERB_STARTING) {
- final boolean workOngoing = message.arg2 == 1;
- handleStartedH(workOngoing);
- } else if (mVerb == VERB_EXECUTING ||
- mVerb == VERB_STOPPING) {
- final boolean reschedule = message.arg2 == 1;
- handleFinishedH(reschedule);
- } else {
- if (DEBUG) {
- Slog.d(TAG, "Unrecognised callback: " + mRunningJob);
- }
- }
+ doCallback(message.arg2);
break;
case MSG_CANCEL:
- if (mVerb == VERB_FINISHED) {
- if (DEBUG) {
- Slog.d(TAG,
- "Trying to process cancel for torn-down context, ignoring.");
- }
- return;
- }
- mParams.setStopReason(message.arg1);
- if (message.arg1 == JobParameters.REASON_PREEMPT) {
- mPreferredUid = mRunningJob != null ? mRunningJob.getUid() :
- NO_PREFERRED_UID;
- }
- handleCancelH();
+ doCancel(message.arg1);
break;
case MSG_TIMEOUT:
- handleOpTimeoutH();
+ synchronized (mLock) {
+ handleOpTimeoutH();
+ }
break;
case MSG_SHUTDOWN_EXECUTION:
closeAndCleanupJobH(true /* needsReschedule */);
@@ -427,6 +431,55 @@
}
}
+ void doServiceBound() {
+ synchronized (mLock) {
+ removeOpTimeOutLocked();
+ handleServiceBoundH();
+ }
+ }
+
+ void doCallback(int arg2) {
+ synchronized (mLock) {
+ if (DEBUG) {
+ Slog.d(TAG, "MSG_CALLBACK of : " + mRunningJob
+ + " v:" + VERB_STRINGS[mVerb]);
+ }
+ removeOpTimeOutLocked();
+
+ if (mVerb == VERB_STARTING) {
+ final boolean workOngoing = arg2 == 1;
+ handleStartedH(workOngoing);
+ } else if (mVerb == VERB_EXECUTING ||
+ mVerb == VERB_STOPPING) {
+ final boolean reschedule = arg2 == 1;
+ handleFinishedH(reschedule);
+ } else {
+ if (DEBUG) {
+ Slog.d(TAG, "Unrecognised callback: " + mRunningJob);
+ }
+ }
+ }
+ }
+
+ void doCancel(int arg1) {
+ synchronized (mLock) {
+ if (mVerb == VERB_FINISHED) {
+ if (DEBUG) {
+ Slog.d(TAG,
+ "Trying to process cancel for torn-down context, ignoring.");
+ }
+ return;
+ }
+ mParams.setStopReason(arg1);
+ if (arg1 == JobParameters.REASON_PREEMPT) {
+ mPreferredUid = mRunningJob != null ? mRunningJob.getUid() :
+ NO_PREFERRED_UID;
+ }
+ handleCancelH();
+ }
+
+ }
+
/** Start the job on the service. */
private void handleServiceBoundH() {
if (DEBUG) {
@@ -448,7 +501,7 @@
}
try {
mVerb = VERB_STARTING;
- scheduleOpTimeOut();
+ scheduleOpTimeOutLocked();
service.startJob(mParams);
} catch (Exception e) {
// We catch 'Exception' because client-app malice or bugs might induce a wide
@@ -483,7 +536,7 @@
handleCancelH();
return;
}
- scheduleOpTimeOut();
+ scheduleOpTimeOutLocked();
break;
default:
Slog.e(TAG, "Handling started job but job wasn't starting! Was "
@@ -587,7 +640,7 @@
* VERB_STOPPING.
*/
private void sendStopMessageH() {
- removeOpTimeOut();
+ removeOpTimeOutLocked();
if (mVerb != VERB_EXECUTING) {
Slog.e(TAG, "Sending onStopJob for a job that isn't started. " + mRunningJob);
closeAndCleanupJobH(false /* reschedule */);
@@ -595,7 +648,7 @@
}
try {
mVerb = VERB_STOPPING;
- scheduleOpTimeOut();
+ scheduleOpTimeOutLocked();
service.stopJob(mParams);
} catch (RemoteException e) {
Slog.e(TAG, "Error sending onStopJob to client.", e);
@@ -635,13 +688,13 @@
mCancelled.set(false);
service = null;
mAvailable = true;
+ removeOpTimeOutLocked();
+ removeMessages(MSG_CALLBACK);
+ removeMessages(MSG_SERVICE_BOUND);
+ removeMessages(MSG_CANCEL);
+ removeMessages(MSG_SHUTDOWN_EXECUTION);
+ mCompletedListener.onJobCompletedLocked(completedJob, reschedule);
}
- removeOpTimeOut();
- removeMessages(MSG_CALLBACK);
- removeMessages(MSG_SERVICE_BOUND);
- removeMessages(MSG_CANCEL);
- removeMessages(MSG_SHUTDOWN_EXECUTION);
- mCompletedListener.onJobCompleted(completedJob, reschedule);
}
}
@@ -650,8 +703,8 @@
* we haven't received a response in a certain amount of time, we want to give up and carry
* on with life.
*/
- private void scheduleOpTimeOut() {
- removeOpTimeOut();
+ private void scheduleOpTimeOutLocked() {
+ removeOpTimeOutLocked();
final long timeoutMillis;
switch (mVerb) {
@@ -678,7 +731,7 @@
}
- private void removeOpTimeOut() {
+ private void removeOpTimeOutLocked() {
mCallbackHandler.removeMessages(MSG_TIMEOUT);
}
}
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index c0264df..2e6cd3f 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -368,13 +368,16 @@
*/
private void writeConstraintsToXml(XmlSerializer out, JobStatus jobStatus) throws IOException {
out.startTag(null, XML_TAG_PARAMS_CONSTRAINTS);
- if (jobStatus.hasConnectivityConstraint()) {
+ if (jobStatus.needsAnyConnectivity()) {
out.attribute(null, "connectivity", Boolean.toString(true));
}
- if (jobStatus.hasUnmeteredConstraint()) {
+ if (jobStatus.needsMeteredConnectivity()) {
+ out.attribute(null, "metered", Boolean.toString(true));
+ }
+ if (jobStatus.needsUnmeteredConnectivity()) {
out.attribute(null, "unmetered", Boolean.toString(true));
}
- if (jobStatus.hasNotRoamingConstraint()) {
+ if (jobStatus.needsNonRoamingConnectivity()) {
out.attribute(null, "not-roaming", Boolean.toString(true));
}
if (jobStatus.hasIdleConstraint()) {
@@ -454,7 +457,7 @@
IActivityManager am = ActivityManager.getService();
for (int i=0; i<jobs.size(); i++) {
JobStatus js = jobs.get(i);
- js.prepare(am);
+ js.prepareLocked(am);
this.jobSet.add(js);
}
}
@@ -713,6 +716,10 @@
if (val != null) {
jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
}
+ val = parser.getAttributeValue(null, "metered");
+ if (val != null) {
+ jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_METERED);
+ }
val = parser.getAttributeValue(null, "unmetered");
if (val != null) {
jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index b458d8b..5ebcc93 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -84,8 +84,7 @@
@Override
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
- if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()
- || jobStatus.hasNotRoamingConstraint()) {
+ if (jobStatus.hasConnectivityConstraint()) {
updateConstraintsSatisfied(jobStatus, null);
mTrackedJobs.add(jobStatus);
}
@@ -94,8 +93,7 @@
@Override
public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
boolean forUpdate) {
- if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()
- || jobStatus.hasNotRoamingConstraint()) {
+ if (jobStatus.hasConnectivityConstraint()) {
mTrackedJobs.remove(jobStatus);
}
}
@@ -114,11 +112,13 @@
&& capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
final boolean connected = info != null && info.isConnected();
final boolean connectionUsable = connected && validated;
+ final boolean metered = connected && info.isMetered();
final boolean unmetered = connected && !info.isMetered();
final boolean notRoaming = connected && !info.isRoaming();
boolean changed = false;
changed |= jobStatus.setConnectivityConstraintSatisfied(connectionUsable);
+ changed |= jobStatus.setMeteredConstraintSatisfied(metered);
changed |= jobStatus.setUnmeteredConstraintSatisfied(unmetered);
changed |= jobStatus.setNotRoamingConstraintSatisfied(notRoaming);
@@ -134,6 +134,7 @@
+ " for " + jobStatus + ": usable=" + connectionUsable
+ " connected=" + connected
+ " validated=" + validated
+ + " metered=" + metered
+ " unmetered=" + unmetered
+ " notRoaming=" + notRoaming);
}
@@ -244,9 +245,10 @@
js.printUniqueId(pw);
pw.print(" from ");
UserHandle.formatUid(pw, js.getSourceUid());
- pw.print(": C="); pw.print(js.hasConnectivityConstraint());
- pw.print(": UM="); pw.print(js.hasUnmeteredConstraint());
- pw.print(": NR="); pw.println(js.hasNotRoamingConstraint());
+ pw.print(": C="); pw.print(js.needsAnyConnectivity());
+ pw.print(": M="); pw.print(js.needsMeteredConnectivity());
+ pw.print(": UM="); pw.print(js.needsUnmeteredConnectivity());
+ pw.print(": NR="); pw.println(js.needsNonRoamingConnectivity());
}
}
}
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 5d209fc..29f0e2c 100644
--- a/services/core/java/com/android/server/job/controllers/ContentObserverController.java
+++ b/services/core/java/com/android/server/job/controllers/ContentObserverController.java
@@ -164,7 +164,7 @@
&& 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.
+ // lose any content changes that had happened 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) {
@@ -195,16 +195,14 @@
}
@Override
- public void rescheduleForFailure(JobStatus newJob, JobStatus failureToReschedule) {
+ public void rescheduleForFailureLocked(JobStatus newJob, JobStatus failureToReschedule) {
if (failureToReschedule.hasContentTriggerConstraint()
&& newJob.hasContentTriggerConstraint()) {
- synchronized (mLock) {
- // Our job has failed, and we are scheduling a new job for it.
- // Copy the last reported content changes in to the new job, so when
- // we schedule the new one we will pick them up and report them again.
- newJob.changedAuthorities = failureToReschedule.changedAuthorities;
- newJob.changedUris = failureToReschedule.changedUris;
- }
+ // Our job has failed, and we are scheduling a new job for it.
+ // Copy the last reported content changes in to the new job, so when
+ // we schedule the new one we will pick them up and report them again.
+ newJob.changedAuthorities = failureToReschedule.changedAuthorities;
+ newJob.changedUris = failureToReschedule.changedUris;
}
}
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 d27d0e5..e8cc078 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -19,6 +19,7 @@
import android.app.AppGlobals;
import android.app.IActivityManager;
import android.app.job.JobInfo;
+import android.app.job.JobWorkItem;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.ContentProvider;
@@ -35,6 +36,7 @@
import android.util.TimeUtils;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.Arrays;
/**
@@ -66,6 +68,11 @@
static final int CONSTRAINT_CONTENT_TRIGGER = 1<<26;
static final int CONSTRAINT_DEVICE_NOT_DOZING = 1<<25;
static final int CONSTRAINT_NOT_ROAMING = 1<<24;
+ static final int CONSTRAINT_METERED = 1<<23;
+
+ static final int CONNECTIVITY_MASK =
+ CONSTRAINT_UNMETERED | CONSTRAINT_CONNECTIVITY |
+ CONSTRAINT_NOT_ROAMING | CONSTRAINT_METERED;
// Soft override: ignore constraints like time that don't affect API availability
public static final int OVERRIDE_SOFT = 1;
@@ -126,6 +133,14 @@
public int lastEvaluatedPriority;
+ // If non-null, this is work that has been enqueued for the job.
+ public ArrayList<JobWorkItem> pendingWork;
+
+ // If non-null, this is work that is currently being executed.
+ public ArrayList<JobWorkItem> executingWork;
+
+ public int nextPendingWorkId = 1;
+
// Used by shell commands
public int overrideState = 0;
@@ -181,15 +196,28 @@
this.numFailures = numFailures;
int requiredConstraints = job.getConstraintFlags();
- if (job.getNetworkType() == JobInfo.NETWORK_TYPE_ANY) {
- requiredConstraints |= CONSTRAINT_CONNECTIVITY;
+
+ switch (job.getNetworkType()) {
+ case JobInfo.NETWORK_TYPE_NONE:
+ // No constraint.
+ break;
+ case JobInfo.NETWORK_TYPE_ANY:
+ requiredConstraints |= CONSTRAINT_CONNECTIVITY;
+ break;
+ case JobInfo.NETWORK_TYPE_UNMETERED:
+ requiredConstraints |= CONSTRAINT_UNMETERED;
+ break;
+ case JobInfo.NETWORK_TYPE_NOT_ROAMING:
+ requiredConstraints |= CONSTRAINT_NOT_ROAMING;
+ break;
+ case JobInfo.NETWORK_TYPE_METERED:
+ requiredConstraints |= CONSTRAINT_METERED;
+ break;
+ default:
+ Slog.w(TAG, "Unrecognized networking constraint " + job.getNetworkType());
+ break;
}
- if (job.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED) {
- requiredConstraints |= CONSTRAINT_UNMETERED;
- }
- if (job.getNetworkType() == JobInfo.NETWORK_TYPE_NOT_ROAMING) {
- requiredConstraints |= CONSTRAINT_NOT_ROAMING;
- }
+
if (earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME) {
requiredConstraints |= CONSTRAINT_TIMING_DELAY;
}
@@ -256,7 +284,59 @@
earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis);
}
- public void prepare(IActivityManager am) {
+ public void enqueueWorkLocked(JobWorkItem work) {
+ if (pendingWork == null) {
+ pendingWork = new ArrayList<>();
+ }
+ work.setWorkId(nextPendingWorkId);
+ nextPendingWorkId++;
+ pendingWork.add(work);
+ }
+
+ public JobWorkItem dequeueWorkLocked() {
+ if (pendingWork != null && pendingWork.size() > 0) {
+ JobWorkItem work = pendingWork.remove(0);
+ if (work != null) {
+ if (executingWork == null) {
+ executingWork = new ArrayList<>();
+ }
+ executingWork.add(work);
+ }
+ return work;
+ }
+ return null;
+ }
+
+ public boolean hasExecutingWorkLocked() {
+ return executingWork != null && executingWork.size() > 0;
+ }
+
+ public boolean completeWorkLocked(int workId) {
+ if (executingWork != null) {
+ final int N = executingWork.size();
+ for (int i = 0; i < N; i++) {
+ if (executingWork.get(i).getWorkId() == workId) {
+ executingWork.remove(i);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public void stopTrackingJobLocked(JobStatus incomingJob) {
+ if (incomingJob != null) {
+ // We are replacing with a new job -- transfer the work!
+ incomingJob.pendingWork = pendingWork;
+ pendingWork = null;
+ incomingJob.nextPendingWorkId = nextPendingWorkId;
+ } else {
+ // We are completely stopping the job... need to clean up work.
+ // XXX remove perms when that is impl.
+ }
+ }
+
+ public void prepareLocked(IActivityManager am) {
if (prepared) {
Slog.wtf(TAG, "Already prepared: " + this);
return;
@@ -271,7 +351,7 @@
}
}
- public void unprepare(IActivityManager am) {
+ public void unprepareLocked(IActivityManager am) {
if (!prepared) {
Slog.wtf(TAG, "Hasn't been prepared: " + this);
return;
@@ -288,7 +368,7 @@
}
}
- public boolean isPrepared() {
+ public boolean isPreparedLocked() {
return prepared;
}
@@ -405,15 +485,24 @@
return job.getFlags();
}
+ /** Does this job have any sort of networking constraint? */
public boolean hasConnectivityConstraint() {
+ return (requiredConstraints&CONNECTIVITY_MASK) != 0;
+ }
+
+ public boolean needsAnyConnectivity() {
return (requiredConstraints&CONSTRAINT_CONNECTIVITY) != 0;
}
- public boolean hasUnmeteredConstraint() {
+ public boolean needsUnmeteredConnectivity() {
return (requiredConstraints&CONSTRAINT_UNMETERED) != 0;
}
- public boolean hasNotRoamingConstraint() {
+ public boolean needsMeteredConnectivity() {
+ return (requiredConstraints&CONSTRAINT_METERED) != 0;
+ }
+
+ public boolean needsNonRoamingConnectivity() {
return (requiredConstraints&CONSTRAINT_NOT_ROAMING) != 0;
}
@@ -509,6 +598,10 @@
return setConstraintSatisfied(CONSTRAINT_UNMETERED, state);
}
+ boolean setMeteredConstraintSatisfied(boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_METERED, state);
+ }
+
boolean setNotRoamingConstraintSatisfied(boolean state) {
return setConstraintSatisfied(CONSTRAINT_NOT_ROAMING, state);
}
@@ -854,6 +947,22 @@
}
}
}
+ if (pendingWork != null && pendingWork.size() > 0) {
+ pw.print(prefix); pw.println("Pending work:");
+ for (int i = 0; i < pendingWork.size(); i++) {
+ JobWorkItem work = pendingWork.get(i);
+ pw.print(prefix); pw.print(" #"); pw.print(i); pw.print(": #");
+ pw.print(work.getWorkId()); pw.print(" "); pw.println(work.getIntent());
+ }
+ }
+ if (executingWork != null && executingWork.size() > 0) {
+ pw.print(prefix); pw.println("Executing work:");
+ for (int i = 0; i < executingWork.size(); i++) {
+ JobWorkItem work = executingWork.get(i);
+ pw.print(prefix); pw.print(" #"); pw.print(i); pw.print(": #");
+ pw.print(work.getWorkId()); pw.print(" "); pw.println(work.getIntent());
+ }
+ }
pw.print(prefix); pw.print("Earliest run time: ");
pw.println(formatRunTime(earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME));
pw.print(prefix); pw.print("Latest run time: ");
diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java
index 1721fb9..497faab 100644
--- a/services/core/java/com/android/server/job/controllers/StateController.java
+++ b/services/core/java/com/android/server/job/controllers/StateController.java
@@ -61,7 +61,7 @@
/**
* Called when a new job is being created to reschedule an old failed job.
*/
- public void rescheduleForFailure(JobStatus newJob, JobStatus failureToReschedule) {
+ public void rescheduleForFailureLocked(JobStatus newJob, JobStatus failureToReschedule) {
}
public abstract void dumpControllerStateLocked(PrintWriter pw, int filterUid);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 2e499f1..9157c4e 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -2992,7 +2992,12 @@
// Skip if it had no restrictions to begin with
if ((oldRules & MASK_ALL_NETWORKS) == 0) continue;
}
- updateRulesForPowerRestrictionsUL(uid, oldRules, paroled);
+ final int newUidRules = updateRulesForPowerRestrictionsUL(uid, oldRules, paroled);
+ if (newUidRules == RULE_NONE) {
+ mUidRules.delete(uid);
+ } else {
+ mUidRules.put(uid, newUidRules);
+ }
}
}
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 2fab288..c28fb67 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -251,7 +251,7 @@
public IConditionProvider findConditionProvider(ComponentName component) {
if (component == null) return null;
- for (ManagedServiceInfo service : mServices) {
+ for (ManagedServiceInfo service : getServices()) {
if (component.equals(service.component)) {
return provider(service);
}
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 0774779..90e9b92 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -90,7 +90,7 @@
// contains connections to all connected services, including app services
// and system services
- protected final ArrayList<ManagedServiceInfo> mServices = new ArrayList<ManagedServiceInfo>();
+ private final ArrayList<ManagedServiceInfo> mServices = new ArrayList<ManagedServiceInfo>();
// things that will be put into mServices as soon as they're ready
private final ArrayList<String> mServicesBinding = new ArrayList<String>();
// lists the component names of all enabled (and therefore potentially connected)
@@ -154,6 +154,13 @@
abstract protected void onServiceAdded(ManagedServiceInfo info);
+ protected List<ManagedServiceInfo> getServices() {
+ synchronized (mMutex) {
+ List<ManagedServiceInfo> services = new ArrayList<>(mServices);
+ return services;
+ }
+ }
+
protected void onServiceRemovedLocked(ManagedServiceInfo removed) { }
private ManagedServiceInfo newServiceInfo(IInterface service,
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index d6c89a4..63647ff 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -21,15 +21,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.provider.Settings;
import android.telecom.TelecomManager;
-import android.text.TextUtils;
-import android.util.ArrayMap;
import com.android.internal.util.NotificationMessagingUtil;
@@ -56,8 +48,8 @@
@Override
public int compare(NotificationRecord left, NotificationRecord right) {
// first all colorized notifications
- boolean leftImportantColorized = isImportantColorized(left);
- boolean rightImportantColorized = isImportantColorized(right);
+ boolean leftImportantColorized = isImportantOngoingColorized(left);
+ boolean rightImportantColorized = isImportantOngoingColorized(right);
if (leftImportantColorized != rightImportantColorized) {
return -1 * Boolean.compare(leftImportantColorized, rightImportantColorized);
@@ -118,7 +110,10 @@
return -1 * Long.compare(left.getRankingTimeMs(), right.getRankingTimeMs());
}
- private boolean isImportantColorized(NotificationRecord record) {
+ private boolean isImportantOngoingColorized(NotificationRecord record) {
+ if (!isOngoing(record)) {
+ return false;
+ }
if (record.getImportance() < NotificationManager.IMPORTANCE_LOW) {
return false;
}
@@ -133,7 +128,6 @@
if (record.getImportance() < NotificationManager.IMPORTANCE_LOW) {
return false;
}
- // TODO: add whitelist
return isCall(record) || isMediaNotification(record);
}
@@ -153,8 +147,7 @@
}
private boolean isOngoing(NotificationRecord record) {
- final int ongoingFlags =
- Notification.FLAG_FOREGROUND_SERVICE | Notification.FLAG_ONGOING_EVENT;
+ final int ongoingFlags = Notification.FLAG_FOREGROUND_SERVICE;
return (record.getNotification().flags & ongoingFlags) != 0;
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 64ee1e9..f334ba4 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -19,6 +19,12 @@
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
+import static android.service.notification.NotificationListenerService
+ .NOTIFICATION_CHANNEL_OR_GROUP_ADDED;
+import static android.service.notification.NotificationListenerService
+ .NOTIFICATION_CHANNEL_OR_GROUP_DELETED;
+import static android.service.notification.NotificationListenerService
+ .NOTIFICATION_CHANNEL_OR_GROUP_UPDATED;
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL_ALL;
import static android.service.notification.NotificationListenerService.REASON_CHANNEL_BANNED;
@@ -70,6 +76,7 @@
import android.app.StatusBarManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
+import android.companion.ICompanionDeviceManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -100,6 +107,7 @@
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -144,6 +152,7 @@
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.NotificationVisibility;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
@@ -260,6 +269,7 @@
Vibrator mVibrator;
private WindowManagerInternal mWindowManagerInternal;
private AlarmManager mAlarmManager;
+ private ICompanionDeviceManager mCompanionManager;
final IBinder mForegroundToken = new Binder();
private Handler mHandler;
@@ -1004,7 +1014,8 @@
// TODO: Tests should call onStart instead once the methods above are removed.
@VisibleForTesting
void init(Looper looper, IPackageManager packageManager, PackageManager packageManagerClient,
- LightsManager lightsManager, NotificationListeners notificationListeners) {
+ LightsManager lightsManager, NotificationListeners notificationListeners,
+ ICompanionDeviceManager companionManager) {
Resources resources = getContext().getResources();
mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
@@ -1017,6 +1028,7 @@
mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
mAppUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
+ mCompanionManager = companionManager;
mHandler = new WorkerHandler(looper);
mRankingThread.start();
@@ -1192,7 +1204,8 @@
@Override
public void onStart() {
init(Looper.myLooper(), AppGlobals.getPackageManager(), getContext().getPackageManager(),
- getLocalService(LightsManager.class), new NotificationListeners());
+ getLocalService(LightsManager.class), new NotificationListeners(),
+ null);
publishBinderService(Context.NOTIFICATION_SERVICE, mService);
publishLocalService(NotificationManagerInternal.class, mInternalService);
}
@@ -1294,7 +1307,8 @@
sendRegisteredOnlyBroadcast(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
}
- private void updateNotificationChannelInt(String pkg, int uid, NotificationChannel channel) {
+ private void updateNotificationChannelInt(String pkg, int uid, NotificationChannel channel,
+ boolean fromListener) {
if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
// cancel
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channel.getId(), 0, 0, true,
@@ -1303,6 +1317,14 @@
}
mRankingHelper.updateNotificationChannel(pkg, uid, channel);
+ final NotificationChannel modifiedChannel =
+ mRankingHelper.getNotificationChannel(pkg, uid, channel.getId(), false);
+
+ if (!fromListener) {
+ mListeners.notifyNotificationChannelChanged(
+ pkg, modifiedChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
+ }
+
synchronized (mNotificationLock) {
final int N = mNotificationList.size();
for (int i = N - 1; i >= 0; --i) {
@@ -1311,8 +1333,7 @@
&& r.sbn.getUid() == uid
&& channel.getId() != null
&& channel.getId().equals(r.getChannel().getId())) {
- r.updateNotificationChannel(mRankingHelper.getNotificationChannel(
- pkg, uid, channel.getId(), false));
+ r.updateNotificationChannel(modifiedChannel);
}
}
}
@@ -1421,6 +1442,11 @@
return INotificationManager.Stub.asInterface(mService);
}
+ @VisibleForTesting
+ NotificationManagerInternal getInternalService() {
+ return mInternalService;
+ }
+
private final IBinder mService = new INotificationManager.Stub() {
// Toasts
// ============================================================================
@@ -1621,6 +1647,8 @@
Preconditions.checkNotNull(group, "group in list is null");
mRankingHelper.createNotificationChannelGroup(pkg, Binder.getCallingUid(), group,
true /* fromTargetApp */);
+ mListeners.notifyNotificationChannelGroupChanged(pkg, group,
+ NOTIFICATION_CHANNEL_OR_GROUP_ADDED);
}
savePolicyFile();
}
@@ -1634,6 +1662,9 @@
Preconditions.checkNotNull(channel, "channel in list is null");
mRankingHelper.createNotificationChannel(pkg, uid, channel,
true /* fromTargetApp */);
+ mListeners.notifyNotificationChannelChanged(pkg,
+ mRankingHelper.getNotificationChannel(pkg, uid, channel.getId(), false),
+ NOTIFICATION_CHANNEL_OR_GROUP_ADDED);
}
savePolicyFile();
}
@@ -1669,12 +1700,16 @@
@Override
public void deleteNotificationChannel(String pkg, String channelId) {
checkCallerIsSystemOrSameApp(pkg);
+ final int callingUid = Binder.getCallingUid();
if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {
throw new IllegalArgumentException("Cannot delete default channel");
}
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channelId, 0, 0, true,
- UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED, null);
- mRankingHelper.deleteNotificationChannel(pkg, Binder.getCallingUid(), channelId);
+ UserHandle.getUserId(callingUid), REASON_CHANNEL_BANNED, null);
+ mRankingHelper.deleteNotificationChannel(pkg, callingUid, channelId);
+ mListeners.notifyNotificationChannelChanged(pkg,
+ mRankingHelper.getNotificationChannel(pkg, callingUid, channelId, true),
+ NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
savePolicyFile();
}
@@ -1687,16 +1722,28 @@
}
@Override
- public void deleteNotificationChannelGroup(String pkg, String channelGroupId) {
+ public void deleteNotificationChannelGroup(String pkg, String groupId) {
checkCallerIsSystemOrSameApp(pkg);
- List<String> deletedChannelIds = mRankingHelper.deleteNotificationChannelGroup(
- pkg, Binder.getCallingUid(), channelGroupId);
- for (int i = 0; i < deletedChannelIds.size(); i++) {
- cancelAllNotificationsInt(MY_UID, MY_PID, pkg, deletedChannelIds.get(i), 0, 0, true,
- UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED, null);
+ final int callingUid = Binder.getCallingUid();
+ NotificationChannelGroup groupToDelete =
+ mRankingHelper.getNotificationChannelGroup(groupId, pkg, callingUid);
+ if (groupToDelete != null) {
+ List<NotificationChannel> deletedChannels =
+ mRankingHelper.deleteNotificationChannelGroup(pkg, callingUid, groupId);
+ for (int i = 0; i < deletedChannels.size(); i++) {
+ final NotificationChannel deletedChannel = deletedChannels.get(i);
+ cancelAllNotificationsInt(MY_UID, MY_PID, pkg, deletedChannel.getId(), 0, 0,
+ true,
+ UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED,
+ null);
+ mListeners.notifyNotificationChannelChanged(pkg, deletedChannel,
+ NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
+ }
+ mListeners.notifyNotificationChannelGroupChanged(
+ pkg, groupToDelete, NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
+ savePolicyFile();
}
- savePolicyFile();
}
@Override
@@ -1704,7 +1751,7 @@
NotificationChannel channel) {
enforceSystemOrSystemUI("Caller not system or systemui");
Preconditions.checkNotNull(channel);
- updateNotificationChannelInt(pkg, uid, channel);
+ updateNotificationChannelInt(pkg, uid, channel, false);
}
@Override
@@ -2641,6 +2688,47 @@
Binder.restoreCallingIdentity(identity);
}
}
+
+ @Override
+ public void updateNotificationChannelFromPrivilegedListener(INotificationListener token,
+ String pkg, NotificationChannel channel) throws RemoteException {
+ Preconditions.checkNotNull(channel);
+
+ ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
+ if (!hasCompanionDevice(info)) {
+ throw new SecurityException(info + " does not have access");
+ }
+
+ int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
+ updateNotificationChannelInt(pkg, uid, channel, true);
+ }
+
+ @Override
+ public ParceledListSlice<NotificationChannel> getNotificationChannelsFromPrivilegedListener(
+ INotificationListener token, String pkg) throws RemoteException {
+ ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
+ if (!hasCompanionDevice(info)) {
+ throw new SecurityException(info + " does not have access");
+ }
+
+ int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
+ return mRankingHelper.getNotificationChannels(pkg, uid, false /* includeDeleted */);
+ }
+
+ @Override
+ public ParceledListSlice<NotificationChannelGroup>
+ getNotificationChannelGroupsFromPrivilegedListener(
+ INotificationListener token, String pkg) throws RemoteException {
+ ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
+ if (!hasCompanionDevice(info)) {
+ throw new SecurityException(info + " does not have access");
+ }
+
+ List<NotificationChannelGroup> groups = new ArrayList<>();
+ int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
+ groups.addAll(mRankingHelper.getNotificationChannelGroups(pkg, uid));
+ return new ParceledListSlice<>(groups);
+ }
};
private void applyAdjustment(NotificationRecord n, Adjustment adjustment) {
@@ -2983,30 +3071,34 @@
public void removeForegroundServiceFlagFromNotification(String pkg, int notificationId,
int userId) {
checkCallerIsSystem();
- synchronized (mNotificationLock) {
- NotificationRecord r = findNotificationByListLocked(mNotificationList, pkg, null,
- notificationId, userId);
- if (r == null) {
- Log.d(TAG, "stripForegroundServiceFlag: Could not find notification with "
- + "pkg=" + pkg + " / id=" + notificationId + " / userId=" + userId);
- return;
- }
- StatusBarNotification sbn = r.sbn;
- // NoMan adds flags FLAG_NO_CLEAR and FLAG_ONGOING_EVENT when it sees
- // FLAG_FOREGROUND_SERVICE. Hence it's not enough to remove FLAG_FOREGROUND_SERVICE,
- // we have to revert to the flags we received initially *and* force remove
- // FLAG_FOREGROUND_SERVICE.
- sbn.getNotification().flags =
- (r.mOriginalFlags & ~Notification.FLAG_FOREGROUND_SERVICE);
- mRankingHelper.sort(mNotificationList);
- mListeners.notifyPostedLocked(sbn, sbn /* oldSbn */);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mGroupHelper.onNotificationPosted(sbn);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mNotificationLock) {
+ removeForegroundServiceFlagByListLocked(mEnqueuedNotifications, pkg, notificationId, userId);
+ removeForegroundServiceFlagByListLocked(mNotificationList, pkg, notificationId, userId);
}
- });
+ }
+ });
+ }
+
+ private void removeForegroundServiceFlagByListLocked(
+ ArrayList<NotificationRecord> notificationList, String pkg, int notificationId, int userId) {
+ NotificationRecord r =
+ findNotificationByListLocked(notificationList, pkg, null, notificationId, userId);
+ if (r == null) {
+ return;
}
+ StatusBarNotification sbn = r.sbn;
+ // NoMan adds flags FLAG_NO_CLEAR and FLAG_ONGOING_EVENT when it sees
+ // FLAG_FOREGROUND_SERVICE. Hence it's not enough to remove
+ // FLAG_FOREGROUND_SERVICE, we have to revert to the flags we received
+ // initially *and* force remove FLAG_FOREGROUND_SERVICE.
+ sbn.getNotification().flags =
+ (r.mOriginalFlags & ~Notification.FLAG_FOREGROUND_SERVICE);
+ mRankingHelper.sort(mNotificationList);
+ mListeners.notifyPostedLocked(sbn, sbn /* oldSbn */);
+ mGroupHelper.onNotificationPosted(sbn);
}
};
@@ -3067,9 +3159,17 @@
+ ", incomingUserId=" + incomingUserId
+ ", notificationUid=" + notificationUid
+ ", notification=" + notification;
- // STOPSHIP TODO: should throw instead of logging.
+ // STOPSHIP TODO: should throw instead of logging or toasting.
// throw new IllegalArgumentException(noChannelStr);
Log.e(TAG, noChannelStr);
+
+ final String noChannelToastStr =
+ "Developer warning for package \"" + pkg + "\"\n" +
+ "Failed to post notification on channel \"" + channelId + "\"\n" +
+ "See log for more details";
+ Toast noChannelToast =
+ Toast.makeText(getContext(), noChannelToastStr, Toast.LENGTH_LONG);
+ noChannelToast.show();
return;
}
final StatusBarNotification n = new StatusBarNotification(
@@ -4425,16 +4525,16 @@
}
}
- protected static boolean isUidSystem(int uid) {
+ protected boolean isUidSystem(int uid) {
final int appid = UserHandle.getAppId(uid);
return (appid == Process.SYSTEM_UID || appid == Process.PHONE_UID || uid == 0);
}
- private static boolean isCallerSystem() {
+ protected boolean isCallerSystem() {
return isUidSystem(Binder.getCallingUid());
}
- private static void checkCallerIsSystem() {
+ private void checkCallerIsSystem() {
if (isCallerSystem()) {
return;
}
@@ -4563,6 +4663,38 @@
channels, overridePeople, snoozeCriteria, showBadge);
}
+ boolean hasCompanionDevice(ManagedServiceInfo info) {
+ if (mCompanionManager == null) {
+ mCompanionManager = getCompanionManager();
+ }
+ // Companion mgr doesn't exist on all device types
+ if (mCompanionManager == null) {
+ return false;
+ }
+ long identity = Binder.clearCallingIdentity();
+ try {
+ List<String> associations = mCompanionManager.getAssociations(
+ info.component.getPackageName(), info.userid);
+ if (!ArrayUtils.isEmpty(associations)) {
+ return true;
+ }
+ } catch (SecurityException se) {
+ // Not a privileged listener
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Cannot reach companion device service", re);
+ } catch (Exception e) {
+ Slog.e(TAG, "Cannot verify listener " + info, e);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ return false;
+ }
+
+ protected ICompanionDeviceManager getCompanionManager() {
+ return ICompanionDeviceManager.Stub.asInterface(
+ ServiceManager.getService(Context.COMPANION_DEVICE_SERVICE));
+ }
+
private boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
if (!listener.enabledAndUserMatches(sbn.getUserId())) {
return false;
@@ -4649,10 +4781,9 @@
final StatusBarNotification sbn = r.sbn;
TrimCache trimCache = new TrimCache(sbn);
- // mServices is the list inside ManagedServices of all the assistants,
// There should be only one, but it's a list, so while we enforce
// singularity elsewhere, we keep it general here, to avoid surprises.
- for (final ManagedServiceInfo info : NotificationAssistants.this.mServices) {
+ for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
boolean sbnVisible = isVisibleToListener(sbn, info);
if (!sbnVisible) {
continue;
@@ -4688,7 +4819,7 @@
public void notifyAssistantSnoozedLocked(final StatusBarNotification sbn,
final String snoozeCriterionId) {
TrimCache trimCache = new TrimCache(sbn);
- for (final ManagedServiceInfo info : mServices) {
+ for (final ManagedServiceInfo info : getServices()) {
final StatusBarNotification sbnToPost = trimCache.ForListener(info);
mHandler.post(new Runnable() {
@Override
@@ -4709,7 +4840,7 @@
}
public boolean isEnabled() {
- return !mServices.isEmpty();
+ return !getServices().isEmpty();
}
}
@@ -4789,7 +4920,7 @@
// Lazily initialized snapshots of the notification.
TrimCache trimCache = new TrimCache(sbn);
- for (final ManagedServiceInfo info : mServices) {
+ for (final ManagedServiceInfo info : getServices()) {
boolean sbnVisible = isVisibleToListener(sbn, info);
boolean oldSbnVisible = oldSbn != null ? isVisibleToListener(oldSbn, info) : false;
// This notification hasn't been and still isn't visible -> ignore.
@@ -4828,7 +4959,7 @@
// NOTE: this copy is lightweight: it doesn't include heavyweight parts of the
// notification
final StatusBarNotification sbnLight = sbn.cloneLight();
- for (final ManagedServiceInfo info : mServices) {
+ for (final ManagedServiceInfo info : getServices()) {
if (!isVisibleToListener(sbn, info)) {
continue;
}
@@ -4846,7 +4977,7 @@
* asynchronously notify all listeners about a reordering of notifications
*/
public void notifyRankingUpdateLocked() {
- for (final ManagedServiceInfo serviceInfo : mServices) {
+ for (final ManagedServiceInfo serviceInfo : getServices()) {
if (!serviceInfo.isEnabledForCurrentProfiles()) {
continue;
}
@@ -4861,7 +4992,7 @@
}
public void notifyListenerHintsChangedLocked(final int hints) {
- for (final ManagedServiceInfo serviceInfo : mServices) {
+ for (final ManagedServiceInfo serviceInfo : getServices()) {
if (!serviceInfo.isEnabledForCurrentProfiles()) {
continue;
}
@@ -4875,7 +5006,7 @@
}
public void notifyInterruptionFilterChanged(final int interruptionFilter) {
- for (final ManagedServiceInfo serviceInfo : mServices) {
+ for (final ManagedServiceInfo serviceInfo : getServices()) {
if (!serviceInfo.isEnabledForCurrentProfiles()) {
continue;
}
@@ -4888,6 +5019,50 @@
}
}
+ protected void notifyNotificationChannelChanged(final String pkg,
+ final NotificationChannel channel, final int modificationType) {
+ if (channel == null) {
+ return;
+ }
+ for (final ManagedServiceInfo serviceInfo : getServices()) {
+ if (!serviceInfo.enabledAndUserMatches(UserHandle.getCallingUserId())) {
+ continue;
+ }
+ if (!hasCompanionDevice(serviceInfo)) {
+ continue;
+ }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ notifyNotificationChannelChanged(serviceInfo, pkg, channel,
+ modificationType);
+ }
+ });
+ }
+ }
+
+ protected void notifyNotificationChannelGroupChanged(final String pkg,
+ final NotificationChannelGroup group, final int modificationType) {
+ if (group == null) {
+ return;
+ }
+ for (final ManagedServiceInfo serviceInfo : getServices()) {
+ if (!serviceInfo.enabledAndUserMatches(UserHandle.getCallingUserId())) {
+ continue;
+ }
+ if (!hasCompanionDevice(serviceInfo)) {
+ continue;
+ }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ notifyNotificationChannelGroupChanged(serviceInfo, pkg, group,
+ modificationType);
+ }
+ });
+ }
+ }
+
private void notifyPosted(final ManagedServiceInfo info,
final StatusBarNotification sbn, NotificationRankingUpdate rankingUpdate) {
final INotificationListener listener = (INotificationListener) info.service;
@@ -4942,13 +5117,35 @@
}
}
+ void notifyNotificationChannelChanged(ManagedServiceInfo info,
+ final String pkg, final NotificationChannel channel,
+ final int modificationType) {
+ final INotificationListener listener = (INotificationListener) info.service;
+ try {
+ listener.onNotificationChannelModification(pkg, channel, modificationType);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "unable to notify listener (channel changed): " + listener, ex);
+ }
+ }
+
+ private void notifyNotificationChannelGroupChanged(ManagedServiceInfo info,
+ final String pkg, final NotificationChannelGroup group,
+ final int modificationType) {
+ final INotificationListener listener = (INotificationListener) info.service;
+ try {
+ listener.onNotificationChannelGroupModification(pkg, group, modificationType);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "unable to notify listener (channel group changed): " + listener, ex);
+ }
+ }
+
public boolean isListenerPackage(String packageName) {
if (packageName == null) {
return false;
}
// TODO: clean up locking object later
synchronized (mNotificationLock) {
- for (final ManagedServiceInfo serviceInfo : mServices) {
+ for (final ManagedServiceInfo serviceInfo : getServices()) {
if (packageName.equals(serviceInfo.component.getPackageName())) {
return true;
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index b043230..b7d3173 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -376,7 +376,20 @@
pw.println(prefix + "fullscreenIntent=" + notification.fullScreenIntent);
pw.println(prefix + "contentIntent=" + notification.contentIntent);
pw.println(prefix + "deleteIntent=" + notification.deleteIntent);
- pw.println(prefix + "tickerText=" + notification.tickerText);
+
+ pw.print(prefix + "tickerText=");
+ if (!TextUtils.isEmpty(notification.tickerText)) {
+ final String ticker = notification.tickerText.toString();
+ if (redact) {
+ // if the string is long enough, we allow ourselves a few bytes for debugging
+ pw.print(ticker.length() > 16 ? ticker.substring(0,8) : "");
+ pw.println("...");
+ } else {
+ pw.println(ticker);
+ }
+ } else {
+ pw.println("null");
+ }
pw.println(prefix + "contentView=" + notification.contentView);
pw.println(prefix + String.format("color=0x%08x", notification.color));
pw.println(prefix + "timeout=" + TimeUtils.formatForLogging(notification.getTimeout()));
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index b789d5c..221b2bb 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -232,7 +232,9 @@
private Record getRecord(String pkg, int uid) {
final String key = recordKey(pkg, uid);
- return mRecords.get(key);
+ synchronized (mRecords) {
+ return mRecords.get(key);
+ }
}
private Record getOrCreateRecord(String pkg, int uid) {
@@ -243,29 +245,32 @@
private Record getOrCreateRecord(String pkg, int uid, int importance, int priority,
int visibility, boolean showBadge) {
final String key = recordKey(pkg, uid);
- Record r = (uid == Record.UNKNOWN_UID) ? mRestoredWithoutUids.get(pkg) : mRecords.get(key);
- if (r == null) {
- r = new Record();
- r.pkg = pkg;
- r.uid = uid;
- r.importance = importance;
- r.priority = priority;
- r.visibility = visibility;
- r.showBadge = showBadge;
+ synchronized (mRecords) {
+ Record r = (uid == Record.UNKNOWN_UID) ? mRestoredWithoutUids.get(pkg) : mRecords.get(
+ key);
+ if (r == null) {
+ r = new Record();
+ r.pkg = pkg;
+ r.uid = uid;
+ r.importance = importance;
+ r.priority = priority;
+ r.visibility = visibility;
+ r.showBadge = showBadge;
- try {
- createDefaultChannelIfNeeded(r);
- } catch (NameNotFoundException e) {
- Slog.e(TAG, "createDefaultChannelIfNeeded - Exception: " + e);
- }
+ try {
+ createDefaultChannelIfNeeded(r);
+ } catch (NameNotFoundException e) {
+ Slog.e(TAG, "createDefaultChannelIfNeeded - Exception: " + e);
+ }
- if (r.uid == Record.UNKNOWN_UID) {
- mRestoredWithoutUids.put(pkg, r);
- } else {
- mRecords.put(key, r);
+ if (r.uid == Record.UNKNOWN_UID) {
+ mRestoredWithoutUids.put(pkg, r);
+ } else {
+ mRecords.put(key, r);
+ }
}
+ return r;
}
- return r;
}
private boolean shouldHaveDefaultChannel(Record r) throws NameNotFoundException {
@@ -346,46 +351,48 @@
out.startTag(null, TAG_RANKING);
out.attribute(null, ATT_VERSION, Integer.toString(XML_VERSION));
- final int N = mRecords.size();
- for (int i = 0; i < N; i++) {
- final Record r = mRecords.valueAt(i);
- //TODO: http://b/22388012
- if (forBackup && UserHandle.getUserId(r.uid) != UserHandle.USER_SYSTEM) {
- continue;
- }
- final boolean hasNonDefaultSettings = r.importance != DEFAULT_IMPORTANCE
- || r.priority != DEFAULT_PRIORITY || r.visibility != DEFAULT_VISIBILITY
- || r.showBadge != DEFAULT_SHOW_BADGE || r.channels.size() > 0
- || r.groups.size() > 0;
- if (hasNonDefaultSettings) {
- out.startTag(null, TAG_PACKAGE);
- out.attribute(null, ATT_NAME, r.pkg);
- if (r.importance != DEFAULT_IMPORTANCE) {
- out.attribute(null, ATT_IMPORTANCE, Integer.toString(r.importance));
+ synchronized (mRecords) {
+ final int N = mRecords.size();
+ for (int i = 0; i < N; i++) {
+ final Record r = mRecords.valueAt(i);
+ //TODO: http://b/22388012
+ if (forBackup && UserHandle.getUserId(r.uid) != UserHandle.USER_SYSTEM) {
+ continue;
}
- if (r.priority != DEFAULT_PRIORITY) {
- out.attribute(null, ATT_PRIORITY, Integer.toString(r.priority));
- }
- if (r.visibility != DEFAULT_VISIBILITY) {
- out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility));
- }
- out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(r.showBadge));
-
- if (!forBackup) {
- out.attribute(null, ATT_UID, Integer.toString(r.uid));
- }
-
- for (NotificationChannelGroup group : r.groups.values()) {
- group.writeXml(out);
- }
-
- for (NotificationChannel channel : r.channels.values()) {
- if (!forBackup || (forBackup && !channel.isDeleted())) {
- channel.writeXml(out);
+ final boolean hasNonDefaultSettings = r.importance != DEFAULT_IMPORTANCE
+ || r.priority != DEFAULT_PRIORITY || r.visibility != DEFAULT_VISIBILITY
+ || r.showBadge != DEFAULT_SHOW_BADGE || r.channels.size() > 0
+ || r.groups.size() > 0;
+ if (hasNonDefaultSettings) {
+ out.startTag(null, TAG_PACKAGE);
+ out.attribute(null, ATT_NAME, r.pkg);
+ if (r.importance != DEFAULT_IMPORTANCE) {
+ out.attribute(null, ATT_IMPORTANCE, Integer.toString(r.importance));
}
- }
+ if (r.priority != DEFAULT_PRIORITY) {
+ out.attribute(null, ATT_PRIORITY, Integer.toString(r.priority));
+ }
+ if (r.visibility != DEFAULT_VISIBILITY) {
+ out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility));
+ }
+ out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(r.showBadge));
- out.endTag(null, TAG_PACKAGE);
+ if (!forBackup) {
+ out.attribute(null, ATT_UID, Integer.toString(r.uid));
+ }
+
+ for (NotificationChannelGroup group : r.groups.values()) {
+ group.writeXml(out);
+ }
+
+ for (NotificationChannel channel : r.channels.values()) {
+ if (!forBackup || (forBackup && !channel.isDeleted())) {
+ channel.writeXml(out);
+ }
+ }
+
+ out.endTag(null, TAG_PACKAGE);
+ }
}
}
out.endTag(null, TAG_RANKING);
@@ -570,10 +577,6 @@
if (!r.showBadge) {
channel.setShowBadge(false);
}
- if (channel.getSound() == null) {
- channel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
- Notification.AUDIO_ATTRIBUTES_DEFAULT);
- }
r.channels.put(channel.getId(), channel);
MetricsLogger.action(getChannelLog(channel, pkg).setType(
MetricsProto.MetricsEvent.TYPE_OPEN));
@@ -715,12 +718,12 @@
return new ParceledListSlice<>(new ArrayList<>(groups.values()));
}
- public List<String> deleteNotificationChannelGroup(String pkg, int uid,
+ public List<NotificationChannel> deleteNotificationChannelGroup(String pkg, int uid,
String groupId) {
- List<String> deletedChannelIds = new ArrayList<>();
+ List<NotificationChannel> deletedChannels = new ArrayList<>();
Record r = getRecord(pkg, uid);
if (r == null || TextUtils.isEmpty(groupId)) {
- return deletedChannelIds;
+ return deletedChannels;
}
r.groups.remove(groupId);
@@ -730,11 +733,11 @@
final NotificationChannel nc = r.channels.valueAt(i);
if (groupId.equals(nc.getGroup())) {
nc.setDeleted(true);
- deletedChannelIds.add(nc.getId());
+ deletedChannels.add(nc);
}
}
updateConfig();
- return deletedChannelIds;
+ return deletedChannels;
}
@Override
@@ -818,7 +821,9 @@
pw.println("per-package config:");
}
pw.println("Records:");
- dumpRecords(pw, prefix, filter, mRecords);
+ synchronized (mRecords) {
+ dumpRecords(pw, prefix, filter, mRecords);
+ }
pw.println("Restored without uid:");
dumpRecords(pw, prefix, filter, mRestoredWithoutUids);
}
@@ -874,36 +879,38 @@
} catch (JSONException e) {
// pass
}
- final int N = mRecords.size();
- for (int i = 0; i < N; i++) {
- final Record r = mRecords.valueAt(i);
- if (filter == null || filter.matches(r.pkg)) {
- JSONObject record = new JSONObject();
- try {
- record.put("userId", UserHandle.getUserId(r.uid));
- record.put("packageName", r.pkg);
- if (r.importance != DEFAULT_IMPORTANCE) {
- record.put("importance", Ranking.importanceToString(r.importance));
+ synchronized (mRecords) {
+ final int N = mRecords.size();
+ for (int i = 0; i < N; i++) {
+ final Record r = mRecords.valueAt(i);
+ if (filter == null || filter.matches(r.pkg)) {
+ JSONObject record = new JSONObject();
+ try {
+ record.put("userId", UserHandle.getUserId(r.uid));
+ record.put("packageName", r.pkg);
+ if (r.importance != DEFAULT_IMPORTANCE) {
+ record.put("importance", Ranking.importanceToString(r.importance));
+ }
+ if (r.priority != DEFAULT_PRIORITY) {
+ record.put("priority", Notification.priorityToString(r.priority));
+ }
+ if (r.visibility != DEFAULT_VISIBILITY) {
+ record.put("visibility", Notification.visibilityToString(r.visibility));
+ }
+ if (r.showBadge != DEFAULT_SHOW_BADGE) {
+ record.put("showBadge", Boolean.valueOf(r.showBadge));
+ }
+ for (NotificationChannel channel : r.channels.values()) {
+ record.put("channel", channel.toJson());
+ }
+ for (NotificationChannelGroup group : r.groups.values()) {
+ record.put("group", group.toJson());
+ }
+ } catch (JSONException e) {
+ // pass
}
- if (r.priority != DEFAULT_PRIORITY) {
- record.put("priority", Notification.priorityToString(r.priority));
- }
- if (r.visibility != DEFAULT_VISIBILITY) {
- record.put("visibility", Notification.visibilityToString(r.visibility));
- }
- if (r.showBadge != DEFAULT_SHOW_BADGE) {
- record.put("showBadge", Boolean.valueOf(r.showBadge));
- }
- for (NotificationChannel channel : r.channels.values()) {
- record.put("channel", channel.toJson());
- }
- for (NotificationChannelGroup group : r.groups.values()) {
- record.put("group", group.toJson());
- }
- } catch (JSONException e) {
- // pass
+ records.put(record);
}
- records.put(record);
}
}
try {
@@ -944,15 +951,18 @@
}
public Map<Integer, String> getPackageBans() {
- final int N = mRecords.size();
- ArrayMap<Integer, String> packageBans = new ArrayMap<>(N);
- for (int i = 0; i < N; i++) {
- final Record r = mRecords.valueAt(i);
- if (r.importance == NotificationManager.IMPORTANCE_NONE) {
- packageBans.put(r.uid, r.pkg);
+ synchronized (mRecords) {
+ final int N = mRecords.size();
+ ArrayMap<Integer, String> packageBans = new ArrayMap<>(N);
+ for (int i = 0; i < N; i++) {
+ final Record r = mRecords.valueAt(i);
+ if (r.importance == NotificationManager.IMPORTANCE_NONE) {
+ packageBans.put(r.uid, r.pkg);
+ }
}
+
+ return packageBans;
}
- return packageBans;
}
/**
@@ -985,15 +995,17 @@
private Map<String, Integer> getPackageChannels() {
ArrayMap<String, Integer> packageChannels = new ArrayMap<>();
- for (int i = 0; i < mRecords.size(); i++) {
- final Record r = mRecords.valueAt(i);
- int channelCount = 0;
- for (int j = 0; j < r.channels.size();j++) {
- if (!r.channels.valueAt(j).isDeleted()) {
- channelCount++;
+ synchronized (mRecords) {
+ for (int i = 0; i < mRecords.size(); i++) {
+ final Record r = mRecords.valueAt(i);
+ int channelCount = 0;
+ for (int j = 0; j < r.channels.size(); j++) {
+ if (!r.channels.valueAt(j).isDeleted()) {
+ channelCount++;
+ }
}
+ packageChannels.put(r.pkg, channelCount);
}
- packageChannels.put(r.pkg, channelCount);
}
return packageChannels;
}
@@ -1010,7 +1022,9 @@
for (int i = 0; i < size; i++) {
final String pkg = pkgList[i];
final int uid = uidList[i];
- mRecords.remove(recordKey(pkg, uid));
+ synchronized (mRecords) {
+ mRecords.remove(recordKey(pkg, uid));
+ }
mRestoredWithoutUids.remove(pkg);
updated = true;
}
@@ -1022,7 +1036,9 @@
try {
r.uid = mPm.getPackageUidAsUser(r.pkg, changeUserId);
mRestoredWithoutUids.remove(pkg);
- mRecords.put(recordKey(r.pkg, r.uid), r);
+ synchronized (mRecords) {
+ mRecords.put(recordKey(r.pkg, r.uid), r);
+ }
updated = true;
} catch (NameNotFoundException e) {
// noop
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 2026c1b..0e1f485 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -71,6 +71,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -193,13 +194,10 @@
* </ul>
*/
public final class OverlayManagerService extends SystemService {
-
static final String TAG = "OverlayManager";
static final boolean DEBUG = false;
- static final String PERMISSION_DENIED = "Operation not permitted for user shell";
-
/**
* The system property that specifies the default overlays to apply.
* This is a semicolon separated list of package names.
@@ -234,7 +232,7 @@
IdmapManager im = new IdmapManager(installer);
mSettings = new OverlayManagerSettings();
mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings,
- getDefaultOverlayPackages());
+ getDefaultOverlayPackages(), new OverlayChangeListener());
mInitCompleteSignal = SystemServerInitThreadPool.get().submit(() -> {
final IntentFilter packageFilter = new IntentFilter();
packageFilter.addAction(ACTION_PACKAGE_ADDED);
@@ -251,9 +249,6 @@
restoreSettings();
onSwitchUser(UserHandle.USER_SYSTEM);
- schedulePersistSettings();
-
- mSettings.addChangeListener(new OverlayChangeListener());
publishBinderService(Context.OVERLAY_SERVICE, mService);
publishLocalService(OverlayManagerService.class, this);
@@ -281,8 +276,9 @@
final List<String> targets;
synchronized (mLock) {
targets = mImpl.onSwitchUser(newUserId);
+ updateAssetsLocked(newUserId, targets);
}
- updateAssets(newUserId, targets);
+ schedulePersistSettings();
}
private static Set<String> getDefaultOverlayPackages() {
@@ -348,7 +344,8 @@
@NonNull final int[] userIds) {
for (final int userId : userIds) {
synchronized (mLock) {
- final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId, false);
+ final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
+ false);
if (pi != null) {
mPackageManager.cachePackageInfo(packageName, userId, pi);
if (!isOverlayPackage(pi)) {
@@ -365,7 +362,8 @@
@NonNull final int[] userIds) {
for (int userId : userIds) {
synchronized (mLock) {
- final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId, false);
+ final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
+ false);
if (pi != null) {
mPackageManager.cachePackageInfo(packageName, userId, pi);
if (!isOverlayPackage(pi)) {
@@ -397,7 +395,8 @@
@NonNull final int[] userIds) {
for (int userId : userIds) {
synchronized (mLock) {
- final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId, false);
+ final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId,
+ false);
if (pi != null) {
mPackageManager.cachePackageInfo(packageName, userId, pi);
if (!isOverlayPackage(pi)) {
@@ -449,8 +448,7 @@
private final IBinder mService = new IOverlayManager.Stub() {
@Override
- public Map<String, List<OverlayInfo>> getAllOverlays(int userId)
- throws RemoteException {
+ public Map<String, List<OverlayInfo>> getAllOverlays(int userId) throws RemoteException {
userId = handleIncomingUser(userId, "getAllOverlays");
synchronized (mLock) {
@@ -508,14 +506,14 @@
int userId) throws RemoteException {
enforceChangeOverlayPackagesPermission("setEnabled");
userId = handleIncomingUser(userId, "setEnabled");
- if (packageName == null) {
+ if (packageName == null || !enable) {
return false;
}
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- return mImpl.setEnabledExclusive(packageName, enable, userId);
+ return mImpl.setEnabledExclusive(packageName, userId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -643,68 +641,24 @@
return pi != null && pi.overlayTarget != null;
}
- private final class OverlayChangeListener implements OverlayManagerSettings.ChangeListener {
+ private final class OverlayChangeListener
+ implements OverlayManagerServiceImpl.OverlayChangeListener {
@Override
- public void onSettingsChanged() {
+ public void onOverlaysChanged(@NonNull final String targetPackageName, final int userId) {
schedulePersistSettings();
- }
-
- @Override
- public void onOverlayAdded(@NonNull final OverlayInfo oi) {
- scheduleBroadcast(Intent.ACTION_OVERLAY_ADDED, oi, oi.isEnabled());
- }
-
- @Override
- public void onOverlayRemoved(@NonNull final OverlayInfo oi) {
- scheduleBroadcast(Intent.ACTION_OVERLAY_REMOVED, oi, oi.isEnabled());
- }
-
- @Override
- public void onOverlayChanged(@NonNull final OverlayInfo oi,
- @NonNull final OverlayInfo oldOi) {
- scheduleBroadcast(Intent.ACTION_OVERLAY_CHANGED, oi, oi.isEnabled() != oldOi.isEnabled());
- }
-
- @Override
- public void onOverlayPriorityChanged(@NonNull final OverlayInfo oi) {
- scheduleBroadcast(Intent.ACTION_OVERLAY_PRIORITY_CHANGED, oi, oi.isEnabled());
- }
-
- private void scheduleBroadcast(@NonNull final String action, @NonNull final OverlayInfo oi,
- final boolean doUpdate) {
- FgThread.getHandler().post(new BroadcastRunnable(action, oi, doUpdate));
- }
-
- private final class BroadcastRunnable implements Runnable {
- private final String mAction;
- private final OverlayInfo mOverlayInfo;
- private final boolean mDoUpdate;
-
- BroadcastRunnable(@NonNull final String action, @NonNull final OverlayInfo oi,
- final boolean doUpdate) {
- mAction = action;
- mOverlayInfo = oi;
- mDoUpdate = doUpdate;
- }
-
- @Override
- public void run() {
- if (mDoUpdate) {
- updateAssets(mOverlayInfo.userId, mOverlayInfo.targetPackageName);
+ FgThread.getHandler().post(() -> {
+ synchronized (mLock) {
+ updateAssetsLocked(userId, targetPackageName);
}
- sendBroadcast(mAction, mOverlayInfo.targetPackageName, mOverlayInfo.packageName,
- mOverlayInfo.userId);
- }
- private void sendBroadcast(@NonNull final String action,
- @NonNull final String targetPackageName, @NonNull final String packageName,
- final int userId) {
- final Intent intent = new Intent(action, Uri.fromParts("package",
- String.format("%s/%s", targetPackageName, packageName), null));
+ final Intent intent = new Intent(Intent.ACTION_OVERLAY_CHANGED,
+ Uri.fromParts("package", targetPackageName, null));
intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+
if (DEBUG) {
- Slog.d(TAG, String.format("send broadcast %s", intent));
+ Slog.d(TAG, "send broadcast " + intent);
}
+
try {
ActivityManager.getService().broadcastIntent(null, intent, null, null, 0,
null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false,
@@ -712,18 +666,20 @@
} catch (RemoteException e) {
// Intentionally left empty.
}
- }
-
+ });
}
}
- private void updateAssets(final int userId, final String targetPackageName) {
+ private void updateAssetsLocked(final int userId, final String targetPackageName) {
final List<String> list = new ArrayList<>();
list.add(targetPackageName);
- updateAssets(userId, list);
+ updateAssetsLocked(userId, list);
}
- private void updateAssets(final int userId, List<String> targetPackageNames) {
+ private void updateAssetsLocked(final int userId, List<String> targetPackageNames) {
+ if (DEBUG) {
+ Slog.d(TAG, "Updating overlay assets");
+ }
final PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
final boolean updateFrameworkRes = targetPackageNames.contains("android");
if (updateFrameworkRes) {
@@ -743,6 +699,12 @@
final int N = targetPackageNames.size();
for (int i = 0; i < N; i++) {
final String targetPackageName = targetPackageNames.get(i);
+ if (DEBUG) {
+ Slog.d(TAG, "-> Updating overlay: target=" + targetPackageName + " overlays=["
+ + TextUtils.join(",", pendingChanges.get(targetPackageName))
+ + "] userId=" + userId);
+ }
+
if (!pm.setEnabledOverlayPackages(
userId, targetPackageName, pendingChanges.get(targetPackageName))) {
Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d",
@@ -762,20 +724,20 @@
if (mPersistSettingsScheduled.getAndSet(true)) {
return;
}
- IoThread.getHandler().post(new Runnable() {
- @Override
- public void run() {
- mPersistSettingsScheduled.set(false);
- synchronized (mLock) {
- FileOutputStream stream = null;
- try {
- stream = mSettingsFile.startWrite();
- mSettings.persist(stream);
- mSettingsFile.finishWrite(stream);
- } catch (IOException | XmlPullParserException e) {
- mSettingsFile.failWrite(stream);
- Slog.e(TAG, "failed to persist overlay state", e);
- }
+ IoThread.getHandler().post(() -> {
+ mPersistSettingsScheduled.set(false);
+ if (DEBUG) {
+ Slog.d(TAG, "Writing overlay settings");
+ }
+ synchronized (mLock) {
+ FileOutputStream stream = null;
+ try {
+ stream = mSettingsFile.startWrite();
+ mSettings.persist(stream);
+ mSettingsFile.finishWrite(stream);
+ } catch (IOException | XmlPullParserException e) {
+ mSettingsFile.failWrite(stream);
+ Slog.e(TAG, "failed to persist overlay state", e);
}
}
});
@@ -793,12 +755,17 @@
// restarted before we received USER_REMOVED. Remove data for
// users that will not exist after the system is ready.
- final List<UserInfo> deadUsers = getDeadUsers();
- final int N = deadUsers.size();
- for (int i = 0; i < N; i++) {
- final UserInfo deadUser = deadUsers.get(i);
- final int userId = deadUser.getUserHandle().getIdentifier();
- mSettings.removeUser(userId);
+ final List<UserInfo> liveUsers = mUserManager.getUsers(true /*excludeDying*/);
+ final int[] liveUserIds = new int[liveUsers.size()];
+ for (int i = 0; i < liveUsers.size(); i++) {
+ liveUserIds[i] = liveUsers.get(i).getUserHandle().getIdentifier();
+ }
+ Arrays.sort(liveUserIds);
+
+ for (int userId : mSettings.getUsers()) {
+ if (Arrays.binarySearch(liveUserIds, userId) < 0) {
+ mSettings.removeUser(userId);
+ }
}
} catch (IOException | XmlPullParserException e) {
Slog.e(TAG, "failed to restore overlay state", e);
@@ -806,13 +773,6 @@
}
}
- private List<UserInfo> getDeadUsers() {
- final List<UserInfo> users = mUserManager.getUsers(false);
- final List<UserInfo> onlyLiveUsers = mUserManager.getUsers(true);
- users.removeAll(onlyLiveUsers);
- return users;
- }
-
private static final class PackageManagerHelper implements
OverlayManagerServiceImpl.PackageManagerHelper {
@@ -862,7 +822,8 @@
// The package manager does not support different versions of packages
// to be installed for different users: ignore userId for now.
try {
- return mPackageManager.checkSignatures(packageName1, packageName2) == SIGNATURE_MATCH;
+ return mPackageManager.checkSignatures(
+ packageName1, packageName2) == SIGNATURE_MATCH;
} catch (RemoteException e) {
// Intentionally left blank
}
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 3705946..5196c66 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -54,15 +54,18 @@
private final IdmapManager mIdmapManager;
private final OverlayManagerSettings mSettings;
private final Set<String> mDefaultOverlays;
+ private final OverlayChangeListener mListener;
OverlayManagerServiceImpl(@NonNull final PackageManagerHelper packageManager,
@NonNull final IdmapManager idmapManager,
@NonNull final OverlayManagerSettings settings,
- @NonNull final Set<String> defaultOverlays) {
+ @NonNull final Set<String> defaultOverlays,
+ @NonNull final OverlayChangeListener listener) {
mPackageManager = packageManager;
mIdmapManager = idmapManager;
mSettings = settings;
mDefaultOverlays = defaultOverlays;
+ mListener = listener;
}
/*
@@ -98,13 +101,18 @@
// Update the overlay if it didn't exist or had the wrong target package.
mSettings.init(overlayPackage.packageName, newUserId,
overlayPackage.overlayTarget,
- overlayPackage.applicationInfo.getBaseCodePath());
+ overlayPackage.applicationInfo.getBaseCodePath(),
+ overlayPackage.isStaticOverlay, overlayPackage.overlayPriority);
if (oi == null) {
// This overlay does not exist in our settings.
if (overlayPackage.isStaticOverlay ||
mDefaultOverlays.contains(overlayPackage.packageName)) {
// Enable this overlay by default.
+ if (DEBUG) {
+ Slog.d(TAG, "Enabling overlay " + overlayPackage.packageName
+ + " for user " + newUserId + " by default");
+ }
mSettings.setEnabled(overlayPackage.packageName, newUserId, true);
}
} else {
@@ -145,7 +153,6 @@
iter.remove();
}
}
-
return new ArrayList<>(packagesToUpdateAssets);
}
@@ -199,25 +206,30 @@
updateAllOverlaysForTarget(packageName, userId, null);
}
- private void updateAllOverlaysForTarget(@NonNull final String packageName, final int userId,
+ /**
+ * Returns true if the settings were modified for this target.
+ */
+ private boolean updateAllOverlaysForTarget(@NonNull final String packageName, final int userId,
@Nullable final PackageInfo targetPackage) {
+ boolean modified = false;
final List<OverlayInfo> ois = mSettings.getOverlaysForTarget(packageName, userId);
final int N = ois.size();
for (int i = 0; i < N; i++) {
final OverlayInfo oi = ois.get(i);
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(oi.packageName, userId);
if (overlayPackage == null) {
- mSettings.remove(oi.packageName, oi.userId);
+ modified |= mSettings.remove(oi.packageName, oi.userId);
removeIdmapIfPossible(oi);
} else {
try {
- updateState(targetPackage, overlayPackage, userId);
+ modified |= updateState(targetPackage, overlayPackage, userId);
} catch (OverlayManagerSettings.BadKeyException e) {
Slog.e(TAG, "failed to update settings", e);
- mSettings.remove(oi.packageName, userId);
+ modified |= mSettings.remove(oi.packageName, userId);
}
}
}
+ return modified;
}
void onOverlayPackageAdded(@NonNull final String packageName, final int userId) {
@@ -236,9 +248,12 @@
mPackageManager.getPackageInfo(overlayPackage.overlayTarget, userId);
mSettings.init(packageName, userId, overlayPackage.overlayTarget,
- overlayPackage.applicationInfo.getBaseCodePath());
+ overlayPackage.applicationInfo.getBaseCodePath(), overlayPackage.isStaticOverlay,
+ overlayPackage.overlayPriority);
try {
- updateState(targetPackage, overlayPackage, userId);
+ if (updateState(targetPackage, overlayPackage, userId)) {
+ mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
+ }
} catch (OverlayManagerSettings.BadKeyException e) {
Slog.e(TAG, "failed to update settings", e);
mSettings.remove(packageName, userId);
@@ -289,8 +304,9 @@
if (overlayPackage == null) {
return false;
}
- // Static overlay is always being enabled.
- if (!enable && overlayPackage.isStaticOverlay) {
+
+ // Ignore static overlays.
+ if (overlayPackage.isStaticOverlay) {
return false;
}
@@ -298,19 +314,21 @@
final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
final PackageInfo targetPackage =
mPackageManager.getPackageInfo(oi.targetPackageName, userId);
- mSettings.setEnabled(packageName, userId, enable);
- updateState(targetPackage, overlayPackage, userId);
+ boolean modified = mSettings.setEnabled(packageName, userId, enable);
+ modified |= updateState(targetPackage, overlayPackage, userId);
+
+ if (modified) {
+ mListener.onOverlaysChanged(oi.targetPackageName, userId);
+ }
return true;
} catch (OverlayManagerSettings.BadKeyException e) {
return false;
}
}
- boolean setEnabledExclusive(@NonNull final String packageName, final boolean enable,
- final int userId) {
+ boolean setEnabledExclusive(@NonNull final String packageName, final int userId) {
if (DEBUG) {
- Slog.d(TAG, String.format("setEnabled packageName=%s enable=%s userId=%d",
- packageName, enable, userId));
+ Slog.d(TAG, String.format("setEnabledExclusive packageName=%s userId=%d", packageName, userId));
}
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
@@ -320,23 +338,48 @@
try {
final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
+ final PackageInfo targetPackage =
+ mPackageManager.getPackageInfo(oi.targetPackageName, userId);
+
List<OverlayInfo> allOverlays = getOverlayInfosForTarget(oi.targetPackageName, userId);
+ boolean modified = false;
+
// Disable all other overlays.
allOverlays.remove(oi);
for (int i = 0; i < allOverlays.size(); i++) {
- // TODO: Optimize this to only send updates after all changes.
- setEnabled(allOverlays.get(i).packageName, false, userId);
+ final String disabledOverlayPackageName = allOverlays.get(i).packageName;
+ final PackageInfo disabledOverlayPackageInfo = mPackageManager.getPackageInfo(
+ disabledOverlayPackageName, userId);
+ if (disabledOverlayPackageInfo == null) {
+ modified |= mSettings.remove(disabledOverlayPackageName, userId);
+ continue;
+ }
+
+ if (disabledOverlayPackageInfo.isStaticOverlay) {
+ // Don't touch static overlays.
+ continue;
+ }
+
+ // Disable the overlay.
+ modified |= mSettings.setEnabled(disabledOverlayPackageName, userId, false);
+ modified |= updateState(targetPackage, disabledOverlayPackageInfo, userId);
}
- setEnabled(packageName, enable, userId);
+ // Enable the selected overlay.
+ modified |= mSettings.setEnabled(packageName, userId, true);
+ modified |= updateState(targetPackage, overlayPackage, userId);
+
+ if (modified) {
+ mListener.onOverlaysChanged(oi.targetPackageName, userId);
+ }
return true;
} catch (OverlayManagerSettings.BadKeyException e) {
return false;
}
}
- boolean isPackageUpdatableOverlay(@NonNull final String packageName, final int userId) {
+ private boolean isPackageUpdatableOverlay(@NonNull final String packageName, final int userId) {
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null || overlayPackage.isStaticOverlay) {
return false;
@@ -346,18 +389,64 @@
boolean setPriority(@NonNull final String packageName,
@NonNull final String newParentPackageName, final int userId) {
- return isPackageUpdatableOverlay(packageName, userId) &&
- mSettings.setPriority(packageName, newParentPackageName, userId);
+ if (DEBUG) {
+ Slog.d(TAG, "setPriority packageName=" + packageName + " newParentPackageName="
+ + newParentPackageName + " userId=" + userId);
+ }
+
+ if (!isPackageUpdatableOverlay(packageName, userId)) {
+ return false;
+ }
+
+ final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
+ if (overlayPackage == null) {
+ return false;
+ }
+
+ if (mSettings.setPriority(packageName, newParentPackageName, userId)) {
+ mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
+ }
+ return true;
}
boolean setHighestPriority(@NonNull final String packageName, final int userId) {
- return isPackageUpdatableOverlay(packageName, userId) &&
- mSettings.setHighestPriority(packageName, userId);
+ if (DEBUG) {
+ Slog.d(TAG, "setHighestPriority packageName=" + packageName + " userId=" + userId);
+ }
+
+ if (!isPackageUpdatableOverlay(packageName, userId)) {
+ return false;
+ }
+
+ final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
+ if (overlayPackage == null) {
+ return false;
+ }
+
+ if (mSettings.setHighestPriority(packageName, userId)) {
+ mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
+ }
+ return true;
}
boolean setLowestPriority(@NonNull final String packageName, final int userId) {
- return isPackageUpdatableOverlay(packageName, userId) &&
- mSettings.setLowestPriority(packageName, userId);
+ if (DEBUG) {
+ Slog.d(TAG, "setLowestPriority packageName=" + packageName + " userId=" + userId);
+ }
+
+ if (!isPackageUpdatableOverlay(packageName, userId)) {
+ return false;
+ }
+
+ final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
+ if (overlayPackage == null) {
+ return false;
+ }
+
+ if (mSettings.setLowestPriority(packageName, userId)) {
+ mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
+ }
+ return true;
}
void onDump(@NonNull final PrintWriter pw) {
@@ -379,16 +468,19 @@
return paths;
}
- private void updateState(@Nullable final PackageInfo targetPackage,
+ /**
+ * Returns true if the settings/state was modified, false otherwise.
+ */
+ private boolean updateState(@Nullable final PackageInfo targetPackage,
@NonNull final PackageInfo overlayPackage, final int userId)
- throws OverlayManagerSettings.BadKeyException {
+ throws OverlayManagerSettings.BadKeyException {
// Static RROs targeting to "android", ie framework-res.apk, are handled by native layers.
if (targetPackage != null &&
!("android".equals(targetPackage.packageName) && overlayPackage.isStaticOverlay)) {
mIdmapManager.createIdmap(targetPackage, overlayPackage, userId);
}
- mSettings.setBaseCodePath(overlayPackage.packageName, userId,
+ boolean modified = mSettings.setBaseCodePath(overlayPackage.packageName, userId,
overlayPackage.applicationInfo.getBaseCodePath());
final int currentState = mSettings.getState(overlayPackage.packageName, userId);
@@ -400,8 +492,9 @@
OverlayInfo.stateToString(currentState),
OverlayInfo.stateToString(newState)));
}
- mSettings.setState(overlayPackage.packageName, userId, newState);
+ modified |= mSettings.setState(overlayPackage.packageName, userId, newState);
}
+ return modified;
}
private int calculateNewState(@Nullable final PackageInfo targetPackage,
@@ -441,10 +534,8 @@
if (!mIdmapManager.idmapExists(oi)) {
return;
}
- final List<Integer> userIds = mSettings.getUsers();
- final int N = userIds.size();
- for (int i = 0; i < N; i++) {
- final int userId = userIds.get(i);
+ final int[] userIds = mSettings.getUsers();
+ for (int userId : userIds) {
try {
final OverlayInfo tmp = mSettings.getOverlayInfo(oi.packageName, userId);
if (tmp != null && tmp.isEnabled()) {
@@ -458,6 +549,10 @@
mIdmapManager.removeIdmap(oi, oi.userId);
}
+ interface OverlayChangeListener {
+ void onOverlaysChanged(@NonNull String targetPackage, int userId);
+ }
+
interface PackageManagerHelper {
PackageInfo getPackageInfo(@NonNull String packageName, int userId);
boolean signaturesMatching(@NonNull String packageName1, @NonNull String packageName2,
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index 2262a2e..2f83793 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -16,8 +16,6 @@
package com.android.server.om;
-import static android.content.om.OverlayInfo.STATE_UNKNOWN;
-
import static com.android.server.om.OverlayManagerService.DEBUG;
import static com.android.server.om.OverlayManagerService.TAG;
@@ -41,252 +39,230 @@
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
import java.util.List;
-import java.util.ListIterator;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* Data structure representing the current state of all overlay packages in the
* system.
*
- * Modifications to the data are exposed through the ChangeListener interface.
+ * Modifications to the data are signaled by returning true from any state mutating method.
*
- * @see ChangeListener
* @see OverlayManagerService
*/
final class OverlayManagerSettings {
- private final List<ChangeListener> mListeners = new ArrayList<>();
-
+ /**
+ * All overlay data for all users and target packages is stored in this list.
+ * This keeps memory down, while increasing the cost of running queries or mutating the
+ * data. This is ok, since changing of overlays is very rare and has larger costs associated
+ * with it.
+ *
+ * The order of the items in the list is important, those with a lower index having a lower
+ * priority.
+ */
private final ArrayList<SettingsItem> mItems = new ArrayList<>();
void init(@NonNull final String packageName, final int userId,
- @NonNull final String targetPackageName, @NonNull final String baseCodePath) {
+ @NonNull final String targetPackageName, @NonNull final String baseCodePath,
+ boolean isStatic, int priority) {
remove(packageName, userId);
final SettingsItem item =
- new SettingsItem(packageName, userId, targetPackageName, baseCodePath);
- mItems.add(item);
- }
-
- void remove(@NonNull final String packageName, final int userId) {
- final SettingsItem item = select(packageName, userId);
- if (item == null) {
- return;
- }
- final OverlayInfo oi = item.getOverlayInfo();
- mItems.remove(item);
- if (oi != null) {
- notifyOverlayRemoved(oi);
+ new SettingsItem(packageName, userId, targetPackageName, baseCodePath,
+ isStatic, priority);
+ if (isStatic) {
+ int i;
+ for (i = mItems.size() - 1; i >= 0; i--) {
+ SettingsItem parentItem = mItems.get(i);
+ if (parentItem.mIsStatic && parentItem.mPriority <= priority) {
+ break;
+ }
+ }
+ int pos = i + 1;
+ if (pos == mItems.size()) {
+ mItems.add(item);
+ } else {
+ mItems.add(pos, item);
+ }
+ } else {
+ mItems.add(item);
}
}
- boolean contains(@NonNull final String packageName, final int userId) {
- return select(packageName, userId) != null;
+ /**
+ * Returns true if the settings were modified, false if they remain the same.
+ */
+ boolean remove(@NonNull final String packageName, final int userId) {
+ final int idx = select(packageName, userId);
+ if (idx < 0) {
+ return false;
+ }
+
+ mItems.remove(idx);
+ return true;
}
OverlayInfo getOverlayInfo(@NonNull final String packageName, final int userId)
throws BadKeyException {
- final SettingsItem item = select(packageName, userId);
- if (item == null) {
+ final int idx = select(packageName, userId);
+ if (idx < 0) {
throw new BadKeyException(packageName, userId);
}
- return item.getOverlayInfo();
+ return mItems.get(idx).getOverlayInfo();
}
- String getTargetPackageName(@NonNull final String packageName, final int userId)
- throws BadKeyException {
- final SettingsItem item = select(packageName, userId);
- if (item == null) {
- throw new BadKeyException(packageName, userId);
- }
- return item.getTargetPackageName();
- }
-
- void setBaseCodePath(@NonNull final String packageName, final int userId,
+ /**
+ * Returns true if the settings were modified, false if they remain the same.
+ */
+ boolean setBaseCodePath(@NonNull final String packageName, final int userId,
@NonNull final String path) throws BadKeyException {
- final SettingsItem item = select(packageName, userId);
- if (item == null) {
+ final int idx = select(packageName, userId);
+ if (idx < 0) {
throw new BadKeyException(packageName, userId);
}
- item.setBaseCodePath(path);
- notifySettingsChanged();
+ return mItems.get(idx).setBaseCodePath(path);
}
boolean getEnabled(@NonNull final String packageName, final int userId) throws BadKeyException {
- final SettingsItem item = select(packageName, userId);
- if (item == null) {
+ final int idx = select(packageName, userId);
+ if (idx < 0) {
throw new BadKeyException(packageName, userId);
}
- return item.isEnabled();
+ return mItems.get(idx).isEnabled();
}
- void setEnabled(@NonNull final String packageName, final int userId, final boolean enable)
+ /**
+ * Returns true if the settings were modified, false if they remain the same.
+ */
+ boolean setEnabled(@NonNull final String packageName, final int userId, final boolean enable)
throws BadKeyException {
- final SettingsItem item = select(packageName, userId);
- if (item == null) {
+ final int idx = select(packageName, userId);
+ if (idx < 0) {
throw new BadKeyException(packageName, userId);
}
- if (enable == item.isEnabled()) {
- return; // nothing to do
- }
-
- item.setEnabled(enable);
- notifySettingsChanged();
+ return mItems.get(idx).setEnabled(enable);
}
int getState(@NonNull final String packageName, final int userId) throws BadKeyException {
- final SettingsItem item = select(packageName, userId);
- if (item == null) {
+ final int idx = select(packageName, userId);
+ if (idx < 0) {
throw new BadKeyException(packageName, userId);
}
- return item.getState();
+ return mItems.get(idx).getState();
}
- void setState(@NonNull final String packageName, final int userId, final int state)
+ /**
+ * Returns true if the settings were modified, false if they remain the same.
+ */
+ boolean setState(@NonNull final String packageName, final int userId, final int state)
throws BadKeyException {
- final SettingsItem item = select(packageName, userId);
- if (item == null) {
+ final int idx = select(packageName, userId);
+ if (idx < 0) {
throw new BadKeyException(packageName, userId);
}
- final OverlayInfo previous = item.getOverlayInfo();
- item.setState(state);
- final OverlayInfo current = item.getOverlayInfo();
- if (previous.state == STATE_UNKNOWN) {
- notifyOverlayAdded(current);
- notifySettingsChanged();
- } else if (current.state != previous.state) {
- notifyOverlayChanged(current, previous);
- notifySettingsChanged();
- }
+ return mItems.get(idx).setState(state);
}
List<OverlayInfo> getOverlaysForTarget(@NonNull final String targetPackageName,
final int userId) {
- final List<SettingsItem> items = selectWhereTarget(targetPackageName, userId);
- if (items.isEmpty()) {
- return Collections.emptyList();
- }
- final List<OverlayInfo> out = new ArrayList<>(items.size());
- final int N = items.size();
- for (int i = 0; i < N; i++) {
- final SettingsItem item = items.get(i);
- out.add(item.getOverlayInfo());
- }
- return out;
+ return selectWhereTarget(targetPackageName, userId)
+ .map(SettingsItem::getOverlayInfo)
+ .collect(Collectors.toList());
}
ArrayMap<String, List<OverlayInfo>> getOverlaysForUser(final int userId) {
- final List<SettingsItem> items = selectWhereUser(userId);
- if (items.isEmpty()) {
- return ArrayMap.EMPTY;
- }
- final ArrayMap<String, List<OverlayInfo>> out = new ArrayMap<>(items.size());
- final int N = items.size();
- for (int i = 0; i < N; i++) {
- final SettingsItem item = items.get(i);
- final String targetPackageName = item.getTargetPackageName();
- if (!out.containsKey(targetPackageName)) {
- out.put(targetPackageName, new ArrayList<OverlayInfo>());
- }
- final List<OverlayInfo> overlays = out.get(targetPackageName);
- overlays.add(item.getOverlayInfo());
- }
- return out;
+ return selectWhereUser(userId)
+ .map(SettingsItem::getOverlayInfo)
+ .collect(Collectors.groupingBy(info -> info.targetPackageName, ArrayMap::new,
+ Collectors.toList()));
}
- List<String> getTargetPackageNamesForUser(final int userId) {
- final List<SettingsItem> items = selectWhereUser(userId);
- if (items.isEmpty()) {
- return Collections.emptyList();
- }
- final List<String> out = new ArrayList<>();
- final int N = items.size();
- for (int i = 0; i < N; i++) {
- final SettingsItem item = items.get(i);
- final String targetPackageName = item.getTargetPackageName();
- if (!out.contains(targetPackageName)) {
- out.add(targetPackageName);
- }
- }
- return out;
+ int[] getUsers() {
+ return mItems.stream().mapToInt(SettingsItem::getUserId).distinct().toArray();
}
- List<Integer> getUsers() {
- final ArrayList<Integer> users = new ArrayList<>();
- final int N = mItems.size();
- for (int i = 0; i < N; i++) {
+ /**
+ * Returns true if the settings were modified, false if they remain the same.
+ */
+ boolean removeUser(final int userId) {
+ boolean removed = false;
+ for (int i = 0; i < mItems.size(); i++) {
final SettingsItem item = mItems.get(i);
- if (!users.contains(item.userId)) {
- users.add(item.userId);
+ if (item.getUserId() == userId) {
+ if (DEBUG) {
+ Slog.d(TAG, "Removing overlay " + item.mPackageName + " for user " + userId
+ + " from settings because user was removed");
+ }
+ mItems.remove(i);
+ removed = true;
+ i--;
}
}
- return users;
+ return removed;
}
- void removeUser(final int userId) {
- final Iterator<SettingsItem> iter = mItems.iterator();
- while (iter.hasNext()) {
- final SettingsItem item = iter.next();
- if (item.userId == userId) {
- iter.remove();
- }
- }
- }
-
+ /**
+ * Returns true if the settings were modified, false if they remain the same.
+ */
boolean setPriority(@NonNull final String packageName,
@NonNull final String newParentPackageName, final int userId) {
if (packageName.equals(newParentPackageName)) {
return false;
}
- final SettingsItem rowToMove = select(packageName, userId);
- if (rowToMove == null) {
- return false;
- }
- final SettingsItem newParentRow = select(newParentPackageName, userId);
- if (newParentRow == null) {
- return false;
- }
- if (!rowToMove.getTargetPackageName().equals(newParentRow.getTargetPackageName())) {
+ final int moveIdx = select(packageName, userId);
+ if (moveIdx < 0) {
return false;
}
- mItems.remove(rowToMove);
- final ListIterator<SettingsItem> iter = mItems.listIterator();
- while (iter.hasNext()) {
- final SettingsItem item = iter.next();
- if (item.userId == userId && item.packageName.equals(newParentPackageName)) {
- iter.add(rowToMove);
- notifyOverlayPriorityChanged(rowToMove.getOverlayInfo());
- notifySettingsChanged();
- return true;
- }
+ final int parentIdx = select(newParentPackageName, userId);
+ if (parentIdx < 0) {
+ return false;
}
- Slog.wtf(TAG, "failed to find the parent item a second time");
- return false;
+ final SettingsItem itemToMove = mItems.get(moveIdx);
+
+ // Make sure both packages are targeting the same package.
+ if (!itemToMove.getTargetPackageName().equals(
+ mItems.get(parentIdx).getTargetPackageName())) {
+ return false;
+ }
+
+ mItems.remove(moveIdx);
+ final int newParentIdx = select(newParentPackageName, userId);
+ mItems.add(newParentIdx, itemToMove);
+ return moveIdx != newParentIdx;
}
+ /**
+ * Returns true if the settings were modified, false if they remain the same.
+ */
boolean setLowestPriority(@NonNull final String packageName, final int userId) {
- final SettingsItem item = select(packageName, userId);
- if (item == null) {
+ final int idx = select(packageName, userId);
+ if (idx <= 0) {
+ // If the item doesn't exist or is already the lowest, don't change anything.
return false;
}
+
+ final SettingsItem item = mItems.get(idx);
mItems.remove(item);
mItems.add(0, item);
- notifyOverlayPriorityChanged(item.getOverlayInfo());
- notifySettingsChanged();
return true;
}
+ /**
+ * Returns true if the settings were modified, false if they remain the same.
+ */
boolean setHighestPriority(@NonNull final String packageName, final int userId) {
- final SettingsItem item = select(packageName, userId);
- if (item == null) {
+ final int idx = select(packageName, userId);
+
+ // If the item doesn't exist or is already the highest, don't change anything.
+ if (idx < 0 || idx == mItems.size() - 1) {
return false;
}
- mItems.remove(item);
+
+ final SettingsItem item = mItems.get(idx);
+ mItems.remove(idx);
mItems.add(item);
- notifyOverlayPriorityChanged(item.getOverlayInfo());
- notifySettingsChanged();
return true;
}
@@ -296,11 +272,6 @@
void dump(@NonNull final PrintWriter pw) {
pw.println("Settings");
- dumpItems(pw);
- dumpListeners(pw);
- }
-
- private void dumpItems(@NonNull final PrintWriter pw) {
pw.println(TAB1 + "Items");
if (mItems.isEmpty()) {
@@ -312,34 +283,18 @@
for (int i = 0; i < N; i++) {
final SettingsItem item = mItems.get(i);
final StringBuilder sb = new StringBuilder();
- sb.append(TAB2 + item.packageName + ":" + item.userId + " {\n");
- sb.append(TAB3 + "packageName.......: " + item.packageName + "\n");
- sb.append(TAB3 + "userId............: " + item.userId + "\n");
- sb.append(TAB3 + "targetPackageName.: " + item.getTargetPackageName() + "\n");
- sb.append(TAB3 + "baseCodePath......: " + item.getBaseCodePath() + "\n");
- sb.append(TAB3 + "state.............: " + OverlayInfo.stateToString(item.getState()) + "\n");
- sb.append(TAB3 + "isEnabled.........: " + item.isEnabled() + "\n");
+ sb.append(TAB2 + item.mPackageName + ":" + item.getUserId() + " {\n");
+ sb.append(TAB3 + "mPackageName.......: " + item.mPackageName + "\n");
+ sb.append(TAB3 + "mUserId............: " + item.getUserId() + "\n");
+ sb.append(TAB3 + "mTargetPackageName.: " + item.getTargetPackageName() + "\n");
+ sb.append(TAB3 + "mBaseCodePath......: " + item.getBaseCodePath() + "\n");
+ sb.append(TAB3 + "mState.............: " + OverlayInfo.stateToString(item.getState()) + "\n");
+ sb.append(TAB3 + "mIsEnabled.........: " + item.isEnabled() + "\n");
sb.append(TAB2 + "}");
pw.println(sb.toString());
}
}
- private void dumpListeners(@NonNull final PrintWriter pw) {
- pw.println(TAB1 + "Change listeners");
-
- if (mListeners.isEmpty()) {
- pw.println(TAB2 + "<none>");
- return;
- }
-
- final int N = mListeners.size();
- for (int i = 0; i < N; i++) {
- final ChangeListener ch = mListeners.get(i);
- pw.println(TAB2 + ch);
- }
-
- }
-
void restore(@NonNull final InputStream is) throws IOException, XmlPullParserException {
Serializer.restore(mItems, is);
}
@@ -357,6 +312,8 @@
private static final String ATTR_PACKAGE_NAME = "packageName";
private static final String ATTR_STATE = "state";
private static final String ATTR_TARGET_PACKAGE_NAME = "targetPackageName";
+ private static final String ATTR_IS_STATIC = "isStatic";
+ private static final String ATTR_PRIORITY = "priority";
private static final String ATTR_USER_ID = "userId";
private static final String ATTR_VERSION = "version";
@@ -408,9 +365,11 @@
final String baseCodePath = XmlUtils.readStringAttribute(parser, ATTR_BASE_CODE_PATH);
final int state = XmlUtils.readIntAttribute(parser, ATTR_STATE);
final boolean isEnabled = XmlUtils.readBooleanAttribute(parser, ATTR_IS_ENABLED);
+ final boolean isStatic = XmlUtils.readBooleanAttribute(parser, ATTR_IS_STATIC);
+ final int priority = XmlUtils.readIntAttribute(parser, ATTR_PRIORITY);
return new SettingsItem(packageName, userId, targetPackageName, baseCodePath, state,
- isEnabled);
+ isEnabled, isStatic, priority);
}
public static void persist(@NonNull final ArrayList<SettingsItem> table,
@@ -434,127 +393,138 @@
private static void persistRow(@NonNull final FastXmlSerializer xml,
@NonNull final SettingsItem item) throws IOException {
xml.startTag(null, TAG_ITEM);
- XmlUtils.writeStringAttribute(xml, ATTR_PACKAGE_NAME, item.packageName);
- XmlUtils.writeIntAttribute(xml, ATTR_USER_ID, item.userId);
- XmlUtils.writeStringAttribute(xml, ATTR_TARGET_PACKAGE_NAME, item.targetPackageName);
- XmlUtils.writeStringAttribute(xml, ATTR_BASE_CODE_PATH, item.baseCodePath);
- XmlUtils.writeIntAttribute(xml, ATTR_STATE, item.state);
- XmlUtils.writeBooleanAttribute(xml, ATTR_IS_ENABLED, item.isEnabled);
+ XmlUtils.writeStringAttribute(xml, ATTR_PACKAGE_NAME, item.mPackageName);
+ XmlUtils.writeIntAttribute(xml, ATTR_USER_ID, item.mUserId);
+ XmlUtils.writeStringAttribute(xml, ATTR_TARGET_PACKAGE_NAME, item.mTargetPackageName);
+ XmlUtils.writeStringAttribute(xml, ATTR_BASE_CODE_PATH, item.mBaseCodePath);
+ XmlUtils.writeIntAttribute(xml, ATTR_STATE, item.mState);
+ XmlUtils.writeBooleanAttribute(xml, ATTR_IS_ENABLED, item.mIsEnabled);
+ XmlUtils.writeBooleanAttribute(xml, ATTR_IS_STATIC, item.mIsStatic);
+ XmlUtils.writeIntAttribute(xml, ATTR_PRIORITY, item.mPriority);
xml.endTag(null, TAG_ITEM);
}
}
private static final class SettingsItem {
- private final int userId;
- private final String packageName;
- private final String targetPackageName;
- private String baseCodePath;
- private int state;
- private boolean isEnabled;
- private OverlayInfo cache;
+ private final int mUserId;
+ private final String mPackageName;
+ private final String mTargetPackageName;
+ private String mBaseCodePath;
+ private int mState;
+ private boolean mIsEnabled;
+ private OverlayInfo mCache;
+ private boolean mIsStatic;
+ private int mPriority;
SettingsItem(@NonNull final String packageName, final int userId,
@NonNull final String targetPackageName, @NonNull final String baseCodePath,
- final int state, final boolean isEnabled) {
- this.packageName = packageName;
- this.userId = userId;
- this.targetPackageName = targetPackageName;
- this.baseCodePath = baseCodePath;
- this.state = state;
- this.isEnabled = isEnabled;
- cache = null;
+ final int state, final boolean isEnabled, final boolean isStatic,
+ final int priority) {
+ mPackageName = packageName;
+ mUserId = userId;
+ mTargetPackageName = targetPackageName;
+ mBaseCodePath = baseCodePath;
+ mState = state;
+ mIsEnabled = isEnabled;
+ mCache = null;
+ mIsStatic = isStatic;
+ mPriority = priority;
}
SettingsItem(@NonNull final String packageName, final int userId,
- @NonNull final String targetPackageName, @NonNull final String baseCodePath) {
- this(packageName, userId, targetPackageName, baseCodePath, STATE_UNKNOWN,
- false);
+ @NonNull final String targetPackageName, @NonNull final String baseCodePath,
+ final boolean isStatic, final int priority) {
+ this(packageName, userId, targetPackageName, baseCodePath, OverlayInfo.STATE_UNKNOWN,
+ false, isStatic, priority);
}
private String getTargetPackageName() {
- return targetPackageName;
+ return mTargetPackageName;
+ }
+
+ private int getUserId() {
+ return mUserId;
}
private String getBaseCodePath() {
- return baseCodePath;
+ return mBaseCodePath;
}
- private void setBaseCodePath(@NonNull final String path) {
- if (!baseCodePath.equals(path)) {
- baseCodePath = path;
+ private boolean setBaseCodePath(@NonNull final String path) {
+ if (!mBaseCodePath.equals(path)) {
+ mBaseCodePath = path;
invalidateCache();
+ return true;
}
+ return false;
}
private int getState() {
- return state;
+ return mState;
}
- private void setState(final int state) {
- if (this.state != state) {
- this.state = state;
+ private boolean setState(final int state) {
+ if (mState != state) {
+ mState = state;
invalidateCache();
+ return true;
}
+ return false;
}
private boolean isEnabled() {
- return isEnabled;
+ return mIsEnabled;
}
- private void setEnabled(final boolean enable) {
- if (isEnabled != enable) {
- isEnabled = enable;
+ private boolean setEnabled(final boolean enable) {
+ if (mIsEnabled != enable) {
+ mIsEnabled = enable;
invalidateCache();
+ return true;
}
+ return false;
}
private OverlayInfo getOverlayInfo() {
- if (cache == null) {
- cache = new OverlayInfo(packageName, targetPackageName, baseCodePath,
- state, userId);
+ if (mCache == null) {
+ mCache = new OverlayInfo(mPackageName, mTargetPackageName, mBaseCodePath, mState,
+ mUserId);
}
- return cache;
+ return mCache;
}
private void invalidateCache() {
- cache = null;
+ mCache = null;
+ }
+
+ private boolean isStatic() {
+ return mIsStatic;
+ }
+
+ private int getPriority() {
+ return mPriority;
}
}
- private SettingsItem select(@NonNull final String packageName, final int userId) {
+ private int select(@NonNull final String packageName, final int userId) {
final int N = mItems.size();
for (int i = 0; i < N; i++) {
final SettingsItem item = mItems.get(i);
- if (item.userId == userId && item.packageName.equals(packageName)) {
- return item;
+ if (item.mUserId == userId && item.mPackageName.equals(packageName)) {
+ return i;
}
}
- return null;
+ return -1;
}
- private List<SettingsItem> selectWhereUser(final int userId) {
- final ArrayList<SettingsItem> items = new ArrayList<>();
- final int N = mItems.size();
- for (int i = 0; i < N; i++) {
- final SettingsItem item = mItems.get(i);
- if (item.userId == userId) {
- items.add(item);
- }
- }
- return items;
+ private Stream<SettingsItem> selectWhereUser(final int userId) {
+ return mItems.stream().filter(item -> item.mUserId == userId);
}
- private List<SettingsItem> selectWhereTarget(@NonNull final String targetPackageName,
+ private Stream<SettingsItem> selectWhereTarget(@NonNull final String targetPackageName,
final int userId) {
- final ArrayList<SettingsItem> items = new ArrayList<>();
- final int N = mItems.size();
- for (int i = 0; i < N; i++) {
- final SettingsItem item = mItems.get(i);
- if (item.userId == userId && item.getTargetPackageName().equals(targetPackageName)) {
- items.add(item);
- }
- }
- return items;
+ return selectWhereUser(userId)
+ .filter(item -> item.getTargetPackageName().equals(targetPackageName));
}
private void assertNotNull(@Nullable final Object o) {
@@ -563,79 +533,9 @@
}
}
- void addChangeListener(@NonNull final ChangeListener listener) {
- mListeners.add(listener);
- }
-
- void removeChangeListener(@NonNull final ChangeListener listener) {
- mListeners.remove(listener);
- }
-
- private void notifySettingsChanged() {
- final int N = mListeners.size();
- for (int i = 0; i < N; i++) {
- final ChangeListener listener = mListeners.get(i);
- listener.onSettingsChanged();
- }
- }
-
- private void notifyOverlayAdded(@NonNull final OverlayInfo oi) {
- if (DEBUG) {
- assertNotNull(oi);
- }
- final int N = mListeners.size();
- for (int i = 0; i < N; i++) {
- final ChangeListener listener = mListeners.get(i);
- listener.onOverlayAdded(oi);
- }
- }
-
- private void notifyOverlayRemoved(@NonNull final OverlayInfo oi) {
- if (DEBUG) {
- assertNotNull(oi);
- }
- final int N = mListeners.size();
- for (int i = 0; i < N; i++) {
- final ChangeListener listener = mListeners.get(i);
- listener.onOverlayRemoved(oi);
- }
- }
-
- private void notifyOverlayChanged(@NonNull final OverlayInfo oi,
- @NonNull final OverlayInfo oldOi) {
- if (DEBUG) {
- assertNotNull(oi);
- assertNotNull(oldOi);
- }
- final int N = mListeners.size();
- for (int i = 0; i < N; i++) {
- final ChangeListener listener = mListeners.get(i);
- listener.onOverlayChanged(oi, oldOi);
- }
- }
-
- private void notifyOverlayPriorityChanged(@NonNull final OverlayInfo oi) {
- if (DEBUG) {
- assertNotNull(oi);
- }
- final int N = mListeners.size();
- for (int i = 0; i < N; i++) {
- final ChangeListener listener = mListeners.get(i);
- listener.onOverlayPriorityChanged(oi);
- }
- }
-
- interface ChangeListener {
- void onSettingsChanged();
- void onOverlayAdded(@NonNull OverlayInfo oi);
- void onOverlayRemoved(@NonNull OverlayInfo oi);
- void onOverlayChanged(@NonNull OverlayInfo oi, @NonNull OverlayInfo oldOi);
- void onOverlayPriorityChanged(@NonNull OverlayInfo oi);
- }
-
static final class BadKeyException extends RuntimeException {
BadKeyException(@NonNull final String packageName, final int userId) {
- super("Bad key packageName=" + packageName + " userId=" + userId);
+ super("Bad key mPackageName=" + packageName + " mUserId=" + userId);
}
}
}
diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
index c4cc4fb..e472928e 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
@@ -32,6 +32,7 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.util.Slog;
import android.util.TimedRemoteCaller;
import com.android.internal.os.TransferPipe;
@@ -49,9 +50,11 @@
* @hide
*/
final class EphemeralResolverConnection implements DeathRecipient {
+ private static final String TAG = "PackageManager";
// This is running in a critical section and the timeout must be sufficiently low
private static final long BIND_SERVICE_TIMEOUT_MS =
("eng".equals(Build.TYPE)) ? 300 : 200;
+ private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE;
private final Object mLock = new Object();
private final GetEphemeralResolveInfoCaller mGetEphemeralResolveInfoCaller =
@@ -143,6 +146,9 @@
if (!mBindRequested) {
mBindRequested = true;
+ if (DEBUG_EPHEMERAL) {
+ Slog.d(TAG, "Binding to resolver service");
+ }
mContext.bindServiceAsUser(mIntent, mServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, UserHandle.SYSTEM);
}
@@ -175,6 +181,9 @@
@Override
public void binderDied() {
+ if (DEBUG_EPHEMERAL) {
+ Slog.d(TAG, "Binder died");
+ }
if (mRemoteInstance != null) {
mRemoteInstance.asBinder().unlinkToDeath(this, 0 /*flags*/);
}
@@ -193,6 +202,9 @@
private final class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
+ if (DEBUG_EPHEMERAL) {
+ Slog.d(TAG, "Service connected");
+ }
synchronized (mLock) {
try {
service.linkToDeath(EphemeralResolverConnection.this, 0 /*flags*/);
@@ -205,6 +217,9 @@
@Override
public void onServiceDisconnected(ComponentName name) {
+ if (DEBUG_EPHEMERAL) {
+ Slog.d(TAG, "Service disconnected");
+ }
synchronized (mLock) {
mRemoteInstance = null;
}
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 498181b..7b86542 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -95,9 +95,6 @@
public OtaDexoptService(Context context, PackageManagerService packageManagerService) {
this.mContext = context;
this.mPackageManagerService = packageManagerService;
-
- // Now it's time to check whether we need to move any A/B artifacts.
- moveAbArtifacts(packageManagerService.mInstaller);
}
public static OtaDexoptService main(Context context,
@@ -105,6 +102,9 @@
OtaDexoptService ota = new OtaDexoptService(context, packageManagerService);
ServiceManager.addService("otadexopt", ota);
+ // Now it's time to check whether we need to move any A/B artifacts.
+ ota.moveAbArtifacts(packageManagerService.mInstaller);
+
return ota;
}
@@ -323,8 +323,15 @@
throw new IllegalStateException("Should not be ota-dexopting when trying to move.");
}
+ if (!mPackageManagerService.isUpgrade()) {
+ Slog.d(TAG, "No upgrade, skipping A/B artifacts check.");
+ return;
+ }
+
// Look into all packages.
Collection<PackageParser.Package> pkgs = mPackageManagerService.getPackages();
+ int packagePaths = 0;
+ int pathsSuccessful = 0;
for (PackageParser.Package pkg : pkgs) {
if (pkg == null) {
continue;
@@ -355,13 +362,16 @@
// TODO: Check first whether there is an artifact, to save the roundtrip time.
+ packagePaths++;
try {
installer.moveAb(path, dexCodeInstructionSet, oatDir);
+ pathsSuccessful++;
} catch (InstallerException e) {
}
}
}
}
+ Slog.i(TAG, "Moved " + pathsSuccessful + "/" + packagePaths);
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e514ecb..650d2f6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -90,7 +90,6 @@
import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
import static com.android.internal.util.ArrayUtils.appendInt;
-import static com.android.server.pm.Installer.DEXOPT_PUBLIC;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
@@ -164,7 +163,6 @@
import android.content.pm.PermissionInfo;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
-import android.content.pm.SELinuxUtil;
import android.content.pm.ServiceInfo;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.Signature;
@@ -173,6 +171,7 @@
import android.content.pm.VerifierInfo;
import android.content.pm.VersionedPackage;
import android.content.res.Resources;
+import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.hardware.display.DisplayManager;
import android.net.Uri;
@@ -221,6 +220,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Base64;
+import android.util.BootTimingsTraceLog;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.ExceptionUtils;
@@ -272,7 +272,6 @@
import com.android.server.SystemServerInitThreadPool;
import com.android.server.Watchdog;
import com.android.server.net.NetworkPolicyManagerInternal;
-import com.android.server.pm.BackgroundDexOptService;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.PermissionsState.PermissionState;
import com.android.server.pm.Settings.DatabaseVersion;
@@ -298,7 +297,6 @@
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FilenameFilter;
@@ -396,7 +394,6 @@
/** REMOVE. According to Svet, this was only used to reset permissions during development. */
static final boolean CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE = false;
- private static final boolean DISABLE_EPHEMERAL_APPS = false;
private static final boolean HIDE_EPHEMERAL_APIS = false;
private static final boolean ENABLE_FREE_CACHE_V2 =
@@ -829,6 +826,7 @@
volatile boolean mSystemReady;
volatile boolean mSafeMode;
volatile boolean mHasSystemUidErrors;
+ private volatile boolean mEphemeralAppsDisabled;
ApplicationInfo mAndroidApplication;
final ActivityInfo mResolveActivity = new ActivityInfo();
@@ -1835,6 +1833,10 @@
extras.putInt(Intent.EXTRA_UID, res.uid);
if (update) {
extras.putBoolean(Intent.EXTRA_REPLACING, true);
+ } else {
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_ADDED, packageName,
+ extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
+ null /*targetPackage*/, null /*finishedReceiver*/, updateUsers);
}
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/, null /*targetPackage*/,
@@ -2725,15 +2727,18 @@
UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,
true /* onlyCoreApps */);
mPrepareAppDataFuture = SystemServerInitThreadPool.get().submit(() -> {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "fixup");
+ BootTimingsTraceLog traceLog = new BootTimingsTraceLog("SystemServerTimingAsync",
+ Trace.TRACE_TAG_PACKAGE_MANAGER);
+ traceLog.traceBegin("AppDataFixup");
try {
mInstaller.fixupAppData(StorageManager.UUID_PRIVATE_INTERNAL,
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
} catch (InstallerException e) {
Slog.w(TAG, "Trouble fixing GIDs", e);
}
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ traceLog.traceEnd();
+ traceLog.traceBegin("AppDataPrepare");
if (deferPackages == null || deferPackages.isEmpty()) {
return;
}
@@ -2754,6 +2759,7 @@
count++;
}
}
+ traceLog.traceEnd();
Slog.i(TAG, "Deferred reconcileAppsData finished " + count + " packages");
}, "prepareAppData");
@@ -4083,6 +4089,24 @@
return updateFlagsForComponent(flags, userId, intent /*cookie*/);
}
+ private ActivityInfo generateActivityInfo(ActivityInfo ai, int flags, PackageUserState state,
+ int userId) {
+ ActivityInfo ret = PackageParser.generateActivityInfo(ai, flags, state, userId);
+ if (ret != null) {
+ rebaseEnabledOverlays(ret.applicationInfo, userId);
+ }
+ return ret;
+ }
+
+ private ActivityInfo generateActivityInfo(PackageParser.Activity a, int flags,
+ PackageUserState state, int userId) {
+ ActivityInfo ai = PackageParser.generateActivityInfo(a, flags, state, userId);
+ if (ai != null) {
+ rebaseEnabledOverlays(ai.applicationInfo, userId);
+ }
+ return ai;
+ }
+
@Override
public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
@@ -4096,12 +4120,11 @@
if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
if (ps == null) return null;
- return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
- userId);
+ return generateActivityInfo(a, flags, ps.readUserState(userId), userId);
}
if (mResolveComponentName.equals(component)) {
- return PackageParser.generateActivityInfo(mResolveActivity, flags,
- new PackageUserState(), userId);
+ return generateActivityInfo(mResolveActivity, flags, new PackageUserState(),
+ userId);
}
}
return null;
@@ -4142,12 +4165,7 @@
if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
if (ps == null) return null;
- ActivityInfo ri = PackageParser.generateActivityInfo(a, flags,
- ps.readUserState(userId), userId);
- if (ri != null) {
- rebaseEnabledOverlays(ri.applicationInfo, userId);
- }
- return ri;
+ return generateActivityInfo(a, flags, ps.readUserState(userId), userId);
}
}
return null;
@@ -5703,33 +5721,15 @@
/**
* Returns whether or not instant apps have been disabled remotely.
- * <p><em>IMPORTANT</em> This should not be called with the package manager lock
- * held. Otherwise we run the risk of deadlock.
*/
private boolean isEphemeralDisabled() {
- // ephemeral apps have been disabled across the board
- if (DISABLE_EPHEMERAL_APPS) {
- return true;
- }
- // system isn't up yet; can't read settings, so, assume no ephemeral apps
- if (!mSystemReady) {
- return true;
- }
- // we can't get a content resolver until the system is ready; these checks must happen last
- final ContentResolver resolver = mContext.getContentResolver();
- if (Global.getInt(resolver, Global.ENABLE_EPHEMERAL_FEATURE, 1) == 0) {
- return true;
- }
- return Secure.getInt(resolver, Secure.WEB_ACTION_ENABLED, 1) == 0;
+ return mEphemeralAppsDisabled;
}
private boolean isEphemeralAllowed(
Intent intent, List<ResolveInfo> resolvedActivities, int userId,
boolean skipPackageCheck) {
final int callingUser = UserHandle.getCallingUserId();
- if (callingUser != UserHandle.USER_SYSTEM) {
- return false;
- }
if (mInstantAppResolverConnection == null) {
return false;
}
@@ -6340,19 +6340,24 @@
Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
}
final ResolveInfo ephemeralInstaller = new ResolveInfo(mInstantAppInstallerInfo);
- ephemeralInstaller.activityInfo = new ActivityInfo(mInstantAppInstallerActivity);
- ephemeralInstaller.activityInfo.launchToken = auxiliaryResponse.token;
- ephemeralInstaller.auxiliaryInfo = auxiliaryResponse;
- // make sure this resolver is the default
- ephemeralInstaller.isDefault = true;
- ephemeralInstaller.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
- | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
- // add a non-generic filter
- ephemeralInstaller.filter = new IntentFilter(intent.getAction());
- ephemeralInstaller.filter.addDataPath(
- intent.getData().getPath(), PatternMatcher.PATTERN_LITERAL);
- ephemeralInstaller.instantAppAvailable = true;
- result.add(ephemeralInstaller);
+ final PackageSetting ps =
+ mSettings.mPackages.get(mInstantAppInstallerActivity.packageName);
+ if (ps != null) {
+ ephemeralInstaller.activityInfo = PackageParser.generateActivityInfo(
+ mInstantAppInstallerActivity, 0, ps.readUserState(userId), userId);
+ ephemeralInstaller.activityInfo.launchToken = auxiliaryResponse.token;
+ ephemeralInstaller.auxiliaryInfo = auxiliaryResponse;
+ // make sure this resolver is the default
+ ephemeralInstaller.isDefault = true;
+ ephemeralInstaller.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
+ | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
+ // add a non-generic filter
+ ephemeralInstaller.filter = new IntentFilter(intent.getAction());
+ ephemeralInstaller.filter.addDataPath(
+ intent.getData().getPath(), PatternMatcher.PATTERN_LITERAL);
+ ephemeralInstaller.instantAppAvailable = true;
+ result.add(ephemeralInstaller);
+ }
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
@@ -7094,17 +7099,23 @@
// used when either 1) the service is in an instant application and the
// caller is not the same instant application or 2) the calling package is
// ephemeral and the activity is not visible to ephemeral applications.
+ final boolean matchInstantApp =
+ (flags & PackageManager.MATCH_INSTANT) != 0;
final boolean matchVisibleToInstantAppOnly =
(flags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
final boolean isCallerInstantApp =
instantAppPkgName != null;
final boolean isTargetSameInstantApp =
comp.getPackageName().equals(instantAppPkgName);
+ final boolean isTargetInstantApp =
+ (si.applicationInfo.privateFlags
+ & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
final boolean isTargetHiddenFromInstantApp =
(si.flags & ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0;
final boolean blockResolution =
!isTargetSameInstantApp
- && ((matchVisibleToInstantAppOnly && isCallerInstantApp
+ && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp)
+ || (matchVisibleToInstantAppOnly && isCallerInstantApp
&& isTargetHiddenFromInstantApp));
if (!blockResolution) {
final ResolveInfo ri = new ResolveInfo();
@@ -7191,6 +7202,7 @@
Intent intent, String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
final int callingUid = Binder.getCallingUid();
+ final String instantAppPkgName = getInstantAppPackageName(callingUid);
flags = updateFlagsForResolve(flags, userId, intent, callingUid,
false /*includeInstantApps*/);
ComponentName comp = intent.getComponent();
@@ -7204,9 +7216,33 @@
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
final ProviderInfo pi = getProviderInfo(comp, flags, userId);
if (pi != null) {
- final ResolveInfo ri = new ResolveInfo();
- ri.providerInfo = pi;
- list.add(ri);
+ // When specifying an explicit component, we prevent the provider from being
+ // used when either 1) the provider is in an instant application and the
+ // caller is not the same instant application or 2) the calling package is an
+ // instant application and the provider is not visible to instant applications.
+ final boolean matchInstantApp =
+ (flags & PackageManager.MATCH_INSTANT) != 0;
+ final boolean matchVisibleToInstantAppOnly =
+ (flags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+ final boolean isCallerInstantApp =
+ instantAppPkgName != null;
+ final boolean isTargetSameInstantApp =
+ comp.getPackageName().equals(instantAppPkgName);
+ final boolean isTargetInstantApp =
+ (pi.applicationInfo.privateFlags
+ & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
+ final boolean isTargetHiddenFromInstantApp =
+ (pi.flags & ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0;
+ final boolean blockResolution =
+ !isTargetSameInstantApp
+ && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp)
+ || (matchVisibleToInstantAppOnly && isCallerInstantApp
+ && isTargetHiddenFromInstantApp));
+ if (!blockResolution) {
+ final ResolveInfo ri = new ResolveInfo();
+ ri.providerInfo = pi;
+ list.add(ri);
+ }
}
return list;
}
@@ -7215,17 +7251,67 @@
synchronized (mPackages) {
String pkgName = intent.getPackage();
if (pkgName == null) {
- return mProviders.queryIntent(intent, resolvedType, flags, userId);
+ return applyPostContentProviderResolutionFilter(
+ mProviders.queryIntent(intent, resolvedType, flags, userId),
+ instantAppPkgName);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
- return mProviders.queryIntentForPackage(
- intent, resolvedType, flags, pkg.providers, userId);
+ return applyPostContentProviderResolutionFilter(
+ mProviders.queryIntentForPackage(
+ intent, resolvedType, flags, pkg.providers, userId),
+ instantAppPkgName);
}
return Collections.emptyList();
}
}
+ private List<ResolveInfo> applyPostContentProviderResolutionFilter(
+ List<ResolveInfo> resolveInfos, String instantAppPkgName) {
+ // TODO: When adding on-demand split support for non-instant applications, remove
+ // this check and always apply post filtering
+ if (instantAppPkgName == null) {
+ return resolveInfos;
+ }
+ for (int i = resolveInfos.size() - 1; i >= 0; i--) {
+ final ResolveInfo info = resolveInfos.get(i);
+ final boolean isEphemeralApp = info.providerInfo.applicationInfo.isInstantApp();
+ // allow providers that are defined in the provided package
+ if (isEphemeralApp && instantAppPkgName.equals(info.providerInfo.packageName)) {
+ if (info.providerInfo.splitName != null
+ && !ArrayUtils.contains(info.providerInfo.applicationInfo.splitNames,
+ info.providerInfo.splitName)) {
+ // requested provider is defined in a split that hasn't been installed yet.
+ // add the installer to the resolve list
+ if (DEBUG_EPHEMERAL) {
+ Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
+ }
+ final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo);
+ installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
+ info.providerInfo.packageName, info.providerInfo.splitName,
+ info.providerInfo.applicationInfo.versionCode);
+ // make sure this resolver is the default
+ installerInfo.isDefault = true;
+ installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
+ | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
+ // add a non-generic filter
+ installerInfo.filter = new IntentFilter();
+ // load resources from the correct package
+ installerInfo.resolvePackageName = info.getComponentInfo().packageName;
+ resolveInfos.set(i, installerInfo);
+ }
+ continue;
+ }
+ // allow providers that have been explicitly exposed to instant applications
+ if (!isEphemeralApp
+ && ((info.providerInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0)) {
+ continue;
+ }
+ resolveInfos.remove(i);
+ }
+ return resolveInfos;
+ }
+
@Override
public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
@@ -7557,17 +7643,38 @@
public ProviderInfo resolveContentProvider(String name, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForComponent(flags, userId, name);
+ final String instantAppPkgName = getInstantAppPackageName(Binder.getCallingUid());
// reader
synchronized (mPackages) {
final PackageParser.Provider provider = mProvidersByAuthority.get(name);
PackageSetting ps = provider != null
? mSettings.mPackages.get(provider.owner.packageName)
: null;
- return ps != null
- && mSettings.isEnabledAndMatchLPr(provider.info, flags, userId)
- ? PackageParser.generateProviderInfo(provider, flags,
- ps.readUserState(userId), userId)
- : null;
+ if (ps != null) {
+ final boolean isInstantApp = ps.getInstantApp(userId);
+ // normal application; filter out instant application provider
+ if (instantAppPkgName == null && isInstantApp) {
+ return null;
+ }
+ // instant application; filter out other instant applications
+ if (instantAppPkgName != null
+ && isInstantApp
+ && !provider.owner.packageName.equals(instantAppPkgName)) {
+ return null;
+ }
+ // instant application; filter out non-exposed provider
+ if (instantAppPkgName != null
+ && (provider.info.flags & ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0) {
+ return null;
+ }
+ // provider not enabled
+ if (!mSettings.isEnabledAndMatchLPr(provider.info, flags, userId)) {
+ return null;
+ }
+ return PackageParser.generateProviderInfo(
+ provider, flags, ps.readUserState(userId), userId);
+ }
+ return null;
}
}
@@ -12307,8 +12414,7 @@
return null;
}
final PackageUserState userState = ps.readUserState(userId);
- ActivityInfo ai = PackageParser.generateActivityInfo(activity, mFlags,
- userState, userId);
+ ActivityInfo ai = generateActivityInfo(activity, mFlags, userState, userId);
if (ai == null) {
return null;
}
@@ -12772,8 +12878,26 @@
if (ps == null) {
return null;
}
+ final PackageUserState userState = ps.readUserState(userId);
+ final boolean matchVisibleToInstantApp =
+ (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+ final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
+ // throw out filters that aren't visible to instant applications
+ if (matchVisibleToInstantApp
+ && !(info.isVisibleToInstantApp() || userState.instantApp)) {
+ return null;
+ }
+ // throw out instant application filters if we're not explicitly requesting them
+ if (!isInstantApp && userState.instantApp) {
+ return null;
+ }
+ // throw out instant application filters if updates are available; will trigger
+ // instant application resolution
+ if (userState.instantApp && ps.isUpdateAvailable()) {
+ return null;
+ }
ProviderInfo pi = PackageParser.generateProviderInfo(provider, mFlags,
- ps.readUserState(userId), userId);
+ userState, userId);
if (pi == null) {
return null;
}
@@ -13271,8 +13395,10 @@
// Set to UID of the first user, EXTRA_UID is automatically updated in sendPackageBroadcast
extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userIds[0], appId));
- sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
- packageName, extras, 0, null, null, userIds);
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_ADDED, packageName,
+ extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, null, null, userIds);
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
+ extras, 0, null, null, userIds);
if (isSystem) {
mHandler.post(() -> {
for (int userId : userIds) {
@@ -20176,6 +20302,21 @@
@Override
public void systemReady() {
mSystemReady = true;
+ final ContentResolver resolver = mContext.getContentResolver();
+ ContentObserver co = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ mEphemeralAppsDisabled =
+ (Global.getInt(resolver, Global.ENABLE_EPHEMERAL_FEATURE, 1) == 0) ||
+ (Secure.getInt(resolver, Secure.INSTANT_APPS_ENABLED, 1) == 0);
+ }
+ };
+ mContext.getContentResolver().registerContentObserver(android.provider.Settings.Global
+ .getUriFor(Global.ENABLE_EPHEMERAL_FEATURE),
+ false, co, UserHandle.USER_SYSTEM);
+ mContext.getContentResolver().registerContentObserver(android.provider.Settings.Global
+ .getUriFor(Secure.INSTANT_APPS_ENABLED), false, co, UserHandle.USER_SYSTEM);
+ co.onChange(true);
// Disable any carrier apps. We do this very early in boot to prevent the apps from being
// disabled after already being started.
@@ -23340,7 +23481,6 @@
intent, resolvedType, flags, userId, callingUid, true /*includeInstantApps*/);
}
-
@Override
public void addIsolatedUid(int isolatedUid, int ownerUid) {
synchronized (mPackages) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 6633efd..4f29bfa 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -145,6 +145,7 @@
import android.database.ContentObserver;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPlaybackClient;
@@ -221,6 +222,7 @@
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
+import android.widget.ImageView;
import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
@@ -2809,6 +2811,7 @@
+ overrideConfig + " to starting window resId=" + resId);
context = overrideContext;
}
+ typedArray.recycle();
}
final PhoneWindow win = new PhoneWindow(context);
@@ -2868,6 +2871,8 @@
}
params.setTitle("Splash Screen " + packageName);
+ addSplashscreenContent(win, context);
+
wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
view = win.getDecorView();
@@ -2898,6 +2903,24 @@
return null;
}
+ private void addSplashscreenContent(PhoneWindow win, Context ctx) {
+ final TypedArray a = ctx.obtainStyledAttributes(R.styleable.Window);
+ final int resId = a.getResourceId(R.styleable.Window_windowSplashscreenContent, 0);
+ a.recycle();
+ if (resId == 0) {
+ return;
+ }
+ final Drawable drawable = ctx.getDrawable(resId);
+ if (drawable == null) {
+ return;
+ }
+
+ // We wrap this into a view so the system insets get applied to the drawable.
+ final View v = new View(ctx);
+ v.setBackground(drawable);
+ win.setContentView(v);
+ }
+
/** Obtain proper context for showing splash screen on the provided display. */
private Context getDisplayContext(Context context, int displayId) {
if (displayId == Display.DEFAULT_DISPLAY) {
@@ -5238,7 +5261,7 @@
@Override
public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
WindowState attached, WindowState imeTarget) {
- final boolean visible = !win.isGoneForLayoutLw();
+ final boolean visible = !win.isGoneForLayoutLw() && win.getAttrs().alpha > 0f;
if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisible=" + visible);
applyKeyguardPolicyLw(win, imeTarget);
final int fl = PolicyControl.getWindowFlags(win, attrs);
@@ -5255,11 +5278,8 @@
}
}
- // Don't allow snapshots to influence SystemUI visibility flags.
- // TODO: Revisit this once SystemUI flags for snapshots are handled correctly
boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
- && attrs.type < FIRST_SYSTEM_WINDOW
- && (attrs.privateFlags & PRIVATE_FLAG_TASK_SNAPSHOT) == 0;
+ && attrs.type < FIRST_SYSTEM_WINDOW;
final int stackId = win.getStackId();
if (mTopFullscreenOpaqueWindowState == null && visible) {
if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index a60dae7..cf597b05 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -46,6 +46,8 @@
import android.os.PowerSaveState;
import android.os.Process;
import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
@@ -4027,6 +4029,14 @@
}
private final class BinderService extends IPowerManager.Stub {
+ @Override
+ public void onShellCommand(FileDescriptor in, FileDescriptor out,
+ FileDescriptor err, String[] args, ShellCallback callback,
+ ResultReceiver resultReceiver) {
+ (new PowerManagerShellCommand(this)).exec(
+ this, in, out, err, args, callback, resultReceiver);
+ }
+
@Override // Binder call
public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,
String packageName, int uid) {
diff --git a/services/core/java/com/android/server/power/PowerManagerShellCommand.java b/services/core/java/com/android/server/power/PowerManagerShellCommand.java
new file mode 100644
index 0000000..46115d8
--- /dev/null
+++ b/services/core/java/com/android/server/power/PowerManagerShellCommand.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.power;
+
+import android.content.Intent;
+import android.os.IPowerManager;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+
+import java.io.PrintWriter;
+
+class PowerManagerShellCommand extends ShellCommand {
+ private static final int LOW_POWER_MODE_ON = 1;
+
+ final IPowerManager mInterface;
+
+ PowerManagerShellCommand(IPowerManager service) {
+ mInterface = service;
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+
+ final PrintWriter pw = getOutPrintWriter();
+ try {
+ switch(cmd) {
+ case "set-mode":
+ return runSetMode();
+ default:
+ return handleDefaultCommands(cmd);
+ }
+ } catch (RemoteException e) {
+ pw.println("Remote exception: " + e);
+ }
+ return -1;
+ }
+
+ private int runSetMode() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ int mode = -1;
+ try {
+ mode = Integer.parseInt(getNextArgRequired());
+ } catch (RuntimeException ex) {
+ pw.println("Error: " + ex.toString());
+ return -1;
+ }
+ mInterface.setPowerSaveMode(mode == LOW_POWER_MODE_ON);
+ return 0;
+ }
+
+ @Override
+ public void onHelp() {
+ final PrintWriter pw = getOutPrintWriter();
+ pw.println("Power manager (power) commands:");
+ pw.println(" help");
+ pw.println(" Print this help text.");
+ pw.println("");
+ pw.println(" set-mode MODE");
+ pw.println(" sets the power mode of the device to MODE.");
+ pw.println(" 1 turns low power mode on and 0 turns low power mode off.");
+ pw.println();
+ Intent.printIntentArgsHelp(pw , "");
+ }
+}
diff --git a/services/core/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java
index 8c31731..8969771 100644
--- a/services/core/java/com/android/server/search/SearchManagerService.java
+++ b/services/core/java/com/android/server/search/SearchManagerService.java
@@ -18,7 +18,6 @@
import android.app.ActivityManager;
import android.app.AppGlobals;
-import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.ISearchManager;
import android.app.SearchManager;
@@ -29,7 +28,6 @@
import android.content.Intent;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
-import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.os.Binder;
@@ -39,8 +37,6 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
-import android.speech.RecognitionService;
-import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
@@ -276,52 +272,6 @@
}
}
- private boolean isDefaultRecognizerPackage(String packageName) {
- ResolveInfo resolveInfo = mContext.getPackageManager().resolveService(
- new Intent(RecognitionService.SERVICE_INTERFACE),
- PackageManager.GET_META_DATA);
- if (resolveInfo == null || resolveInfo.serviceInfo == null) {
- Log.w(TAG, "Unable to resolve default voice recognition service.");
- return false;
- }
- if (!TextUtils.isEmpty(packageName) && TextUtils.equals(packageName,
- resolveInfo.serviceInfo.packageName)) {
- return true;
- }
- return false;
- }
-
- private ComponentName getLegacyAssistReceiverComponent(int userHandle) {
- try {
- userHandle = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
- Binder.getCallingUid(), userHandle, true, false,
- "getLegacyAssistReceiverComponent", null);
- IPackageManager pm = AppGlobals.getPackageManager();
- Intent assistIntent = new Intent(Intent.ACTION_ASSIST);
- ParceledListSlice<ResolveInfo> infoParceledList =
- pm.queryIntentReceivers(assistIntent,
- assistIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
- PackageManager.MATCH_DEFAULT_ONLY, userHandle);
- if (infoParceledList != null) {
- List<ResolveInfo> infoList = infoParceledList.getList();
- if (infoList != null && infoList.size() > 0) {
- if (isDefaultRecognizerPackage(
- infoList.get(0).activityInfo.applicationInfo.packageName)) {
- return new ComponentName(
- infoList.get(0).activityInfo.applicationInfo.packageName,
- infoList.get(0).activityInfo.name);
- }
- }
- }
- } catch (RemoteException re) {
- // Local call
- Log.e(TAG, "RemoteException in getLegacyAssistReceiverComponent: " + re);
- } catch (Exception e) {
- Log.e(TAG, "Exception in getLegacyAssistReceiverComponent: " + e);
- }
- return null;
- }
-
private ComponentName getLegacyAssistComponent(int userHandle) {
try {
userHandle = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
@@ -348,7 +298,7 @@
@Override
public boolean launchLegacyAssist(String hint, int userHandle, Bundle args) {
- ComponentName comp = getLegacyAssistReceiverComponent(userHandle);
+ ComponentName comp = getLegacyAssistComponent(userHandle);
if (comp == null) {
return false;
}
@@ -356,13 +306,9 @@
try {
Intent intent = new Intent(Intent.ACTION_ASSIST);
intent.setComponent(comp);
- if (args != null) {
- intent.putExtras(args);
- }
IActivityManager am = ActivityManager.getService();
- return am.broadcastIntent(null, intent, null, null, 0, null, null, null,
- AppOpsManager.OP_NONE, null, false, false,
- userHandle) == ActivityManager.BROADCAST_SUCCESS;
+ return am.launchAssistIntent(intent, ActivityManager.ASSIST_CONTEXT_BASIC, hint,
+ userHandle, args);
} catch (RemoteException e) {
} finally {
Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index be91f48..25a0772 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -942,6 +942,50 @@
}
@Override
+ public void sendTvInputNotifyIntent(Intent intent, int userId) {
+ if (mContext.checkCallingPermission(android.Manifest.permission.NOTIFY_TV_INPUTS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("The caller: " + getCallingPackageName()
+ + " doesn't have permission: "
+ + android.Manifest.permission.NOTIFY_TV_INPUTS);
+ }
+ if (TextUtils.isEmpty(intent.getPackage())) {
+ throw new IllegalArgumentException("Must specify package name to notify.");
+ }
+ switch (intent.getAction()) {
+ case TvContract.ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED:
+ if (intent.getLongExtra(TvContract.EXTRA_PREVIEW_PROGRAM_ID, -1) < 0) {
+ throw new IllegalArgumentException("Invalid preview program ID.");
+ }
+ break;
+ case TvContract.ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED:
+ if (intent.getLongExtra(TvContract.EXTRA_WATCH_NEXT_PROGRAM_ID, -1) < 0) {
+ throw new IllegalArgumentException("Invalid watch next program ID.");
+ }
+ break;
+ case TvContract.ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT:
+ if (intent.getLongExtra(TvContract.EXTRA_PREVIEW_PROGRAM_ID, -1) < 0) {
+ throw new IllegalArgumentException("Invalid preview program ID.");
+ }
+ if (intent.getLongExtra(TvContract.EXTRA_WATCH_NEXT_PROGRAM_ID, -1) < 0) {
+ throw new IllegalArgumentException("Invalid watch next program ID.");
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid TV input notifying action: "
+ + intent.getAction());
+ }
+ final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, "sendTvInputNotifyIntent");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ getContext().sendBroadcastAsUser(intent, new UserHandle(resolvedUserId));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void registerCallback(final ITvInputManagerCallback callback, int userId) {
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
Binder.getCallingUid(), userId, "registerCallback");
@@ -1910,6 +1954,33 @@
}
@Override
+ public void requestChannelBrowsable(Uri channelUri, int userId)
+ throws RemoteException {
+ final String callingPackageName = getCallingPackageName();
+ final long identity = Binder.clearCallingIdentity();
+ final int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+ userId, "requestChannelBrowsable");
+ try {
+ Intent intent = new Intent(TvContract.ACTION_CHANNEL_BROWSABLE_REQUESTED);
+ List<ResolveInfo> list = getContext().getPackageManager()
+ .queryBroadcastReceivers(intent, 0);
+ if (list != null) {
+ for (ResolveInfo info : list) {
+ String receiverPackageName = info.activityInfo.packageName;
+ intent.putExtra(TvContract.EXTRA_CHANNEL_ID, ContentUris.parseId(
+ channelUri));
+ intent.putExtra(TvContract.EXTRA_PACKAGE_NAME, callingPackageName);
+ intent.setPackage(receiverPackageName);
+ getContext().sendBroadcastAsUser(intent, new UserHandle(resolvedUserId));
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
@SuppressWarnings("resource")
protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index a39131c..bde2111 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -449,7 +449,8 @@
public boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
- IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning) {
+ IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
+ boolean allowTaskSnapshot) {
synchronized(mWindowMap) {
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "setAppStartingWindow: token=" + mToken
+ " pkg=" + pkg + " transferFrom=" + transferFrom);
@@ -469,7 +470,8 @@
return false;
}
- final int type = getStartingWindowType(newTask, taskSwitch, processRunning);
+ final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
+ allowTaskSnapshot);
if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
return createSnapshot();
@@ -539,10 +541,11 @@
return true;
}
- private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning) {
+ private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
+ boolean allowTaskSnapshot) {
if (newTask || !processRunning) {
return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
- } else if (taskSwitch) {
+ } else if (taskSwitch && allowTaskSnapshot) {
return STARTING_WINDOW_TYPE_SNAPSHOT;
} else {
return STARTING_WINDOW_TYPE_NONE;
@@ -566,7 +569,7 @@
return false;
}
- mContainer.startingData = new SnapshotStartingData(mService, snapshot.getSnapshot());
+ mContainer.startingData = new SnapshotStartingData(mService, snapshot);
scheduleAddStartingWindow();
return true;
}
@@ -612,13 +615,13 @@
}
}
- public void notifyAppResumed(boolean wasStopped, boolean allowSavedSurface) {
+ public void notifyAppResumed(boolean wasStopped) {
synchronized(mWindowMap) {
if (mContainer == null) {
Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + mToken);
return;
}
- mContainer.notifyAppResumed(wasStopped, allowSavedSurface);
+ mContainer.notifyAppResumed(wasStopped);
}
}
@@ -712,6 +715,10 @@
@Override
public String toString() {
- return "{AppWindowContainerController token=" + mToken + "}";
+ return "AppWindowContainerController{"
+ + " token=" + mToken
+ + " mContainer=" + mContainer
+ + " mListener=" + mListener
+ + "}";
}
}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index a8664a5..1fb34eb 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -582,16 +582,13 @@
* Notify that the app is now resumed, and it was not stopped before, perform a clean
* up of the surfaces
*/
- void notifyAppResumed(boolean wasStopped, boolean allowSavedSurface) {
+ void notifyAppResumed(boolean wasStopped) {
if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppResumed: wasStopped=" + wasStopped
- + " allowSavedSurface=" + allowSavedSurface + " " + this);
+ + " " + this);
mAppStopped = false;
if (!wasStopped) {
destroySurfaces(true /*cleanupOnResume*/);
}
- if (!allowSavedSurface) {
- destroySavedSurfaces();
- }
}
/**
@@ -1553,6 +1550,9 @@
if (mPendingRelaunchCount != 0) {
pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
}
+ if (getController() != null) {
+ pw.print(prefix); pw.print("controller="); pw.println(getController());
+ }
}
@Override
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 2811145..f41eed5 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -33,6 +33,8 @@
import android.view.animation.Interpolator;
import android.view.WindowManagerInternal;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* Enables animating bounds of objects.
*
@@ -103,7 +105,8 @@
com.android.internal.R.interpolator.fast_out_slow_in);
}
- private final class BoundsAnimator extends ValueAnimator
+ @VisibleForTesting
+ final class BoundsAnimator extends ValueAnimator
implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener {
private final AnimateBoundsUser mTarget;
private final Rect mFrom = new Rect();
@@ -113,10 +116,12 @@
private final boolean mMoveToFullScreen;
// True if this this animation was cancelled and will be replaced the another animation from
// the same {@link #AnimateBoundsUser} target.
- private boolean mSkipAnimationEnd;
+ private boolean mSkipFinalResize;
// True if this animation replaced a previous animation of the same
// {@link #AnimateBoundsUser} target.
private final boolean mSkipAnimationStart;
+ // True if this animation was cancelled by the user, not as a part of a replacing animation
+ private boolean mSkipAnimationEnd;
// True if this animation is not replacing a previous animation, or if the previous
// animation is animating to a different fullscreen state than the current animation.
// We use this to ensure that we always provide a consistent set/order of callbacks when we
@@ -200,7 +205,11 @@
// Whoops, the target doesn't feel like animating anymore. Let's immediately finish
// any further animation.
if (DEBUG) Slog.d(TAG, "animateUpdate: cancelled");
- animation.cancel();
+
+ // Since we are cancelling immediately without a replacement animation, send the
+ // animation end to maintain callback parity, but also skip any further resizes
+ prepareCancel(false /* skipAnimationEnd */, true /* skipFinalResize */);
+ cancel();
}
}
@@ -208,7 +217,7 @@
public void onAnimationEnd(Animator animation) {
if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget
+ " mMoveToFullScreen=" + mMoveToFullScreen
- + " mSkipAnimationEnd=" + mSkipAnimationEnd
+ + " mSkipFinalResize=" + mSkipFinalResize
+ " mFinishAnimationAfterTransition=" + mFinishAnimationAfterTransition
+ " mAppTransitionIsRunning=" + mAppTransition.isRunning());
@@ -222,10 +231,15 @@
return;
}
+ if (!mSkipFinalResize) {
+ // If not cancelled, resize the pinned stack to the final size. All calls to
+ // setPinnedStackSize() must be done between onAnimationStart() and onAnimationEnd()
+ mTarget.setPinnedStackSize(mTo, null);
+ }
+
finishAnimation();
- mTarget.setPinnedStackSize(mTo, null);
- if (mMoveToFullScreen && !mSkipAnimationEnd) {
+ if (mMoveToFullScreen && !mSkipFinalResize) {
mTarget.moveToFullscreen();
}
}
@@ -235,10 +249,16 @@
finishAnimation();
}
+ public void prepareCancel(boolean skipAnimationEnd, boolean skipFinalResize) {
+ if (DEBUG) Slog.d(TAG, "prepareCancel: skipAnimationEnd=" + skipAnimationEnd
+ + " skipFinalResize=" + skipFinalResize);
+ mSkipAnimationEnd = skipAnimationEnd;
+ mSkipFinalResize = skipFinalResize;
+ }
+
@Override
public void cancel() {
- mSkipAnimationEnd = true;
- if (DEBUG) Slog.d(TAG, "cancel: willReplace mTarget=" + mTarget);
+ if (DEBUG) Slog.d(TAG, "cancel: mTarget=" + mTarget);
super.cancel();
}
@@ -273,19 +293,15 @@
public interface AnimateBoundsUser {
/**
- * Asks the target to directly (without any intermediate steps, like scheduling animation)
- * resize its bounds.
- *
- * @return Whether the target still wants to be animated and successfully finished the
- * operation. If it returns false, the animation will immediately be cancelled. The target
- * should return false when something abnormal happened, e.g. it was completely removed
- * from the hierarchy and is not valid anymore.
- */
- boolean setSize(Rect bounds);
- /**
- * Behaves as setSize, but freezes the bounds of any tasks in the target at taskBounds,
+ * Sets the size of the target (without any intermediate steps, like scheduling animation)
+ * but freezes the bounds of any tasks in the target at taskBounds,
* to allow for more flexibility during resizing. Only works for the pinned stack at the
* moment.
+ *
+ * @return Whether the target should continue to be animated and this call was successful.
+ * If false, the animation will be cancelled because the user has determined that the
+ * animation is now invalid and not required. In such a case, the cancel will trigger the
+ * animation end callback as well, but will not send any further size changes.
*/
boolean setPinnedStackSize(Rect bounds, Rect taskBounds);
@@ -310,11 +326,20 @@
*/
void onAnimationEnd();
+ /**
+ * Callback for the target to inform it to reparent to the fullscreen stack.
+ */
void moveToFullscreen();
}
- void animateBounds(final AnimateBoundsUser target, Rect from, Rect to, int animationDuration,
- boolean moveToFullscreen) {
+ public void animateBounds(final AnimateBoundsUser target, Rect from, Rect to,
+ int animationDuration, boolean moveToFullscreen) {
+ animateBoundsImpl(target, from, to, animationDuration, moveToFullscreen);
+ }
+
+ @VisibleForTesting
+ BoundsAnimator animateBoundsImpl(final AnimateBoundsUser target, Rect from, Rect to,
+ int animationDuration, boolean moveToFullscreen) {
final BoundsAnimator existing = mRunningAnimations.get(target);
final boolean replacing = existing != null;
final boolean animatingToNewFullscreenState = (existing == null) ||
@@ -326,12 +351,15 @@
if (replacing) {
if (existing.isAnimatingTo(to)) {
- // Just les the current animation complete if it has the same destination as the
+ // Just let the current animation complete if it has the same destination as the
// one we are trying to start.
if (DEBUG) Slog.d(TAG, "animateBounds: same destination as existing=" + existing
+ " ignoring...");
- return;
+ return existing;
}
+ // Since we are replacing, we skip both animation start and end callbacks, and don't
+ // animate to the final bounds when cancelling
+ existing.prepareCancel(true /* skipAnimationEnd */, true /* skipFinalResize */);
existing.cancel();
}
final BoundsAnimator animator = new BoundsAnimator(target, from, to, moveToFullscreen,
@@ -342,5 +370,6 @@
: DEFAULT_TRANSITION_DURATION) * DEBUG_ANIMATION_SLOW_DOWN_FACTOR);
animator.setInterpolator(mFastOutSlowInInterpolator);
animator.start();
+ return animator;
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 23058bd..058fdae 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1420,6 +1420,13 @@
changedStackList.add(stack.mStackId);
}
}
+
+ // If there was no pinned stack, we still need to notify the controller of the display info
+ // update as a result of the config change. We do this here to consolidate the flow between
+ // changes when there is and is not a stack.
+ if (getStackById(PINNED_STACK_ID) == null) {
+ mPinnedStackControllerLocked.onDisplayInfoChanged();
+ }
}
@Override
@@ -2921,7 +2928,11 @@
if (stack != null) {
stack.getBounds(frame);
}
- } else if (!mutableIncludeFullDisplay.value && !w.mIsWallpaper) {
+
+ // We want to screenshot with the exact bounds of the surface of the app. Thus,
+ // intersect it with the frame.
+ frame.intersect(w.mFrame);
+ }else if (!mutableIncludeFullDisplay.value && !w.mIsWallpaper) {
final Rect wf = w.mFrame;
final Rect cr = w.mContentInsets;
int left = wf.left + cr.left;
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 3ce61f0..1684878 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -147,7 +147,6 @@
void onConfigurationChanged() {
reloadResources();
- notifyMovementBoundsChanged(false /* fromImeAdjustment */);
}
/**
@@ -241,13 +240,31 @@
}
/**
+ * In the case where the display rotation is changed but there is no stack, we can't depend on
+ * onTaskStackBoundsChanged() to be called. But we still should update our known display info
+ * with the new state so that we can update SystemUI.
+ */
+ synchronized void onDisplayInfoChanged() {
+ mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
+ notifyMovementBoundsChanged(false /* fromImeAdjustment */);
+ }
+
+ /**
* Updates the display info, calculating and returning the new stack and movement bounds in the
* new orientation of the device if necessary.
*/
- void onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
+ boolean onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
if (mDisplayInfo.equals(displayInfo)) {
- return;
+ // We are already in the right orientation, ignore
+ outBounds.setEmpty();
+ return false;
+ } else if (targetBounds.isEmpty()) {
+ // The stack is null, we are just initializing the stack, so just store the display info
+ // and ignore
+ mDisplayInfo.copyFrom(displayInfo);
+ outBounds.setEmpty();
+ return false;
}
mTmpRect.set(targetBounds);
@@ -272,6 +289,7 @@
notifyMovementBoundsChanged(false /* fromImeAdjustment */);
outBounds.set(postChangeStackBounds);
+ return true;
}
/**
@@ -371,7 +389,7 @@
final Rect animatingBounds = mTmpAnimatingBoundsRect;
final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID);
if (pinnedStack != null) {
- pinnedStack.getAnimatingBounds(animatingBounds);
+ pinnedStack.getAnimationOrCurrentBounds(animatingBounds);
} else {
animatingBounds.set(normalBounds);
}
diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowController.java b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
index 0145454..135832e 100644
--- a/services/core/java/com/android/server/wm/PinnedStackWindowController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
@@ -32,8 +32,8 @@
private Rect mTmpBoundsRect = new Rect();
- public PinnedStackWindowController(int stackId, StackWindowListener listener, int displayId,
- boolean onTop, Rect outBounds) {
+ public PinnedStackWindowController(int stackId, PinnedStackWindowListener listener,
+ int displayId, boolean onTop, Rect outBounds) {
super(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance());
}
@@ -63,7 +63,7 @@
final Rect originalBounds = new Rect();
mContainer.getBounds(originalBounds);
- mContainer.setAnimatingBounds(sourceBounds, toBounds);
+ mContainer.setAnimationFinalBounds(sourceBounds, toBounds);
UiThread.getHandler().post(() -> {
if (mContainer == null) {
return;
@@ -84,9 +84,10 @@
}
final int displayId = mContainer.getDisplayContent().getDisplayId();
- final Rect toBounds = mService.getPictureInPictureBounds(displayId, aspectRatio);
+ final Rect toBounds = mService.getPictureInPictureBounds(displayId, aspectRatio,
+ true /* useExistingStackBounds */);
final Rect targetBounds = new Rect();
- mContainer.getAnimatingBounds(targetBounds);
+ mContainer.getAnimationOrCurrentBounds(targetBounds);
final PinnedStackController pinnedStackController =
mContainer.getDisplayContent().getPinnedStackController();
@@ -117,8 +118,12 @@
/**
* @return whether the bounds are currently animating to fullscreen.
*/
- public boolean isBoundsAnimatingToFullscreen() {
- return mContainer.isBoundsAnimatingToFullscreen();
+ public boolean isAnimatingBoundsToFullscreen() {
+ return mContainer.isAnimatingBoundsToFullscreen();
+ }
+
+ public boolean pinnedStackResizeAllowed() {
+ return mContainer.pinnedStackResizeAllowed();
}
/**
@@ -132,4 +137,16 @@
}
return bounds;
}
+
+ /**
+ * The following calls are made from WM to AM.
+ */
+
+ /** Calls directly into activity manager so window manager lock shouldn't held. */
+ public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {
+ if (mListener != null) {
+ PinnedStackWindowListener listener = (PinnedStackWindowListener) mListener;
+ listener.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowListener.java b/services/core/java/com/android/server/wm/PinnedStackWindowListener.java
new file mode 100644
index 0000000..12b9c1f
--- /dev/null
+++ b/services/core/java/com/android/server/wm/PinnedStackWindowListener.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.graphics.Rect;
+
+/**
+ * Interface used by the creator of {@link PinnedStackWindowController} to listen to changes with
+ * the stack container.
+ */
+public interface PinnedStackWindowListener extends StackWindowListener {
+
+ /**
+ * Called when the stack container pinned stack animation will change the picture-in-picture
+ * mode. This is a direct call into ActivityManager.
+ */
+ default void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {}
+}
diff --git a/services/core/java/com/android/server/wm/SnapshotStartingData.java b/services/core/java/com/android/server/wm/SnapshotStartingData.java
index e73d4d25..35f35db 100644
--- a/services/core/java/com/android/server/wm/SnapshotStartingData.java
+++ b/services/core/java/com/android/server/wm/SnapshotStartingData.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import android.app.ActivityManager.TaskSnapshot;
import android.graphics.GraphicBuffer;
import android.view.WindowManagerPolicy.StartingSurface;
@@ -25,9 +26,9 @@
class SnapshotStartingData extends StartingData {
private final WindowManagerService mService;
- private final GraphicBuffer mSnapshot;
+ private final TaskSnapshot mSnapshot;
- SnapshotStartingData(WindowManagerService service, GraphicBuffer snapshot) {
+ SnapshotStartingData(WindowManagerService service, TaskSnapshot snapshot) {
super(service);
mService = service;
mSnapshot = snapshot;
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index bf024cf..b927e67 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -368,13 +368,6 @@
}
}
- /** Calls directly into activity manager so window manager lock shouldn't held. */
- void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {
- if (mListener != null) {
- mListener.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds);
- }
- }
-
void requestResize(Rect bounds) {
mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
}
diff --git a/services/core/java/com/android/server/wm/StackWindowListener.java b/services/core/java/com/android/server/wm/StackWindowListener.java
index a55f9df..c763c17 100644
--- a/services/core/java/com/android/server/wm/StackWindowListener.java
+++ b/services/core/java/com/android/server/wm/StackWindowListener.java
@@ -26,10 +26,4 @@
/** Called when the stack container would like its controller to resize. */
void requestResize(Rect bounds);
-
- /**
- * Called when the stack container pinned stack animation will change the picture-in-picture
- * mode. This is a direct call into ActivityManager.
- */
- default void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 3ffb093..4262d12 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -17,15 +17,14 @@
package com.android.server.wm;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static com.android.server.EventLogTags.WM_TASK_REMOVED;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -40,7 +39,6 @@
import android.view.Surface;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.EventLogTags;
import java.io.PrintWriter;
@@ -186,7 +184,7 @@
super.removeImmediately();
}
- void reparent(TaskStack stack, int position) {
+ void reparent(TaskStack stack, int position, boolean moveParents) {
if (stack == mStack) {
throw new IllegalArgumentException(
"task=" + this + " already child of stack=" + mStack);
@@ -197,7 +195,7 @@
final DisplayContent prevDisplayContent = getDisplayContent();
getParent().removeChild(this);
- stack.addTask(this, position, showForAllUsers(), false /* moveParents */);
+ stack.addTask(this, position, showForAllUsers(), moveParents);
// Relayout display(s).
final DisplayContent displayContent = stack.getDisplayContent();
@@ -597,8 +595,7 @@
* we will have a jump at the end.
*/
boolean isFloating() {
- return StackId.tasksAreFloating(mStack.mStackId)
- && !mStack.isBoundsAnimatingToFullscreen();
+ return StackId.tasksAreFloating(mStack.mStackId) && !mStack.isAnimatingBoundsToFullscreen();
}
WindowState getTopVisibleAppMainWindow() {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotCache.java b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
index 1ec0201..7bf4edb 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotCache.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
@@ -32,15 +32,10 @@
*/
class TaskSnapshotCache {
- // TODO: Make this more dynamic to accomodate for different clients.
- private static final int RETRIEVAL_CACHE_SIZE = 4;
-
private final WindowManagerService mService;
private final TaskSnapshotLoader mLoader;
private final ArrayMap<AppWindowToken, Integer> mAppTaskMap = new ArrayMap<>();
private final ArrayMap<Integer, CacheEntry> mRunningCache = new ArrayMap<>();
- private final LruCache<Integer, TaskSnapshot> mRetrievalCache =
- new LruCache<>(RETRIEVAL_CACHE_SIZE);
TaskSnapshotCache(WindowManagerService service, TaskSnapshotLoader loader) {
mService = service;
@@ -55,7 +50,6 @@
final AppWindowToken top = task.getTopChild();
mAppTaskMap.put(top, task.mTaskId);
mRunningCache.put(task.mTaskId, new CacheEntry(snapshot, task.getTopChild()));
- mRetrievalCache.put(task.mTaskId, snapshot);
}
/**
@@ -70,12 +64,6 @@
if (entry != null) {
return entry.snapshot;
}
-
- // Try the retrieval cache.
- final TaskSnapshot snapshot = mRetrievalCache.get(taskId);
- if (snapshot != null) {
- return snapshot;
- }
}
// Try to restore from disk if asked.
@@ -93,13 +81,6 @@
if (snapshot == null) {
return null;
}
-
- // Only cache non-reduced snapshots.
- if (!reducedResolution) {
- synchronized (mService.mWindowMap) {
- mRetrievalCache.put(taskId, snapshot);
- }
- }
return snapshot;
}
@@ -111,9 +92,6 @@
if (taskId != null) {
removeRunningEntry(taskId);
}
- if (wtoken.getTask() != null) {
- mRetrievalCache.remove(wtoken.getTask().mTaskId);
- }
}
/**
@@ -128,7 +106,6 @@
void onTaskRemoved(int taskId) {
removeRunningEntry(taskId);
- mRetrievalCache.remove(taskId);
}
private void removeRunningEntry(int taskId) {
@@ -142,20 +119,12 @@
void dump(PrintWriter pw, String prefix) {
final String doublePrefix = prefix + " ";
final String triplePrefix = doublePrefix + " ";
- final String quadruplePrefix = triplePrefix + " ";
pw.println(prefix + "SnapshotCache");
- pw.println(doublePrefix + "RunningCache");
for (int i = mRunningCache.size() - 1; i >= 0; i--) {
final CacheEntry entry = mRunningCache.valueAt(i);
- pw.println(triplePrefix + "Entry taskId=" + mRunningCache.keyAt(i));
- pw.println(quadruplePrefix + "topApp=" + entry.topApp);
- pw.println(quadruplePrefix + "snapshot=" + entry.snapshot);
- }
- pw.println(doublePrefix + "RetrievalCache");
- final Map<Integer, TaskSnapshot> retrievalSnapshot = mRetrievalCache.snapshot();
- for (Entry<Integer, TaskSnapshot> entry : retrievalSnapshot.entrySet()) {
- pw.println(triplePrefix + "Entry taskId=" + entry.getKey());
- pw.println(quadruplePrefix + "snapshot=" + entry.getValue());
+ pw.println(doublePrefix + "Entry taskId=" + mRunningCache.keyAt(i));
+ pw.println(triplePrefix + "topApp=" + entry.topApp);
+ pw.println(triplePrefix + "snapshot=" + entry.snapshot);
}
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index b8d0b8c..fbb826d 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -28,6 +28,7 @@
import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Canvas;
import android.graphics.GraphicBuffer;
+import android.graphics.Rect;
import android.os.Environment;
import android.util.ArraySet;
import android.view.WindowManagerPolicy.StartingSurface;
@@ -152,7 +153,7 @@
* MANAGER LOCK WHEN CALLING THIS METHOD!
*/
StartingSurface createStartingSurface(AppWindowToken token,
- GraphicBuffer snapshot) {
+ TaskSnapshot snapshot) {
return TaskSnapshotSurface.create(mService, token, snapshot);
}
@@ -161,13 +162,25 @@
if (top == null) {
return null;
}
+ final WindowState mainWindow = top.findMainWindow();
+ if (mainWindow == null) {
+ return null;
+ }
final GraphicBuffer buffer = top.mDisplayContent.screenshotApplicationsToBuffer(top.token,
-1, -1, false, 1.0f, false, true);
if (buffer == null) {
return null;
}
return new TaskSnapshot(buffer, top.getConfiguration().orientation,
- top.findMainWindow().mStableInsets, false /* reduced */, 1f /* scale */);
+ minRect(mainWindow.mContentInsets, mainWindow.mStableInsets), false /* reduced */,
+ 1f /* scale */);
+ }
+
+ private Rect minRect(Rect rect1, Rect rect2) {
+ return new Rect(Math.min(rect1.left, rect2.left),
+ Math.min(rect1.top, rect2.top),
+ Math.min(rect1.right, rect2.right),
+ Math.min(rect1.bottom, rect2.bottom));
}
/**
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 04403e2..c816ba3 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -16,20 +16,35 @@
package com.android.server.wm;
-import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+import static android.graphics.Color.WHITE;
+import static android.graphics.Color.alpha;
+import static android.view.SurfaceControl.HIDDEN;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+import static android.view.WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
+import static android.view.WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
+import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
+import static com.android.internal.policy.DecorView.getColorViewLeftInset;
+import static com.android.internal.policy.DecorView.getColorViewTopInset;
+import static com.android.internal.policy.DecorView.getNavigationBarRect;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.app.ActivityManager.TaskDescription;
-import android.graphics.Bitmap;
+import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.GraphicBuffer;
import android.graphics.Paint;
import android.graphics.Rect;
@@ -37,17 +52,22 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.util.MergedConfiguration;
import android.util.Slog;
import android.view.IWindowSession;
import android.view.Surface;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicy.StartingSurface;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.DecorView;
import com.android.internal.view.BaseIWindow;
/**
@@ -57,19 +77,57 @@
*/
class TaskSnapshotSurface implements StartingSurface {
+ private static final long SIZE_MISMATCH_MINIMUM_TIME_MS = 450;
+
+ /**
+ * When creating the starting window, we use the exact same layout flags such that we end up
+ * with a window with the exact same dimensions etc. However, these flags are not used in layout
+ * and might cause other side effects so we exclude them.
+ */
+ private static final int FLAG_INHERIT_EXCLUDES = FLAG_NOT_FOCUSABLE
+ | FLAG_NOT_TOUCHABLE
+ | FLAG_NOT_TOUCH_MODAL
+ | FLAG_ALT_FOCUSABLE_IM
+ | FLAG_NOT_FOCUSABLE
+ | FLAG_HARDWARE_ACCELERATED
+ | FLAG_IGNORE_CHEEK_PRESSES
+ | FLAG_LOCAL_FOCUS_MODE
+ | FLAG_SLIPPERY
+ | FLAG_WATCH_OUTSIDE_TOUCH
+ | FLAG_SPLIT_TOUCH
+ | FLAG_SCALED
+ | FLAG_SECURE;
+
private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
private static final int MSG_REPORT_DRAW = 0;
private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
private final Window mWindow;
private final Surface mSurface;
+ private SurfaceControl mChildSurfaceControl;
private final IWindowSession mSession;
private final WindowManagerService mService;
+ private final Rect mTaskBounds;
+ private final Rect mStableInsets = new Rect();
+ private final Rect mContentInsets = new Rect();
+ private final Rect mFrame = new Rect();
+ private final TaskSnapshot mSnapshot;
+ private final CharSequence mTitle;
private boolean mHasDrawn;
private boolean mReportNextDraw;
- private Paint mFillBackgroundPaint = new Paint();
+ private long mShownTime;
+ private final Handler mHandler;
+ private boolean mSizeMismatch;
+ private final Paint mBackgroundPaint = new Paint();
+ private final Paint mStatusBarPaint = new Paint();
+ private final Paint mNavigationBarPaint = new Paint();
+ private final int mStatusBarColor;
+ private final int mNavigationBarColor;
+ private final int mSysUiVis;
+ private final int mWindowFlags;
+ private final int mWindowPrivateFlags;
static TaskSnapshotSurface create(WindowManagerService service, AppWindowToken token,
- GraphicBuffer snapshot) {
+ TaskSnapshot snapshot) {
final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
final Window window = new Window();
@@ -78,32 +136,51 @@
final Surface surface = new Surface();
final Rect tmpRect = new Rect();
final Rect tmpFrame = new Rect();
+ final Rect taskBounds;
+ final Rect tmpContentInsets = new Rect();
+ final Rect tmpStableInsets = new Rect();
final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
- int fillBackgroundColor = Color.WHITE;
+ int backgroundColor = WHITE;
+ int statusBarColor = 0;
+ int navigationBarColor = 0;
+ final int sysUiVis;
+ final int windowFlags;
+ final int windowPrivateFlags;
synchronized (service.mWindowMap) {
+ final WindowState mainWindow = token.findMainWindow();
+ if (mainWindow == null) {
+ Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for token="
+ + token);
+ return null;
+ }
+ sysUiVis = mainWindow.getSystemUiVisibility();
+ windowFlags = mainWindow.getAttrs().flags;
+ windowPrivateFlags = mainWindow.getAttrs().privateFlags;
+
layoutParams.type = TYPE_APPLICATION_STARTING;
- layoutParams.format = snapshot.getFormat();
- layoutParams.flags = FLAG_LAYOUT_INSET_DECOR
- | FLAG_LAYOUT_IN_SCREEN
+ layoutParams.format = snapshot.getSnapshot().getFormat();
+ layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
| FLAG_NOT_FOCUSABLE
- | FLAG_NOT_TOUCHABLE
- | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+ | FLAG_NOT_TOUCHABLE;
layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT;
layoutParams.token = token.token;
layoutParams.width = LayoutParams.MATCH_PARENT;
layoutParams.height = LayoutParams.MATCH_PARENT;
-
- // TODO: Inherit behavior whether to draw behind status bar/nav bar.
- layoutParams.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ layoutParams.systemUiVisibility = sysUiVis;
final Task task = token.getTask();
if (task != null) {
- layoutParams.setTitle(String.format(TITLE_FORMAT,task.mTaskId));
+ layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
final TaskDescription taskDescription = task.getTaskDescription();
if (taskDescription != null) {
- fillBackgroundColor = taskDescription.getBackgroundColor();
+ backgroundColor = taskDescription.getBackgroundColor();
+ statusBarColor = taskDescription.getStatusBarColor();
+ navigationBarColor = taskDescription.getNavigationBarColor();
}
+ taskBounds = new Rect();
+ task.getBounds(taskBounds);
+ } else {
+ taskBounds = null;
}
}
try {
@@ -118,31 +195,55 @@
// Local call.
}
final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window,
- surface, fillBackgroundColor);
+ surface, snapshot, layoutParams.getTitle(), backgroundColor, statusBarColor,
+ navigationBarColor, sysUiVis, windowFlags, windowPrivateFlags, taskBounds);
window.setOuter(snapshotSurface);
try {
session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, tmpFrame,
- tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpRect, tmpMergedConfiguration,
- surface);
+ tmpRect, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect, tmpRect,
+ tmpMergedConfiguration, surface);
} catch (RemoteException e) {
// Local call.
}
- snapshotSurface.drawSnapshot(snapshot);
+ snapshotSurface.setFrames(tmpFrame, tmpContentInsets, tmpStableInsets);
+ snapshotSurface.drawSnapshot();
return snapshotSurface;
}
@VisibleForTesting
TaskSnapshotSurface(WindowManagerService service, Window window, Surface surface,
- int fillBackgroundColor) {
+ TaskSnapshot snapshot, CharSequence title, int backgroundColor, int statusBarColor,
+ int navigationBarColor, int sysUiVis, int windowFlags, int windowPrivateFlags,
+ Rect taskBounds) {
mService = service;
+ mHandler = new Handler(mService.mH.getLooper());
mSession = WindowManagerGlobal.getWindowSession();
mWindow = window;
mSurface = surface;
- mFillBackgroundPaint.setColor(fillBackgroundColor);
+ mSnapshot = snapshot;
+ mTitle = title;
+ mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
+ mTaskBounds = taskBounds;
+ mSysUiVis = sysUiVis;
+ mWindowFlags = windowFlags;
+ mWindowPrivateFlags = windowPrivateFlags;
+ mStatusBarColor = DecorView.calculateStatusBarColor(windowFlags,
+ service.mContext.getColor(R.color.system_bar_background_semi_transparent),
+ statusBarColor);
+ mNavigationBarColor = navigationBarColor;
+ mStatusBarPaint.setColor(mStatusBarColor);
+ mNavigationBarPaint.setColor(navigationBarColor);
}
@Override
public void remove() {
+ synchronized (mService.mWindowMap) {
+ final long now = SystemClock.uptimeMillis();
+ if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS) {
+ mHandler.postAtTime(this::remove, mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS);
+ return;
+ }
+ }
try {
mSession.remove(mWindow);
} catch (RemoteException e) {
@@ -150,31 +251,151 @@
}
}
- private void drawSnapshot(GraphicBuffer snapshot) {
- mSurface.attachAndQueueBuffer(snapshot);
+ @VisibleForTesting
+ void setFrames(Rect frame, Rect contentInsets, Rect stableInsets) {
+ mFrame.set(frame);
+ mContentInsets.set(contentInsets);
+ mStableInsets.set(stableInsets);
+ mSizeMismatch = (mFrame.width() != mSnapshot.getSnapshot().getWidth()
+ || mFrame.height() != mSnapshot.getSnapshot().getHeight());
+ }
+
+ private void drawSnapshot() {
+ final GraphicBuffer buffer = mSnapshot.getSnapshot();
+ if (mSizeMismatch) {
+ // The dimensions of the buffer and the window don't match, so attaching the buffer
+ // will fail. Better create a child window with the exact dimensions and fill the parent
+ // window with the background color!
+ drawSizeMismatchSnapshot(buffer);
+ } else {
+ drawSizeMatchSnapshot(buffer);
+ }
final boolean reportNextDraw;
synchronized (mService.mWindowMap) {
+ mShownTime = SystemClock.uptimeMillis();
mHasDrawn = true;
reportNextDraw = mReportNextDraw;
}
if (reportNextDraw) {
reportDrawn();
}
+ }
+
+ private void drawSizeMatchSnapshot(GraphicBuffer buffer) {
+ mSurface.attachAndQueueBuffer(buffer);
+ mSurface.release();
+ }
+
+ private void drawSizeMismatchSnapshot(GraphicBuffer buffer) {
+ final SurfaceSession session = new SurfaceSession(mSurface);
+
+ // Keep a reference to it such that it doesn't get destroyed when finalized.
+ mChildSurfaceControl = new SurfaceControl(session,
+ mTitle + " - task-snapshot-surface",
+ buffer.getWidth(), buffer.getHeight(), buffer.getFormat(), HIDDEN);
+ Surface surface = new Surface();
+ surface.copyFrom(mChildSurfaceControl);
+
+ // Clip off ugly navigation bar.
+ final Rect crop = calculateSnapshotCrop();
+ final Rect frame = calculateSnapshotFrame(crop);
+ SurfaceControl.openTransaction();
+ try {
+ // We can just show the surface here as it will still be hidden as the parent is
+ // still hidden.
+ mChildSurfaceControl.show();
+ mChildSurfaceControl.setWindowCrop(crop);
+ mChildSurfaceControl.setPosition(frame.left, frame.top);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ surface.attachAndQueueBuffer(buffer);
+ surface.release();
+
+ final Canvas c = mSurface.lockCanvas(null);
+ drawBackgroundAndBars(c, frame);
+ mSurface.unlockCanvasAndPost(c);
mSurface.release();
}
@VisibleForTesting
- void fillEmptyBackground(Canvas c, Bitmap b) {
- final boolean fillHorizontally = c.getWidth() > b.getWidth();
- final boolean fillVertically = c.getHeight() > b.getHeight();
+ Rect calculateSnapshotCrop() {
+ final Rect rect = new Rect();
+ rect.set(0, 0, mSnapshot.getSnapshot().getWidth(), mSnapshot.getSnapshot().getHeight());
+ final Rect insets = mSnapshot.getContentInsets();
+
+ // Let's remove all system decorations except the status bar, but only if the task is at the
+ // very top of the screen.
+ rect.inset(insets.left, mTaskBounds.top != 0 ? insets.top : 0, insets.right, insets.bottom);
+ return rect;
+ }
+
+ @VisibleForTesting
+ Rect calculateSnapshotFrame(Rect crop) {
+ final Rect frame = new Rect(crop);
+
+ // By default, offset it to to top/left corner
+ frame.offsetTo(-crop.left, -crop.top);
+
+ // However, we also need to make space for the navigation bar on the left side.
+ final int colorViewLeftInset = getColorViewLeftInset(mStableInsets.left,
+ mContentInsets.left);
+ frame.offset(colorViewLeftInset, 0);
+ return frame;
+ }
+
+ @VisibleForTesting
+ void drawBackgroundAndBars(Canvas c, Rect frame) {
+ final int statusBarHeight = getStatusBarColorViewHeight();
+ final boolean fillHorizontally = c.getWidth() > frame.right;
+ final boolean fillVertically = c.getHeight() > frame.bottom;
if (fillHorizontally) {
- c.drawRect(b.getWidth(), 0, c.getWidth(), fillVertically
- ? b.getHeight()
- : c.getHeight(),
- mFillBackgroundPaint);
+ c.drawRect(frame.right, alpha(mStatusBarColor) == 0xFF ? statusBarHeight : 0,
+ c.getWidth(), fillVertically
+ ? frame.bottom
+ : c.getHeight(),
+ mBackgroundPaint);
}
if (fillVertically) {
- c.drawRect(0, b.getHeight(), c.getWidth(), c.getHeight(), mFillBackgroundPaint);
+ c.drawRect(0, frame.bottom, c.getWidth(), c.getHeight(), mBackgroundPaint);
+ }
+ drawStatusBarBackground(c, frame, statusBarHeight);
+ drawNavigationBarBackground(c);
+ }
+
+ private int getStatusBarColorViewHeight() {
+ final boolean forceStatusBarBackground =
+ (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
+ if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mSysUiVis, mStatusBarColor, mWindowFlags, forceStatusBarBackground)) {
+ return getColorViewTopInset(mStableInsets.top, mContentInsets.top);
+ } else {
+ return 0;
+ }
+ }
+
+ private boolean isNavigationBarColorViewVisible() {
+ return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mSysUiVis, mNavigationBarColor, mWindowFlags, false /* force */);
+ }
+
+ @VisibleForTesting
+ void drawStatusBarBackground(Canvas c, Rect frame, int statusBarHeight) {
+ if (statusBarHeight > 0 && c.getWidth() > frame.right) {
+ final int rightInset = DecorView.getColorViewRightInset(mStableInsets.right,
+ mContentInsets.right);
+ c.drawRect(frame.right, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
+ }
+ }
+
+ @VisibleForTesting
+ void drawNavigationBarBackground(Canvas c) {
+ final Rect navigationBarRect = new Rect();
+ getNavigationBarRect(c.getWidth(), c.getHeight(), mStableInsets, mContentInsets,
+ navigationBarRect);
+ final boolean visible = isNavigationBarColorViewVisible();
+ if (visible && !navigationBarRect.isEmpty()) {
+ c.drawRect(navigationBarRect, mNavigationBarPaint);
}
}
@@ -211,10 +432,10 @@
}
};
- private static class Window extends BaseIWindow {
+ @VisibleForTesting
+ static class Window extends BaseIWindow {
private TaskSnapshotSurface mOuter;
-
public void setOuter(TaskSnapshotSurface outer) {
mOuter = outer;
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 1a67ac7..d7c41d3 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -77,6 +77,7 @@
/** For comparison with DisplayContent bounds. */
private Rect mTmpRect = new Rect();
private Rect mTmpRect2 = new Rect();
+ private Rect mTmpRect3 = new Rect();
/** Content limits relative to the DisplayContent this sits in. */
private Rect mBounds = new Rect();
@@ -125,7 +126,11 @@
// perfectly fit the region it would have been cropped to. We may also avoid certain logic we
// would otherwise apply while resizing, while resizing in the bounds animating mode.
private boolean mBoundsAnimating = false;
+ // Set when an animation has been requested but has not yet started from the UI thread. This is
+ // cleared when the animation actually starts.
+ private boolean mBoundsAnimatingRequested = false;
private boolean mBoundsAnimatingToFullscreen = false;
+ private boolean mCancelCurrentBoundsAnimation = false;
private Rect mBoundsAnimationTarget = new Rect();
private Rect mBoundsAnimationSourceBounds = new Rect();
@@ -262,12 +267,6 @@
if (mDisplayContent != null) {
mDisplayContent.mDimLayerController.updateDimLayer(this);
- if (mStackId == PINNED_STACK_ID) {
- // Update the bounds based on any changes to the display info
- getAnimatingBounds(mTmpRect2);
- mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(mTmpRect2,
- bounds);
- }
mAnimationBackgroundSurface.setBounds(bounds);
}
@@ -320,10 +319,11 @@
}
/**
- * Sets the bounds animation target bounds. This can't currently be done in onAnimationStart()
- * since that is started on the UiThread.
+ * Sets the bounds animation target bounds ahead of an animation. This can't currently be done
+ * in onAnimationStart() since that is started on the UiThread.
*/
- void setAnimatingBounds(Rect sourceBounds, Rect destBounds) {
+ void setAnimationFinalBounds(Rect sourceBounds, Rect destBounds) {
+ mBoundsAnimatingRequested = true;
if (sourceBounds != null) {
mBoundsAnimationSourceBounds.set(sourceBounds);
} else {
@@ -337,23 +337,26 @@
}
/**
- * @return the source bounds for the bounds animation.
+ * @return the final bounds for the bounds animation.
*/
- void getAnimatingSourceBounds(Rect outBounds) {
- if (!mBoundsAnimationSourceBounds.isEmpty()) {
- outBounds.set(mBoundsAnimationSourceBounds);
- return;
- }
- outBounds.setEmpty();
+ void getFinalAnimationBounds(Rect outBounds) {
+ outBounds.set(mBoundsAnimationTarget);
}
/**
- * @return the bounds that the task stack is currently being animated towards, or the current
- * stack bounds if there is no animation in progress.
+ * @return the final source bounds for the bounds animation.
*/
- void getAnimatingBounds(Rect outBounds) {
- if (!mBoundsAnimationTarget.isEmpty()) {
- outBounds.set(mBoundsAnimationTarget);
+ void getFinalAnimationSourceBounds(Rect outBounds) {
+ outBounds.set(mBoundsAnimationSourceBounds);
+ }
+
+ /**
+ * @return the final animation bounds if the task stack is currently being animated, or the
+ * current stack bounds otherwise.
+ */
+ void getAnimationOrCurrentBounds(Rect outBounds) {
+ if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
+ getFinalAnimationBounds(outBounds);
return;
}
getBounds(outBounds);
@@ -398,6 +401,24 @@
// as it's going away soon anyway.
return false;
}
+
+ if (mStackId == PINNED_STACK_ID) {
+ getAnimationOrCurrentBounds(mTmpRect2);
+ boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
+ mTmpRect2, mTmpRect3);
+ if (updated) {
+ mBoundsAfterRotation.set(mTmpRect3);
+
+ // Once we've set the bounds based on the rotation of the old bounds in the new
+ // orientation, clear the animation target bounds since they are obsolete, and
+ // cancel any currently running animations
+ mBoundsAnimationTarget.setEmpty();
+ mBoundsAnimationSourceBounds.setEmpty();
+ mCancelCurrentBoundsAnimation = true;
+ return true;
+ }
+ }
+
final int newRotation = getDisplayInfo().rotation;
final int newDensity = getDisplayInfo().logicalDensityDpi;
@@ -413,20 +434,6 @@
return false;
}
- if (StackId.tasksAreFloating(mStackId)) {
- // Update stack bounds again since the display info has changed since updateDisplayInfo,
- // however, for floating tasks, we don't need to apply the new rotation to the bounds,
- // we can just update and return them here
- setBounds(mBounds);
- mBoundsAfterRotation.set(mBounds);
-
- // Once we've set the bounds based on the rotation of the old bounds in the new
- // orientation, clear the animation target bounds since they are obsolete
- mBoundsAnimationTarget.setEmpty();
- mBoundsAnimationSourceBounds.setEmpty();
- return true;
- }
-
mTmpRect2.set(mBounds);
mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
switch (mStackId) {
@@ -692,6 +699,14 @@
getStackDockedModeBounds(mTmpRect, bounds, mStackId, mTmpRect2,
mDisplayContent.mDividerControllerLocked.getContentWidth(),
dockedOnTopOrLeft);
+ } else if (mStackId == PINNED_STACK_ID) {
+ // Update the bounds based on any changes to the display info
+ getAnimationOrCurrentBounds(mTmpRect2);
+ boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
+ mTmpRect2, mTmpRect3);
+ if (updated) {
+ bounds = new Rect(mTmpRect3);
+ }
}
updateDisplayInfo(bounds);
@@ -1443,21 +1458,11 @@
}
}
- @Override // AnimatesBounds
- public boolean setSize(Rect bounds) {
- synchronized (mService.mWindowMap) {
- if (mDisplayContent == null) {
- return false;
- }
- }
- try {
- mService.mActivityManager.resizeStack(mStackId, bounds, false, true, false, -1);
- } catch (RemoteException e) {
- }
- return true;
- }
-
public boolean setPinnedStackSize(Rect bounds, Rect tempTaskBounds) {
+ if (mCancelCurrentBoundsAnimation) {
+ return false;
+ }
+
try {
mService.mActivityManager.resizePinnedStack(bounds, tempTaskBounds);
} catch (RemoteException e) {
@@ -1469,8 +1474,10 @@
@Override // AnimatesBounds
public void onAnimationStart(boolean toFullscreen) {
synchronized (mService.mWindowMap) {
+ mBoundsAnimatingRequested = false;
mBoundsAnimating = true;
mBoundsAnimatingToFullscreen = toFullscreen;
+ mCancelCurrentBoundsAnimation = false;
}
if (mStackId == PINNED_STACK_ID) {
@@ -1484,7 +1491,8 @@
@Override // AnimatesBounds
public void updatePictureInPictureMode(Rect targetStackBounds) {
- final StackWindowController controller = getController();
+ final PinnedStackWindowController controller =
+ (PinnedStackWindowController) getController();
if (controller != null) {
controller.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds);
}
@@ -1523,14 +1531,21 @@
return mBoundsAnimating;
}
- public boolean getBoundsAnimating() {
+ public boolean isAnimatingBounds() {
return mBoundsAnimating;
}
- public boolean isBoundsAnimatingToFullscreen() {
+ public boolean isAnimatingBoundsToFullscreen() {
return mBoundsAnimating && mBoundsAnimatingToFullscreen;
}
+ public boolean pinnedStackResizeAllowed() {
+ if (mBoundsAnimating && mCancelCurrentBoundsAnimation) {
+ return true;
+ }
+ return false;
+ }
+
/** Returns true if a removal action is still being deferred. */
boolean checkCompleteDeferredRemoval() {
if (isAnimating()) {
diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerController.java b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
index efc2e11..9f02485 100644
--- a/services/core/java/com/android/server/wm/TaskWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
@@ -121,7 +121,7 @@
}
}
- public void reparent(StackWindowController stackController, int position) {
+ public void reparent(StackWindowController stackController, int position, boolean moveParents) {
synchronized (mWindowMap) {
if (DEBUG_STACK) Slog.i(TAG_WM, "reparent: moving taskId=" + mTaskId
+ " to stack=" + stackController + " at " + position);
@@ -135,7 +135,7 @@
throw new IllegalArgumentException("reparent: could not find stack="
+ stackController);
}
- mContainer.reparent(stack, position);
+ mContainer.reparent(stack, position, moveParents);
mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0f4707e..0049585 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -31,7 +31,6 @@
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.THREAD_PRIORITY_DISPLAY;
import static android.os.Process.myPid;
-import static android.os.Process.myTid;
import static android.os.UserHandle.USER_NULL;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.DOCKED_INVALID;
@@ -148,7 +147,6 @@
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
-import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
@@ -2758,7 +2756,12 @@
mDockedStackCreateBounds = bounds;
}
- public Rect getPictureInPictureBounds(int displayId, float aspectRatio) {
+ /**
+ * @param useExistingStackBounds Apply {@param aspectRatio} to the existing target stack bounds
+ * if possible
+ */
+ public Rect getPictureInPictureBounds(int displayId, float aspectRatio,
+ boolean useExistingStackBounds) {
synchronized (mWindowMap) {
if (!mSupportsPictureInPicture) {
return null;
@@ -2773,11 +2776,11 @@
final PinnedStackController pinnedStackController =
displayContent.getPinnedStackController();
final TaskStack stack = displayContent.getStackById(PINNED_STACK_ID);
- if (stack != null) {
+ if (stack != null && useExistingStackBounds) {
// If the stack exists, then use its final bounds to calculate the new aspect ratio
// bounds.
stackBounds = new Rect();
- stack.getAnimatingBounds(stackBounds);
+ stack.getAnimationOrCurrentBounds(stackBounds);
} else {
// Otherwise, just calculate the aspect ratio bounds from the default bounds
stackBounds = pinnedStackController.getDefaultBounds();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 8098eea..0b96f3f 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -50,6 +50,7 @@
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
@@ -1089,7 +1090,7 @@
// notify the client of frame changes in this case. Not only is it a lot of churn, but
// the frame may not correspond to the surface size or the onscreen area at various
// phases in the animation, and the client will become sad and confused.
- if (task != null && task.mStack.getBoundsAnimating()) {
+ if (task != null && task.mStack.isAnimatingBounds()) {
return;
}
@@ -4411,4 +4412,14 @@
nowGone = true;
}
}
+
+ boolean usesRelativeZOrdering() {
+ if (!isChildWindow()) {
+ return false;
+ } else if (mAttrs.type == TYPE_APPLICATION_MEDIA_OVERLAY) {
+ return true;
+ } else {
+ return false;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index a7f6db1..fa35336 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -714,7 +714,16 @@
}
// Start a new transaction and apply position & offset.
- mSurfaceController.setPositionAndLayer(mTmpSize.left, mTmpSize.top, getLayerStack(), mAnimLayer);
+
+ mService.openSurfaceTransaction();
+ try {
+ mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top, false);
+ mSurfaceController.setLayerStackInTransaction(getLayerStack());
+ mSurfaceController.setLayer(mAnimLayer);
+ } finally {
+ mService.closeSurfaceTransaction();
+ }
+
mLastHidden = true;
if (WindowManagerService.localLOGV) Slog.v(TAG, "Created surface " + this);
@@ -1351,11 +1360,11 @@
int posX = mTmpSize.left;
int posY = mTmpSize.top;
task.mStack.getDimBounds(mTmpStackBounds);
- task.mStack.getAnimatingSourceBounds(mTmpSourceBounds);
+ task.mStack.getFinalAnimationSourceBounds(mTmpSourceBounds);
if (!mTmpSourceBounds.isEmpty()) {
// Get the final target stack bounds, if we are not animating, this is just the
// current stack bounds
- task.mStack.getAnimatingBounds(mTmpAnimatingBounds);
+ task.mStack.getFinalAnimationBounds(mTmpAnimatingBounds);
// Calculate the current progress and interpolate the difference between the target
// and source bounds
@@ -1521,12 +1530,13 @@
+ "," + mDsDy + "*" + w.mVScale + "]", false);
boolean prepared =
- mSurfaceController.prepareToShowInTransaction(mShownAlpha, mAnimLayer,
+ mSurfaceController.prepareToShowInTransaction(mShownAlpha,
mDsDx * w.mHScale * mExtraHScale,
mDtDx * w.mVScale * mExtraVScale,
mDtDy * w.mHScale * mExtraHScale,
mDsDy * w.mVScale * mExtraVScale,
recoveringMemory);
+ mSurfaceController.setLayer(mAnimLayer);
if (prepared && mLastHidden && mDrawState == HAS_DRAWN) {
if (showSurfaceRobustlyLocked()) {
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index adf4501..edbdf8b 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -163,32 +163,6 @@
}
}
- void setPositionAndLayer(float left, float top, int layerStack, int layer) {
- mService.openSurfaceTransaction();
- try {
- mSurfaceX = left;
- mSurfaceY = top;
-
- try {
- if (SHOW_TRANSACTIONS) logSurface(
- "POS (setPositionAndLayer) @ (" + left + "," + top + ")", null);
- mSurfaceControl.setPosition(left, top);
- mSurfaceControl.setLayerStack(layerStack);
-
- mSurfaceControl.setLayer(layer);
- mSurfaceControl.setAlpha(0);
- setShown(false);
- } catch (RuntimeException e) {
- Slog.w(TAG, "Error creating surface in " + this, e);
- mAnimator.reclaimSomeSurfaceMemory("create-init", true);
- }
- } finally {
- mService.closeSurfaceTransaction();
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- "<<< CLOSE TRANSACTION setPositionAndLayer");
- }
- }
-
void destroyInTransaction() {
if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(8));
@@ -269,7 +243,15 @@
if (mSurfaceControl != null) {
mService.openSurfaceTransaction();
try {
- mSurfaceControl.setLayer(layer);
+ if (mAnimator.mWin.usesRelativeZOrdering()) {
+ mSurfaceControl.setRelativeLayer(
+ mAnimator.mWin.getParentWindow()
+ .mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(),
+ -1);
+ } else {
+ mSurfaceLayer = layer;
+ mSurfaceControl.setLayer(layer);
+ }
} finally {
mService.closeSurfaceTransaction();
}
@@ -363,15 +345,13 @@
return false;
}
- boolean prepareToShowInTransaction(float alpha, int layer,
+ boolean prepareToShowInTransaction(float alpha,
float dsdx, float dtdx, float dsdy,
float dtdy, boolean recoveringMemory) {
if (mSurfaceControl != null) {
try {
mSurfaceAlpha = alpha;
mSurfaceControl.setAlpha(alpha);
- mSurfaceLayer = layer;
- mSurfaceControl.setLayer(layer);
mLastDsdx = dsdx;
mLastDtdx = dtdx;
mLastDsdy = dsdy;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index f74512a..42a9232 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -981,6 +981,11 @@
traceBeginAndSlog("StartPersistentDataBlock");
mSystemServiceManager.startService(PersistentDataBlockService.class);
traceEnd();
+
+ // Implementation depends on persistent data block
+ traceBeginAndSlog("StartOemLockService");
+ mSystemServiceManager.startService(OemLockService.class);
+ traceEnd();
}
traceBeginAndSlog("StartDeviceIdleController");
@@ -1437,7 +1442,8 @@
traceEnd();
}
- if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_LIVE_TV)) {
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_LIVE_TV)
+ || mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
traceBeginAndSlog("StartTvInputManager");
mSystemServiceManager.startService(TvInputManagerService.class);
traceEnd();
@@ -1540,9 +1546,11 @@
mSystemServiceManager.startService(RetailDemoModeService.class);
traceEnd();
- traceBeginAndSlog("StartAutoFillService");
- mSystemServiceManager.startService(AUTO_FILL_MANAGER_SERVICE_CLASS);
- traceEnd();
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOFILL)) {
+ traceBeginAndSlog("StartAutoFillService");
+ mSystemServiceManager.startService(AUTO_FILL_MANAGER_SERVICE_CLASS);
+ traceEnd();
+ }
// It is now time to start up the app processes...
diff --git a/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java b/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
index d14f4eb..013eab8 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
@@ -67,7 +67,7 @@
@Override
public void show() {
super.show();
- final TextView messageView = (TextView) findViewById(R.id.message);
+ final TextView messageView = findViewById(R.id.message);
messageView.post(new Runnable() {
@Override
public void run() {
diff --git a/services/tests/notification/Android.mk b/services/tests/notification/Android.mk
index a5d5570..940db79 100644
--- a/services/tests/notification/Android.mk
+++ b/services/tests/notification/Android.mk
@@ -23,7 +23,8 @@
guava \
android-support-test \
mockito-target-minus-junit4 \
- platform-test-annotations
+ platform-test-annotations \
+ testables
LOCAL_JAVA_LIBRARIES := android.test.runner
diff --git a/services/tests/notification/AndroidManifest.xml b/services/tests/notification/AndroidManifest.xml
index cf050a8..99d9c7b 100644
--- a/services/tests/notification/AndroidManifest.xml
+++ b/services/tests/notification/AndroidManifest.xml
@@ -24,6 +24,7 @@
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATIONS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
index e285669..d383aea 100644
--- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -215,6 +215,8 @@
builder.setSound(CUSTOM_SOUND);
channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
}
+ } else {
+ channel.setSound(null, null);
}
if (buzzy) {
if (defaultVibration) {
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
index 176342b..84945ab 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
@@ -75,6 +75,7 @@
private NotificationRecord mRecordContact;
private NotificationRecord mRecordUrgent;
private NotificationRecord mRecordCheater;
+ private NotificationRecord mRecordCheaterColorized;
@Before
@@ -174,6 +175,7 @@
pkg2, 1, "cheater", uid2, uid2, n9, new UserHandle(userId),
"", 9258), getDefaultChannel());
mRecordCheater.setUserImportance(NotificationManager.IMPORTANCE_LOW);
+ mRecordCheater.setPackagePriority(Notification.PRIORITY_MAX);
Notification n10 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
.setStyle(new Notification.InboxStyle().setSummaryText("message!")).build();
@@ -181,6 +183,15 @@
pkg2, 1, "email", uid2, uid2, n10, new UserHandle(userId),
"", 1599), getDefaultChannel());
mRecordEmail.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
+
+ Notification n11 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+ .setCategory(Notification.CATEGORY_MESSAGE)
+ .setColorized(true)
+ .build();
+ mRecordCheaterColorized = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
+ pkg2, 1, "cheater", uid2, uid2, n11, new UserHandle(userId),
+ "", 9258), getDefaultChannel());
+ mRecordCheaterColorized.setUserImportance(NotificationManager.IMPORTANCE_LOW);
}
@Test
@@ -195,6 +206,7 @@
expected.add(mRecordEmail);
expected.add(mRecordUrgent);
expected.add(mRecordCheater);
+ expected.add(mRecordCheaterColorized);
expected.add(mRecordMinCall);
List<NotificationRecord> actual = new ArrayList<>();
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index 4c23d79..f666727 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -16,7 +16,10 @@
package com.android.server.notification;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+
import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
@@ -26,6 +29,8 @@
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -33,27 +38,33 @@
import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
+import android.companion.ICompanionDeviceManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
+import android.graphics.Color;
import android.os.Binder;
-import android.os.HandlerThread;
-import android.os.MessageQueue;
import android.os.UserHandle;
+import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.support.test.annotation.UiThreadTest;
import android.support.test.InstrumentationRegistry;
+import android.testing.TestableLooper;
+import java.util.ArrayList;
import java.util.Arrays;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+import java.util.List;
+
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
@@ -64,66 +75,72 @@
private final int uid = Binder.getCallingUid();
private NotificationManagerService mNotificationManagerService;
private INotificationManager mBinderService;
- private IPackageManager mPackageManager = mock(IPackageManager.class);
- private final PackageManager mPackageManagerClient = mock(PackageManager.class);
+ private NotificationManagerInternal mInternalService;
+ @Mock
+ private IPackageManager mPackageManager;
+ @Mock
+ private PackageManager mPackageManagerClient;
private Context mContext = InstrumentationRegistry.getTargetContext();
private final String PKG = mContext.getPackageName();
- private HandlerThread mThread;
- private final RankingHelper mRankingHelper = mock(RankingHelper.class);
+ private TestableLooper mTestableLooper;
+ @Mock
+ private RankingHelper mRankingHelper;
private NotificationChannel mTestNotificationChannel = new NotificationChannel(
TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
+ @Mock
+ private NotificationManagerService.NotificationListeners mNotificationListeners;
+ private ManagedServices.ManagedServiceInfo mListener;
+ @Mock private ICompanionDeviceManager mCompanionMgr;
+
+ // Use a Testable subclass so we can simulate calls from the system without failing.
+ private static class TestableNotificationManagerService extends NotificationManagerService {
+ public TestableNotificationManagerService(Context context) { super(context); }
+
+ @Override
+ protected boolean isCallerSystem() {
+ return true;
+ }
+
+ @Override
+ protected ICompanionDeviceManager getCompanionManager() {
+ return null;
+ }
+ }
@Before
- @Test
@UiThreadTest
public void setUp() throws Exception {
- mNotificationManagerService = new NotificationManagerService(mContext);
+ MockitoAnnotations.initMocks(this);
+ mNotificationManagerService = new TestableNotificationManagerService(mContext);
// MockPackageManager - default returns ApplicationInfo with matching calling UID
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.uid = uid;
- when(mPackageManager.getApplicationInfo(any(), anyInt(), anyInt()))
+ when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
.thenReturn(applicationInfo);
when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
.thenReturn(applicationInfo);
final LightsManager mockLightsManager = mock(LightsManager.class);
when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
- // Use a separate thread for service looper.
- mThread = new HandlerThread("TestThread");
- mThread.start();
- // Mock NotificationListeners to bypass security checks.
- final NotificationManagerService.NotificationListeners mockNotificationListeners =
- mock(NotificationManagerService.NotificationListeners.class);
- when(mockNotificationListeners.checkServiceTokenLocked(any())).thenReturn(
- mockNotificationListeners.new ManagedServiceInfo(null,
- new ComponentName(PKG, "test_class"), uid, true, null, 0));
+ // Use this testable looper.
+ mTestableLooper = new TestableLooper(false);
- mNotificationManagerService.init(mThread.getLooper(), mPackageManager,
- mPackageManagerClient, mockLightsManager, mockNotificationListeners);
+ mListener = mNotificationListeners.new ManagedServiceInfo(
+ null, new ComponentName(PKG, "test_class"), uid, true, null, 0);
+ when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
+ mNotificationManagerService.init(mTestableLooper.getLooper(), mPackageManager,
+ mPackageManagerClient, mockLightsManager, mNotificationListeners, mCompanionMgr);
// Tests call directly into the Binder.
mBinderService = mNotificationManagerService.getBinderService();
+ mInternalService = mNotificationManagerService.getInternalService();
mBinderService.createNotificationChannels(
PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
}
public void waitForIdle() throws Exception {
- MessageQueue queue = mThread.getLooper().getQueue();
- if (queue.isIdle()) {
- return;
- }
- CountDownLatch latch = new CountDownLatch(1);
- queue.addIdleHandler(new MessageQueue.IdleHandler() {
- @Override public boolean queueIdle() {
- latch.countDown();
- return false;
- }
- });
- // Timeout is valid in the cases where the queue goes idle before the IdleHandler
- // is added.
- latch.await(WAIT_FOR_IDLE_TIMEOUT, TimeUnit.SECONDS);
- waitForIdle();
+ mTestableLooper.processAllMessages();
}
private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
@@ -260,7 +277,6 @@
@Test
@UiThreadTest
- @Ignore("Flaky")
public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
generateNotificationRecord(null).getNotification(), new int[1], 0);
@@ -380,6 +396,21 @@
@Test
@UiThreadTest
+ public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
+ final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
+ sbn.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
+ mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
+ sbn.getId(), sbn.getNotification(), new int[1], sbn.getUserId());
+ mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
+ sbn.getUserId());
+ waitForIdle();
+ StatusBarNotification[] notifs =
+ mBinderService.getActiveNotifications(sbn.getPackageName());
+ assertEquals(0, notifs[0].getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE);
+ }
+
+ @Test
+ @UiThreadTest
public void testTvExtenderChannelOverride_onTv() throws Exception {
mNotificationManagerService.setIsTelevision(true);
mNotificationManagerService.setRankingHelper(mRankingHelper);
@@ -409,4 +440,223 @@
verify(mRankingHelper, times(1)).getNotificationChannel(
anyString(), anyInt(), eq(mTestNotificationChannel.getId()), anyBoolean());
}
+
+ @Test
+ @UiThreadTest
+ public void testCreateChannelNotifyListener() throws Exception {
+ List<String> associations = new ArrayList<>();
+ associations.add("a");
+ when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+ mNotificationManagerService.setRankingHelper(mRankingHelper);
+ when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
+ eq(mTestNotificationChannel.getId()), anyBoolean()))
+ .thenReturn(mTestNotificationChannel);
+ NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
+ when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
+ eq(channel2.getId()), anyBoolean()))
+ .thenReturn(channel2);
+
+ reset(mNotificationListeners);
+ mBinderService.createNotificationChannels(PKG,
+ new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
+ verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
+ eq(mTestNotificationChannel),
+ eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
+ verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
+ eq(channel2),
+ eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCreateChannelGroupNotifyListener() throws Exception {
+ List<String> associations = new ArrayList<>();
+ associations.add("a");
+ when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+ mNotificationManagerService.setRankingHelper(mRankingHelper);
+ NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
+ NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
+
+ reset(mNotificationListeners);
+ mBinderService.createNotificationChannelGroups(PKG,
+ new ParceledListSlice(Arrays.asList(group1, group2)));
+ verify(mNotificationListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
+ eq(group1),
+ eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
+ verify(mNotificationListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
+ eq(group2),
+ eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testUpdateChannelNotifyListener() throws Exception {
+ List<String> associations = new ArrayList<>();
+ associations.add("a");
+ when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+ mNotificationManagerService.setRankingHelper(mRankingHelper);
+ mTestNotificationChannel.setLightColor(Color.CYAN);
+ when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
+ eq(mTestNotificationChannel.getId()), anyBoolean()))
+ .thenReturn(mTestNotificationChannel);
+
+ reset(mNotificationListeners);
+ mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
+ verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
+ eq(mTestNotificationChannel),
+ eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testDeleteChannelNotifyListener() throws Exception {
+ List<String> associations = new ArrayList<>();
+ associations.add("a");
+ when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+ mNotificationManagerService.setRankingHelper(mRankingHelper);
+ when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
+ eq(mTestNotificationChannel.getId()), anyBoolean()))
+ .thenReturn(mTestNotificationChannel);
+ reset(mNotificationListeners);
+ mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
+ verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
+ eq(mTestNotificationChannel),
+ eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testDeleteChannelGroupNotifyListener() throws Exception {
+ List<String> associations = new ArrayList<>();
+ associations.add("a");
+ when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+ NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
+ mNotificationManagerService.setRankingHelper(mRankingHelper);
+ when(mRankingHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
+ .thenReturn(ncg);
+ reset(mNotificationListeners);
+ mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
+ verify(mNotificationListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
+ eq(ncg),
+ eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
+ mNotificationManagerService.setRankingHelper(mRankingHelper);
+ List<String> associations = new ArrayList<>();
+ associations.add("a");
+ when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+
+ mBinderService.updateNotificationChannelFromPrivilegedListener(
+ null, PKG, mTestNotificationChannel);
+
+ verify(mRankingHelper, times(1)).updateNotificationChannel(anyString(), anyInt(), any());
+
+ verify(mNotificationListeners, never()).notifyNotificationChannelChanged(eq(PKG),
+ eq(mTestNotificationChannel),
+ eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
+ mNotificationManagerService.setRankingHelper(mRankingHelper);
+ List<String> associations = new ArrayList<>();
+ when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+
+ try {
+ mBinderService.updateNotificationChannelFromPrivilegedListener(
+ null, PKG, mTestNotificationChannel);
+ fail("listeners that don't have a companion device shouldn't be able to call this");
+ } catch (SecurityException e) {
+ // pass
+ }
+
+ verify(mRankingHelper, never()).updateNotificationChannel(anyString(), anyInt(), any());
+
+ verify(mNotificationListeners, never()).notifyNotificationChannelChanged(eq(PKG),
+ eq(mTestNotificationChannel),
+ eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testGetNotificationChannelFromPrivilegedListener_success() throws Exception {
+ mNotificationManagerService.setRankingHelper(mRankingHelper);
+ List<String> associations = new ArrayList<>();
+ associations.add("a");
+ when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+
+ mBinderService.getNotificationChannelsFromPrivilegedListener(null, PKG);
+
+ verify(mRankingHelper, times(1)).getNotificationChannels(
+ anyString(), anyInt(), anyBoolean());
+ }
+
+ @Test
+ @UiThreadTest
+ public void testGetNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
+ mNotificationManagerService.setRankingHelper(mRankingHelper);
+ List<String> associations = new ArrayList<>();
+ when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+
+ try {
+ mBinderService.getNotificationChannelsFromPrivilegedListener(null, PKG);
+ fail("listeners that don't have a companion device shouldn't be able to call this");
+ } catch (SecurityException e) {
+ // pass
+ }
+
+ verify(mRankingHelper, never()).getNotificationChannels(
+ anyString(), anyInt(), anyBoolean());
+ }
+
+ @Test
+ @UiThreadTest
+ public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
+ mNotificationManagerService.setRankingHelper(mRankingHelper);
+ List<String> associations = new ArrayList<>();
+ associations.add("a");
+ when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+
+ mBinderService.getNotificationChannelGroupsFromPrivilegedListener(null, PKG);
+
+ verify(mRankingHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
+ }
+
+ @Test
+ @UiThreadTest
+ public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
+ mNotificationManagerService.setRankingHelper(mRankingHelper);
+ List<String> associations = new ArrayList<>();
+ when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+
+ try {
+ mBinderService.getNotificationChannelGroupsFromPrivilegedListener(null, PKG);
+ fail("listeners that don't have a companion device shouldn't be able to call this");
+ } catch (SecurityException e) {
+ // pass
+ }
+
+ verify(mRankingHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHasCompanionDevice_failure() throws Exception {
+ when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
+ new IllegalArgumentException());
+ mNotificationManagerService.hasCompanionDevice(mListener);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHasCompanionDevice_noService() throws Exception {
+ mNotificationManagerService = new TestableNotificationManagerService(mContext);
+
+ assertFalse(mNotificationManagerService.hasCompanionDevice(mListener));
+ }
+
}
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index 885eb2e..303054e 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -738,15 +738,6 @@
}
@Test
- public void testCreateChannel_addMissingSound() throws Exception {
- final NotificationChannel channel =
- new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
- mHelper.createNotificationChannel(PKG, UID, channel, true);
- assertNotNull(mHelper.getNotificationChannel(
- PKG, UID, channel.getId(), false).getSound());
- }
-
- @Test
public void testCreateChannel_noOverrideSound() throws Exception {
Uri sound = new Uri.Builder().scheme("test").build();
final NotificationChannel channel = new NotificationChannel("id2", "name2",
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 353199a..985e5ea 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -23,7 +23,6 @@
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.assertSame;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
@@ -37,7 +36,7 @@
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -49,7 +48,6 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.INetworkRecommendationProvider;
@@ -94,8 +92,6 @@
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -138,11 +134,13 @@
@Mock private Context mContext;
@Mock private Resources mResources;
@Mock private INetworkScoreCache.Stub mNetworkScoreCache, mNetworkScoreCache2;
- @Mock private IBinder mIBinder, mIBinder2;
+ @Mock private IBinder mScoreCacheIBinder, mScoreCacheIBinder2;
+ @Mock private IBinder mServiceConnectionIBinder;
@Mock private INetworkRecommendationProvider mRecommendationProvider;
@Mock private UnaryOperator<List<ScoredNetwork>> mCurrentNetworkFilter;
@Mock private UnaryOperator<List<ScoredNetwork>> mScanResultsFilter;
@Mock private WifiInfo mWifiInfo;
+ @Mock private NetworkScoreService.ScoringServiceConnection mServiceConnection;
@Captor private ArgumentCaptor<List<ScoredNetwork>> mScoredNetworkCaptor;
private ContentResolver mContentResolver;
@@ -160,17 +158,22 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- when(mNetworkScoreCache.asBinder()).thenReturn(mIBinder);
- when(mNetworkScoreCache2.asBinder()).thenReturn(mIBinder2);
+ when(mNetworkScoreCache.asBinder()).thenReturn(mScoreCacheIBinder);
+ when(mNetworkScoreCache2.asBinder()).thenReturn(mScoreCacheIBinder2);
+ when(mServiceConnectionIBinder.queryLocalInterface(anyString()))
+ .thenReturn(mRecommendationProvider);
mContentResolver = InstrumentationRegistry.getContext().getContentResolver();
when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mContext.getResources()).thenReturn(mResources);
when(mWifiInfo.getSSID()).thenReturn(SCORED_NETWORK.networkKey.wifiKey.ssid);
when(mWifiInfo.getBSSID()).thenReturn(SCORED_NETWORK.networkKey.wifiKey.bssid);
+ when(mServiceConnection.getAppData()).thenReturn(NEW_SCORER);
+ when(mServiceConnection.getRecommendationProvider()).thenReturn(mRecommendationProvider);
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
mHandlerThread = new HandlerThread("NetworkScoreServiceTest");
mHandlerThread.start();
mNetworkScoreService = new NetworkScoreService(mContext, mNetworkScorerAppManager,
- mHandlerThread.getLooper());
+ networkScorerAppData -> mServiceConnection, mHandlerThread.getLooper());
WifiConfiguration configuration = new WifiConfiguration();
configuration.SSID = "NetworkScoreServiceTest_SSID";
configuration.BSSID = "NetworkScoreServiceTest_BSSID";
@@ -209,12 +212,10 @@
mNetworkScoreService.onUserUnlocked(0);
- verify(mContext).bindServiceAsUser(MockUtils.checkIntent(
- new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
- .setComponent(RECOMMENDATION_SERVICE_COMP)),
- any(ServiceConnection.class),
- eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
- eq(UserHandle.SYSTEM));
+ verify(mNetworkScorerAppManager).updateState();
+ verify(mNetworkScorerAppManager).migrateNetworkScorerAppSettingIfNeeded();
+ verify(mServiceConnection).bind(mContext);
+
}
@Test
@@ -238,16 +239,16 @@
@Test
public void testRequestScores_providerThrowsRemoteException() throws Exception {
- injectProvider();
doThrow(new RemoteException()).when(mRecommendationProvider)
.requestScores(any(NetworkKey[].class));
+ mNetworkScoreService.onUserUnlocked(0);
assertFalse(mNetworkScoreService.requestScores(new NetworkKey[0]));
}
@Test
public void testRequestScores_providerAvailable() throws Exception {
- injectProvider();
+ mNetworkScoreService.onUserUnlocked(0);
final NetworkKey[] networks = new NetworkKey[0];
assertTrue(mNetworkScoreService.requestScores(networks));
@@ -291,11 +292,11 @@
@Test
public void testRequestRecommendation_providerThrowsRemoteException() throws Exception {
- injectProvider();
when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
doThrow(new RemoteException()).when(mRecommendationProvider)
.requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
anyInt());
+ mNetworkScoreService.onUserUnlocked(0);
final RecommendationResult result =
mNetworkScoreService.requestRecommendation(mRecommendationRequest);
@@ -306,7 +307,6 @@
@Test
public void testRequestRecommendation_resultReturned() throws Exception {
- injectProvider();
when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
final WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = "testRequestRecommendation_resultReturned_SSID";
@@ -322,6 +322,7 @@
}).when(mRecommendationProvider)
.requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
anyInt());
+ mNetworkScoreService.onUserUnlocked(0);
final RecommendationResult result =
mNetworkScoreService.requestRecommendation(mRecommendationRequest);
@@ -357,7 +358,7 @@
@Test
public void testRequestRecommendationAsync_requestTimesOut() throws Exception {
- injectProvider();
+ mNetworkScoreService.onUserUnlocked(0);
Settings.Global.putLong(mContentResolver,
Settings.Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS, 1L);
mNetworkScoreService.refreshRecommendationRequestTimeoutMs();
@@ -378,7 +379,7 @@
@Test
public void testRequestRecommendationAsync_requestSucceeds() throws Exception {
- injectProvider();
+ mNetworkScoreService.onUserUnlocked(0);
final Bundle bundle = new Bundle();
doAnswer(invocation -> {
invocation.<IRemoteCallback>getArgument(1).sendResult(bundle);
@@ -397,7 +398,7 @@
@Test
public void testRequestRecommendationAsync_requestThrowsRemoteException() throws Exception {
- injectProvider();
+ mNetworkScoreService.onUserUnlocked(0);
doThrow(new RemoteException()).when(mRecommendationProvider)
.requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
anyInt());
@@ -657,9 +658,13 @@
@Test
public void testIsCallerActiveScorer_noBoundService() throws Exception {
+ // No active scorer.
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(null);
mNetworkScoreService.onUserUnlocked(0);
- assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
+ mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid());
+
+ verify(mServiceConnection, never()).getAppData();
}
@Test
@@ -678,9 +683,13 @@
@Test
public void testGetActiveScorerPackage_notActive() throws Exception {
+ // No active scorer.
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(null);
mNetworkScoreService.onUserUnlocked(0);
- assertNull(mNetworkScoreService.getActiveScorerPackage());
+ mNetworkScoreService.getActiveScorerPackage();
+
+ verify(mServiceConnection, never()).getPackageName();
}
@Test
@@ -688,10 +697,9 @@
when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
mNetworkScoreService.onUserUnlocked(0);
- assertEquals(NEW_SCORER.getRecommendationServicePackageName(),
- mNetworkScoreService.getActiveScorerPackage());
- assertEquals(NEW_SCORER.getEnableUseOpenWifiActivity(),
- mNetworkScoreService.getActiveScorer().getEnableUseOpenWifiActivity());
+ mNetworkScoreService.getActiveScorerPackage();
+
+ verify(mServiceConnection).getPackageName();
}
@Test
@@ -931,7 +939,12 @@
public void testGetActiveScorer_notConnected_canRequestScores() throws Exception {
when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_GRANTED);
- assertNull(mNetworkScoreService.getActiveScorer());
+ when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(null);
+ mNetworkScoreService.onUserUnlocked(0);
+
+ mNetworkScoreService.getActiveScorer();
+
+ verify(mServiceConnection, never()).getAppData();
}
@Test
@@ -951,11 +964,11 @@
throws Exception {
when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
.thenReturn(PackageManager.PERMISSION_GRANTED);
- NetworkScorerAppData expectedAppData = new NetworkScorerAppData(Binder.getCallingUid(),
- RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
- USE_WIFI_ENABLE_ACTIVITY_COMP, NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID);
- bindToScorer(expectedAppData);
- assertEquals(expectedAppData, mNetworkScoreService.getActiveScorer());
+ mNetworkScoreService.onUserUnlocked(0);
+
+ mNetworkScoreService.getActiveScorer();
+
+ verify(mServiceConnection).getAppData();
}
@Test
@@ -972,23 +985,98 @@
}
}
- // "injects" the mock INetworkRecommendationProvider into the NetworkScoreService.
- private void injectProvider() {
- when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
- when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
- isA(UserHandle.class))).thenAnswer(new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- IBinder mockBinder = mock(IBinder.class);
- when(mockBinder.queryLocalInterface(anyString()))
- .thenReturn(mRecommendationProvider);
- invocation.<ServiceConnection>getArgument(1)
- .onServiceConnected(NEW_SCORER.getRecommendationServiceComponent(),
- mockBinder);
- return true;
- }
- });
- mNetworkScoreService.onUserUnlocked(0);
+ @Test
+ public void testServiceConnection_bind_notBound() throws Exception {
+ NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
+ .ScoringServiceConnection(NEW_SCORER);
+ connection.bind(mContext);
+
+ verify(mContext).bindServiceAsUser(MockUtils.checkIntent(
+ new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
+ .setComponent(RECOMMENDATION_SERVICE_COMP)),
+ eq(connection),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ eq(UserHandle.SYSTEM));
+ }
+
+ @Test
+ public void testServiceConnection_bind_alreadyBound() throws Exception {
+ NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
+ .ScoringServiceConnection(NEW_SCORER);
+
+ when(mContext.bindServiceAsUser(MockUtils.checkIntent(
+ new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
+ .setComponent(RECOMMENDATION_SERVICE_COMP)),
+ eq(connection),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ eq(UserHandle.SYSTEM))).thenReturn(true /*bound*/);
+
+ // Calling bind more than once should only result in 1 bindService call.
+ connection.bind(mContext);
+ connection.bind(mContext);
+
+ verify(mContext, times(1)).bindServiceAsUser(MockUtils.checkIntent(
+ new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
+ .setComponent(RECOMMENDATION_SERVICE_COMP)),
+ eq(connection),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ eq(UserHandle.SYSTEM));
+ }
+
+ @Test
+ public void testServiceConnection_bindFails() throws Exception {
+ NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
+ .ScoringServiceConnection(NEW_SCORER);
+
+ when(mContext.bindServiceAsUser(MockUtils.checkIntent(
+ new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
+ .setComponent(RECOMMENDATION_SERVICE_COMP)),
+ eq(connection),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ eq(UserHandle.SYSTEM))).thenReturn(false /*bound*/);
+
+ connection.bind(mContext);
+
+ verify(mContext).unbindService(connection);
+ }
+
+ @Test
+ public void testServiceConnection_unbind_notBound() throws Exception {
+ NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
+ .ScoringServiceConnection(NEW_SCORER);
+
+ connection.unbind(mContext);
+
+ verify(mContext, never()).unbindService(connection);
+ }
+
+ @Test
+ public void testServiceConnection_unbind_alreadyBound() throws Exception {
+ NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
+ .ScoringServiceConnection(NEW_SCORER);
+
+ when(mContext.bindServiceAsUser(MockUtils.checkIntent(
+ new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
+ .setComponent(RECOMMENDATION_SERVICE_COMP)),
+ eq(connection),
+ eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ eq(UserHandle.SYSTEM))).thenReturn(true /*bound*/);
+
+ connection.bind(mContext);
+ connection.unbind(mContext);
+
+ verify(mContext).unbindService(connection);
+ }
+
+ @Test
+ public void testServiceConnection_dump_doesNotCrash() throws Exception {
+ NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
+ .ScoringServiceConnection(NEW_SCORER);
+ final StringWriter stringWriter = new StringWriter();
+
+ connection.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
+
+ assertFalse(stringWriter.toString().isEmpty());
}
private void bindToScorer(boolean callerIsScorer) {
@@ -996,13 +1084,7 @@
NetworkScorerAppData appData = new NetworkScorerAppData(callingUid,
RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
USE_WIFI_ENABLE_ACTIVITY_COMP, NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID);
- bindToScorer(appData);
- }
-
- private void bindToScorer(NetworkScorerAppData appData) {
- when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
- when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
- isA(UserHandle.class))).thenReturn(true);
+ when(mServiceConnection.getAppData()).thenReturn(appData);
mNetworkScoreService.onUserUnlocked(0);
}
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 00f6273..20839c5 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -117,6 +117,7 @@
@Captor private ArgumentCaptor<Bundle> mBundleCaptor;
private int mVisibleAccountsChangedBroadcasts;
private int mLoginAccountsChangedBroadcasts;
+ private int mAccountRemovedBroadcasts;
private static final int LATCH_TIMEOUT_MS = 500;
private static final String PREN_DB = "pren.db";
@@ -2510,6 +2511,7 @@
updateBroadcastCounters(2);
assertEquals(mVisibleAccountsChangedBroadcasts, 0); // broadcast was not sent
assertEquals(mLoginAccountsChangedBroadcasts, 2);
+ assertEquals(mAccountRemovedBroadcasts, 0);
}
@SmallTest
@@ -2533,9 +2535,10 @@
mAms.registerAccountListener( null /* accountTypes */, "testpackage");
mAms.removeAccountInternal(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE);
- updateBroadcastCounters(6);
+ updateBroadcastCounters(8);
assertEquals(mVisibleAccountsChangedBroadcasts, 2);
assertEquals(mLoginAccountsChangedBroadcasts, 4);
+ assertEquals(mAccountRemovedBroadcasts, 2);
}
@SmallTest
@@ -2560,17 +2563,19 @@
"testpackage3"); // opPackageName
// Remove account with 2 active listeners.
mAms.removeAccountInternal(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS);
- updateBroadcastCounters(7);
+ updateBroadcastCounters(8);
assertEquals(mVisibleAccountsChangedBroadcasts, 5);
assertEquals(mLoginAccountsChangedBroadcasts, 2); // 3 add, 2 remove
+ assertEquals(mAccountRemovedBroadcasts, 1);
// Add account of another type.
mAms.addAccountExplicitly(
AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_TYPE_2, "p11", null);
- updateBroadcastCounters(8);
+ updateBroadcastCounters(9);
assertEquals(mVisibleAccountsChangedBroadcasts, 5);
assertEquals(mLoginAccountsChangedBroadcasts, 3);
+ assertEquals(mAccountRemovedBroadcasts, 1);
}
@SmallTest
@@ -2602,16 +2607,20 @@
private void updateBroadcastCounters (int expectedBroadcasts){
mVisibleAccountsChangedBroadcasts = 0;
mLoginAccountsChangedBroadcasts = 0;
+ mAccountRemovedBroadcasts = 0;
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mMockContext, times(expectedBroadcasts)).sendBroadcastAsUser(captor.capture(),
any(UserHandle.class));
for (Intent intent : captor.getAllValues()) {
- if (AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED. equals(intent.getAction())) {
+ if (AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED.equals(intent.getAction())) {
mVisibleAccountsChangedBroadcasts++;
}
- if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION. equals(intent.getAction())) {
+ if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.equals(intent.getAction())) {
mLoginAccountsChangedBroadcasts++;
}
+ if (AccountManager.ACTION_ACCOUNT_REMOVED.equals(intent.getAction())) {
+ mAccountRemovedBroadcasts++;
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
new file mode 100644
index 0000000..1d80b33
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.content.ComponentName;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link ActivityStack} class.
+ *
+ * Build/Install/Run:
+ * bit FrameworksServicesTests:com.android.server.am.ActivityStackTests
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class ActivityStackTests extends ActivityTestsBase {
+ private final ComponentName testActivityComponent =
+ ComponentName.unflattenFromString("com.foo/.BarActivity");
+
+ @Test
+ public void testEmptyTaskCleanupOnRemove() throws Exception {
+ final ActivityManagerService service = createActivityManagerService();
+ final TestActivityStack testStack = new ActivityStackBuilder(service).build();
+ final TaskRecord task = createTask(service, testActivityComponent, testStack);
+ assertNotNull(task.getWindowContainerController());
+ testStack.removeTask(task, "testEmptyTaskCleanupOnRemove",
+ ActivityStack.REMOVE_TASK_MODE_DESTROYING);
+ assertNull(task.getWindowContainerController());
+ }
+ @Test
+ public void testOccupiedTaskCleanupOnRemove() throws Exception {
+ final ActivityManagerService service = createActivityManagerService();
+ final TestActivityStack testStack = new ActivityStackBuilder(service).build();
+ final TaskRecord task = createTask(service, testActivityComponent, testStack);
+ final ActivityRecord activityRecord = createActivity(service, testActivityComponent, task);
+ assertNotNull(task.getWindowContainerController());
+ testStack.removeTask(task, "testOccupiedTaskCleanupOnRemove",
+ ActivityStack.REMOVE_TASK_MODE_DESTROYING);
+ assertNotNull(task.getWindowContainerController());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 5240586..3bf0e5f 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -18,6 +18,7 @@
import static org.mockito.Mockito.mock;
+import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -62,14 +63,16 @@
}
protected ActivityManagerService createActivityManagerService() {
- return new TestActivityManagerService(mContext);
+ final ActivityManagerService service = new TestActivityManagerService(mContext);
+ service.mWindowManager = WindowTestUtils.getWindowManagerService(mContext);
+ return service;
}
protected static TestActivityStack createActivityStack(ActivityManagerService service,
int stackId, int displayId, boolean onTop) {
if (service.mStackSupervisor instanceof TestActivityStackSupervisor) {
final TestActivityStack stack = ((TestActivityStackSupervisor) service.mStackSupervisor)
- .createTestStack(stackId, onTop);
+ .createTestStack(service, stackId, onTop);
return stack;
}
@@ -109,7 +112,7 @@
intent.setComponent(component);
final TaskRecord task = new TaskRecord(service, 0, aInfo, intent /*intent*/,
- null /*_taskDescription*/, null /*thumbnailInfo*/);
+ null /*_taskDescription*/, new ActivityManager.TaskThumbnailInfo());
stack.addTask(task, true, "creating test task");
task.setStack(stack);
task.createWindowContainer(true, true);
@@ -146,25 +149,39 @@
void updateUIDsPresentOnDisplay() {
}
- public TestActivityStack createTestStack(int stackId, boolean onTop) {
+ public TestActivityStack createTestStack(ActivityManagerService service, int stackId,
+ boolean onTop) {
final ActivityDisplay display = new ActivityDisplay();
final TestActivityContainer container =
- new TestActivityContainer(stackId, display, onTop);
+ new TestActivityContainer(service, stackId, display, onTop);
return container.getStack();
}
private class TestActivityContainer extends ActivityContainer {
+ private ActivityManagerService mService;
private TestActivityStack mStack;
- TestActivityContainer(int stackId, ActivityDisplay activityDisplay, boolean onTop) {
+ private boolean mOnTop;
+
+ TestActivityContainer(ActivityManagerService service, int stackId,
+ ActivityDisplay activityDisplay, boolean onTop) {
super(stackId, activityDisplay, onTop);
+ mService = service;
}
@Override
protected void createStack(int stackId, boolean onTop) {
- mStack = new TestActivityStack(this, null /*recentTasks*/, onTop);
+ // normally stack creation is done here. However we need to do it on demand since
+ // we cannot set {@link mService} by the time the super constructor calling this
+ // method is invoked.
+ mOnTop = onTop;
}
public TestActivityStack getStack() {
+ if (mStack == null) {
+ mStack = new TestActivityStack(this,
+ new RecentTasks(mService, mService.mStackSupervisor), mOnTop);
+ }
+
return mStack;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 9861aa1..cd39d88 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -708,7 +708,7 @@
Drawable dr = mLauncherApps.getShortcutIconDrawable(
makeShortcutWithIcon("bmp64x64", bmp64x64_maskable), 0);
assertTrue(dr instanceof AdaptiveIconDrawable);
- float viewportPercentage = 1 / (1 + 2 * AdaptiveIconDrawable.getExtraInsetPercentage());
+ float viewportPercentage = 1 / (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction());
assertEquals((int) (bmp64x64_maskable.getBitmap().getWidth() * viewportPercentage),
dr.getIntrinsicWidth());
assertEquals((int) (bmp64x64_maskable.getBitmap().getHeight() * viewportPercentage),
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
index 3c8bf20..d206407 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -97,7 +97,7 @@
final WindowTestUtils.TestAppWindowContainerController controller =
createAppWindowController();
controller.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false);
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true);
waitUntilHandlersIdle();
final AppWindowToken atoken = controller.getAppWindowToken();
assertHasStartingWindow(atoken);
@@ -113,11 +113,11 @@
final WindowTestUtils.TestAppWindowContainerController controller2 =
createAppWindowController();
controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false);
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true);
waitUntilHandlersIdle();
controller2.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
android.R.style.Theme, null, "Test", 0, 0, 0, 0, controller1.mToken.asBinder(),
- true, true, false);
+ true, true, false, true);
waitUntilHandlersIdle();
assertNoStartingWindow(controller1.getAppWindowToken());
assertHasStartingWindow(controller2.getAppWindowToken());
@@ -134,10 +134,10 @@
// Surprise, ...! Transfer window in the middle of the creation flow.
controller2.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
android.R.style.Theme, null, "Test", 0, 0, 0, 0, controller1.mToken.asBinder(),
- true, true, false);
+ true, true, false, true);
});
controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false);
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true);
waitUntilHandlersIdle();
assertNoStartingWindow(controller1.getAppWindowToken());
assertHasStartingWindow(controller2.getAppWindowToken());
diff --git a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
new file mode 100644
index 0000000..85dc712
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.WindowManagerInternal.AppTransitionListener;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.android.server.wm.BoundsAnimationController.BoundsAnimator;
+
+/**
+ * Test class for {@link BoundsAnimationController} to ensure that it sends the right callbacks
+ * depending on the various interactions.
+ *
+ * Build/Install/Run:
+ * bit FrameworksServicesTests:com.android.server.wm.BoundsAnimationControllerTests
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class BoundsAnimationControllerTests extends WindowTestsBase {
+
+ /**
+ * Mock value animator to simulate updates with.
+ */
+ private class MockValueAnimator extends ValueAnimator {
+
+ private float mFraction;
+
+ public MockValueAnimator getWithValue(float fraction) {
+ mFraction = fraction;
+ return this;
+ }
+
+ @Override
+ public Object getAnimatedValue() {
+ return mFraction;
+ }
+ }
+
+ /**
+ * Mock app transition to fire notifications to the bounds animator.
+ */
+ private class MockAppTransition extends AppTransition {
+
+ private AppTransitionListener mListener;
+
+ MockAppTransition(Context context) {
+ super(context, null);
+ }
+
+ @Override
+ void registerListenerLocked(AppTransitionListener listener) {
+ mListener = listener;
+ }
+
+ public void notifyTransitionPending() {
+ mListener.onAppTransitionPendingLocked();
+ }
+
+ public void notifyTransitionCancelled(int transit) {
+ mListener.onAppTransitionCancelledLocked(transit);
+ }
+
+ public void notifyTransitionStarting(int transit) {
+ mListener.onAppTransitionStartingLocked(transit, null, null, null, null);
+ }
+
+ public void notifyTransitionFinished() {
+ mListener.onAppTransitionFinishedLocked(null);
+ }
+ }
+
+ /**
+ * A test animate bounds user to track callbacks from the bounds animation.
+ */
+ private class TestAnimateBoundsUser implements BoundsAnimationController.AnimateBoundsUser {
+
+ boolean mMovedToFullscreen;
+ boolean mAnimationStarted;
+ boolean mAnimationStartedToFullscreen;
+ boolean mAnimationEnded;
+ boolean mUpdatedPictureInPictureModeWithBounds;
+ boolean mBoundsUpdated;
+ Rect mStackBounds;
+ Rect mTaskBounds;
+
+ boolean mRequestCancelAnimation = false;
+
+ void reinitialize(Rect stackBounds, Rect taskBounds) {
+ mMovedToFullscreen = false;
+ mAnimationStarted = false;
+ mAnimationStartedToFullscreen = false;
+ mAnimationEnded = false;
+ mUpdatedPictureInPictureModeWithBounds = false;
+ mStackBounds = stackBounds;
+ mTaskBounds = taskBounds;
+ mBoundsUpdated = false;
+ mRequestCancelAnimation = false;
+ }
+
+ @Override
+ public void onAnimationStart(boolean toFullscreen) {
+ mAnimationStarted = true;
+ mAnimationStartedToFullscreen = toFullscreen;
+ }
+
+ @Override
+ public void updatePictureInPictureMode(Rect targetStackBounds) {
+ mUpdatedPictureInPictureModeWithBounds = true;
+ }
+
+ @Override
+ public boolean setPinnedStackSize(Rect stackBounds, Rect taskBounds) {
+ // TODO: Once we break the runs apart, we should fail() here if this is called outside
+ // of onAnimationStart() and onAnimationEnd()
+ if (mRequestCancelAnimation) {
+ return false;
+ } else {
+ mBoundsUpdated = true;
+ mStackBounds = stackBounds;
+ mTaskBounds = taskBounds;
+ return true;
+ }
+ }
+
+ @Override
+ public void onAnimationEnd() {
+ mAnimationEnded = true;
+ }
+
+ @Override
+ public void moveToFullscreen() {
+ mMovedToFullscreen = true;
+ }
+ }
+
+ // Constants
+ private static final boolean MOVE_TO_FULLSCREEN = true;
+
+ // Some dummy bounds to represent fullscreen and floating bounds
+ private static final Rect BOUNDS_FULL = new Rect(0, 0, 100, 100);
+ private static final Rect BOUNDS_FLOATING = new Rect(80, 80, 95, 95);
+ private static final Rect BOUNDS_ALT_FLOATING = new Rect(60, 60, 95, 95);
+
+ // Some dummy duration
+ private static final int DURATION = 100;
+
+ // Common
+ private MockAppTransition mAppTransition;
+ private MockValueAnimator mAnimator;
+ private TestAnimateBoundsUser mTarget;
+ private BoundsAnimationController mController;
+
+ // Temp
+ private Rect mTmpRect = new Rect();
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ final Context context = InstrumentationRegistry.getTargetContext();
+ final Handler handler = new Handler(Looper.getMainLooper());
+ mAppTransition = new MockAppTransition(context);
+ mAnimator = new MockValueAnimator();
+ mTarget = new TestAnimateBoundsUser();
+ mController = new BoundsAnimationController(context, mAppTransition, handler);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testFullscreenToFloatingTransition() throws Exception {
+ // Create and start the animation
+ mTarget.reinitialize(BOUNDS_FULL, null);
+ final BoundsAnimator boundsAnimator = mController.animateBoundsImpl(mTarget, BOUNDS_FULL,
+ BOUNDS_FLOATING, DURATION, !MOVE_TO_FULLSCREEN);
+
+ // Assert that when we are started, and that we are not going to fullscreen
+ assertTrue(mTarget.mAnimationStarted);
+ assertFalse(mTarget.mAnimationStartedToFullscreen);
+ // Ensure we are not triggering a PiP mode change
+ assertFalse(mTarget.mUpdatedPictureInPictureModeWithBounds);
+ // Ensure that the task stack bounds are already frozen to the larger source stack bounds
+ assertEquals(BOUNDS_FULL, mTarget.mStackBounds);
+ assertEquals(BOUNDS_FULL, offsetToZero(mTarget.mTaskBounds));
+
+ // Drive some animation updates, ensure that only the stack bounds change and the task
+ // bounds are frozen to the original stack bounds (adjusted for the offset)
+ boundsAnimator.onAnimationUpdate(mAnimator.getWithValue(0.5f));
+ assertNotEquals(BOUNDS_FULL, mTarget.mStackBounds);
+ assertEquals(BOUNDS_FULL, offsetToZero(mTarget.mTaskBounds));
+ boundsAnimator.onAnimationUpdate(mAnimator.getWithValue(1f));
+ assertNotEquals(BOUNDS_FULL, mTarget.mStackBounds);
+ assertEquals(BOUNDS_FULL, offsetToZero(mTarget.mTaskBounds));
+
+ // Finish the animation, ensure that it reaches the final bounds with the given state
+ boundsAnimator.end();
+ assertTrue(mTarget.mAnimationEnded);
+ assertEquals(BOUNDS_FLOATING, mTarget.mStackBounds);
+ assertNull(mTarget.mTaskBounds);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testFloatingToFullscreenTransition() throws Exception {
+ // Create and start the animation
+ mTarget.reinitialize(BOUNDS_FULL, null);
+ final BoundsAnimator boundsAnimator = mController.animateBoundsImpl(mTarget, BOUNDS_FLOATING,
+ BOUNDS_FULL, DURATION, MOVE_TO_FULLSCREEN);
+
+ // Assert that when we are started, and that we are going to fullscreen
+ assertTrue(mTarget.mAnimationStarted);
+ assertTrue(mTarget.mAnimationStartedToFullscreen);
+ // Ensure that we update the PiP mode change with the new fullscreen bounds
+ assertTrue(mTarget.mUpdatedPictureInPictureModeWithBounds);
+ // Ensure that the task stack bounds are already frozen to the larger target stack bounds
+ assertEquals(BOUNDS_FLOATING, mTarget.mStackBounds);
+ assertEquals(BOUNDS_FULL, offsetToZero(mTarget.mTaskBounds));
+
+ // Drive some animation updates, ensure that only the stack bounds change and the task
+ // bounds are frozen to the original stack bounds (adjusted for the offset)
+ boundsAnimator.onAnimationUpdate(mAnimator.getWithValue(0.5f));
+ assertNotEquals(BOUNDS_FLOATING, mTarget.mStackBounds);
+ assertEquals(BOUNDS_FULL, offsetToZero(mTarget.mTaskBounds));
+ boundsAnimator.onAnimationUpdate(mAnimator.getWithValue(1f));
+ assertNotEquals(BOUNDS_FLOATING, mTarget.mStackBounds);
+ assertEquals(BOUNDS_FULL, offsetToZero(mTarget.mTaskBounds));
+
+ // Finish the animation, ensure that it reaches the final bounds with the given state
+ boundsAnimator.end();
+ assertTrue(mTarget.mAnimationEnded);
+ assertEquals(BOUNDS_FULL, mTarget.mStackBounds);
+ assertNull(mTarget.mTaskBounds);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testInterruptAnimationFromUser() throws Exception {
+ // Create and start the animation
+ mTarget.reinitialize(BOUNDS_FULL, null);
+ final BoundsAnimator boundsAnimator = mController.animateBoundsImpl(mTarget, BOUNDS_FULL,
+ BOUNDS_FLOATING, DURATION, !MOVE_TO_FULLSCREEN);
+
+ // Cancel the animation on the next update from the user
+ mTarget.mRequestCancelAnimation = true;
+ mTarget.mBoundsUpdated = false;
+ boundsAnimator.onAnimationUpdate(mAnimator.getWithValue(0.5f));
+ // Ensure that we got no more updates after returning false and the bounds are not updated
+ // to the end value
+ assertFalse(mTarget.mBoundsUpdated);
+ assertNotEquals(BOUNDS_FLOATING, mTarget.mStackBounds);
+ assertNotEquals(BOUNDS_FLOATING, mTarget.mTaskBounds);
+ // Ensure that we received the animation end call
+ assertTrue(mTarget.mAnimationEnded);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testCancelAnimationFromNewAnimationToExistingBounds() throws Exception {
+ // Create and start the animation
+ mTarget.reinitialize(BOUNDS_FULL, null);
+ final BoundsAnimator boundsAnimator = mController.animateBoundsImpl(mTarget, BOUNDS_FULL,
+ BOUNDS_FLOATING, DURATION, !MOVE_TO_FULLSCREEN);
+
+ // Drive some animation updates
+ boundsAnimator.onAnimationUpdate(mAnimator.getWithValue(0.5f));
+
+ // Cancel the animation as a restart to the same bounds
+ mTarget.reinitialize(null, null);
+ final BoundsAnimator altBoundsAnimator = mController.animateBoundsImpl(mTarget, BOUNDS_FULL,
+ BOUNDS_FLOATING, DURATION, !MOVE_TO_FULLSCREEN);
+ // Ensure the animator is the same
+ assertSame(boundsAnimator, altBoundsAnimator);
+ // Ensure we haven't restarted or finished the animation
+ assertFalse(mTarget.mAnimationStarted);
+ assertFalse(mTarget.mAnimationEnded);
+ // Ensure that we haven't tried to update the PiP mode
+ assertFalse(mTarget.mUpdatedPictureInPictureModeWithBounds);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testCancelAnimationFromNewAnimationToNewBounds() throws Exception {
+ // Create and start the animation
+ mTarget.reinitialize(BOUNDS_FULL, null);
+ final BoundsAnimator boundsAnimator = mController.animateBoundsImpl(mTarget, BOUNDS_FULL,
+ BOUNDS_FLOATING, DURATION, !MOVE_TO_FULLSCREEN);
+
+ // Drive some animation updates
+ boundsAnimator.onAnimationUpdate(mAnimator.getWithValue(0.5f));
+
+ // Cancel the animation as a restart to new bounds
+ mTarget.reinitialize(null, null);
+ final BoundsAnimator altBoundsAnimator = mController.animateBoundsImpl(mTarget, BOUNDS_FULL,
+ BOUNDS_ALT_FLOATING, DURATION, !MOVE_TO_FULLSCREEN);
+ // Ensure the animator is not the same
+ assertNotSame(boundsAnimator, altBoundsAnimator);
+ // Ensure that we did not get an animation start/end callback
+ assertFalse(mTarget.mAnimationStarted);
+ assertFalse(mTarget.mAnimationEnded);
+ // Ensure that we haven't tried to update the PiP mode
+ assertFalse(mTarget.mUpdatedPictureInPictureModeWithBounds);
+ }
+
+ /**
+ * @return the bounds offset to zero/zero.
+ */
+ private Rect offsetToZero(Rect bounds) {
+ mTmpRect.set(bounds);
+ mTmpRect.offsetTo(0, 0);
+ return mTmpRect;
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java
index 290f69a..c61076d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java
@@ -79,18 +79,6 @@
assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, 0 /* userId */,
false /* restoreFromDisk */, false /* reducedResolution */));
mCache.onAppDied(window.mAppToken);
-
- // Should still be in the retrieval cache.
- assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, 0 /* userId */,
- false /* restoreFromDisk */, false /* reducedResolution */));
-
- // Trash retrieval cache.
- for (int i = 0; i < 20; i++) {
- mCache.putSnapshot(createWindow(null, FIRST_APPLICATION_WINDOW, "window").getTask(),
- createSnapshot());
- }
-
- // Should not be in cache anymore
assertNull(mCache.getSnapshot(window.getTask().mTaskId, 0 /* userId */,
false /* restoreFromDisk */, false /* reducedResolution */));
}
@@ -134,9 +122,5 @@
// Load it from disk
assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, sWm.mCurrentUserId,
true /* restoreFromDisk */, false /* reducedResolution */));
-
- // Make sure it's in the cache now.
- assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, sWm.mCurrentUserId,
- false /* restoreFromDisk */, false /* reducedResolution */));
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index aab75ee..717ddf2 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -16,6 +16,9 @@
package com.android.server.wm;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
@@ -24,15 +27,19 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
+import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.GraphicBuffer;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import android.view.Surface;
-import org.junit.Before;
+import com.android.server.wm.TaskSnapshotSurface.Window;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -48,59 +55,174 @@
private TaskSnapshotSurface mSurface;
- @Before
- public void setUp() {
- mSurface = new TaskSnapshotSurface(null, null, null, Color.WHITE);
+ private void setupSurface(int width, int height, Rect contentInsets, int sysuiVis,
+ int windowFlags, Rect taskBounds) {
+ final GraphicBuffer buffer = GraphicBuffer.create(width, height, PixelFormat.RGBA_8888,
+ GraphicBuffer.USAGE_SW_READ_NEVER | GraphicBuffer.USAGE_SW_WRITE_NEVER);
+ final TaskSnapshot snapshot = new TaskSnapshot(buffer,
+ ORIENTATION_PORTRAIT, contentInsets, false, 1.0f);
+ mSurface = new TaskSnapshotSurface(sWm, new Window(), new Surface(), snapshot, "Test",
+ Color.WHITE, Color.RED, Color.BLUE, sysuiVis, windowFlags, 0, taskBounds);
+ }
+
+ private void setupSurface(int width, int height) {
+ setupSurface(width, height, new Rect(), 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, width, height));
}
@Test
public void fillEmptyBackground_fillHorizontally() throws Exception {
+ setupSurface(200, 100);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(200);
when(mockCanvas.getHeight()).thenReturn(100);
- final Bitmap b = Bitmap.createBitmap(100, 200, Config.ARGB_8888);
- mSurface.fillEmptyBackground(mockCanvas, b);
+ mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 200));
verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
}
@Test
public void fillEmptyBackground_fillVertically() throws Exception {
+ setupSurface(100, 200);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(200);
- final Bitmap b = Bitmap.createBitmap(200, 100, Config.ARGB_8888);
- mSurface.fillEmptyBackground(mockCanvas, b);
+ mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 100));
verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(100.0f), eq(200.0f), any());
}
@Test
public void fillEmptyBackground_fillBoth() throws Exception {
+ setupSurface(200, 200);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(200);
when(mockCanvas.getHeight()).thenReturn(200);
- final Bitmap b = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
- mSurface.fillEmptyBackground(mockCanvas, b);
+ mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(200.0f), eq(200.0f), any());
}
@Test
public void fillEmptyBackground_dontFill_sameSize() throws Exception {
+ setupSurface(100, 100);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- final Bitmap b = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
- mSurface.fillEmptyBackground(mockCanvas, b);
+ mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
}
@Test
public void fillEmptyBackground_dontFill_bitmapLarger() throws Exception {
+ setupSurface(100, 100);
final Canvas mockCanvas = mock(Canvas.class);
when(mockCanvas.getWidth()).thenReturn(100);
when(mockCanvas.getHeight()).thenReturn(100);
- final Bitmap b = Bitmap.createBitmap(200, 200, Config.ARGB_8888);
- mSurface.fillEmptyBackground(mockCanvas, b);
+ mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 200));
verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
}
+
+ @Test
+ public void testCalculateSnapshotCrop() {
+ setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 0, 100, 100));
+ assertEquals(new Rect(0, 0, 100, 90), mSurface.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotCrop_taskNotOnTop() {
+ setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 50, 100, 100));
+ assertEquals(new Rect(0, 10, 100, 90), mSurface.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotCrop_navBarLeft() {
+ setupSurface(100, 100, new Rect(10, 10, 0, 0), 0, 0, new Rect(0, 0, 100, 100));
+ assertEquals(new Rect(10, 0, 100, 100), mSurface.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotCrop_navBarRight() {
+ setupSurface(100, 100, new Rect(0, 10, 10, 0), 0, 0, new Rect(0, 0, 100, 100));
+ assertEquals(new Rect(0, 0, 90, 100), mSurface.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotFrame() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(0, 10, 0, 10);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ assertEquals(new Rect(0, -10, 100, 70),
+ mSurface.calculateSnapshotFrame(new Rect(0, 10, 100, 90)));
+ }
+
+ @Test
+ public void testCalculateSnapshotFrame_navBarLeft() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(10, 10, 0, 0);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ assertEquals(new Rect(0, -10, 90, 80),
+ mSurface.calculateSnapshotFrame(new Rect(10, 10, 100, 100)));
+ }
+
+ @Test
+ public void testDrawStatusBarBackground() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(0, 10, 10, 0);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 50, 100), 10);
+ verify(mockCanvas).drawRect(eq(50.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
+ }
+
+ @Test
+ public void testDrawStatusBarBackground_nope() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(0, 10, 10, 0);
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 100, 100), 10);
+ verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
+ }
+
+ @Test
+ public void testDrawNavigationBarBackground() {
+ final Rect insets = new Rect(0, 10, 0, 10);
+ setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, 100, 100));
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.drawNavigationBarBackground(mockCanvas);
+ verify(mockCanvas).drawRect(eq(new Rect(0, 90, 100, 100)), any());
+ }
+
+ @Test
+ public void testDrawNavigationBarBackground_left() {
+ final Rect insets = new Rect(10, 10, 0, 0);
+ setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, 100, 100));
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.drawNavigationBarBackground(mockCanvas);
+ verify(mockCanvas).drawRect(eq(new Rect(0, 0, 10, 100)), any());
+ }
+
+ @Test
+ public void testDrawNavigationBarBackground_right() {
+ final Rect insets = new Rect(0, 10, 10, 0);
+ setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, 100, 100));
+ mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mSurface.drawNavigationBarBackground(mockCanvas);
+ verify(mockCanvas).drawRect(eq(new Rect(90, 0, 100, 100)), any());
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
index 1819c56..98d20a2 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
@@ -89,7 +89,7 @@
boolean gotException = false;
try {
- taskController.reparent(stackController1, 0);
+ taskController.reparent(stackController1, 0, false/* moveParents */);
} catch (IllegalArgumentException e) {
gotException = true;
}
@@ -100,14 +100,14 @@
stackController3.setContainer(null);
gotException = false;
try {
- taskController.reparent(stackController3, 0);
+ taskController.reparent(stackController3, 0, false/* moveParents */);
} catch (IllegalArgumentException e) {
gotException = true;
}
assertTrue("Should not be able to reparent to a stack that doesn't have a container",
gotException);
- taskController.reparent(stackController2, 0);
+ taskController.reparent(stackController2, 0, false/* moveParents */);
assertEquals(stackController2.mContainer, taskController.mContainer.getParent());
assertEquals(0, ((WindowTestUtils.TestTask) taskController.mContainer).positionInParent());
assertEquals(1, ((WindowTestUtils.TestTask) taskController2.mContainer).positionInParent());
@@ -135,7 +135,7 @@
(WindowTestUtils.TestTask) taskController2.mContainer;
// Reparent and check state
- taskController.reparent(stack2Controller, 0);
+ taskController.reparent(stack2Controller, 0, false /* moveParents */);
assertEquals(stack2, task1.getParent());
assertEquals(0, task1.positionInParent());
assertEquals(1, task2.positionInParent());
diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java
index 3f39e4f..5ad7f80 100644
--- a/services/usage/java/com/android/server/usage/StorageStatsService.java
+++ b/services/usage/java/com/android/server/usage/StorageStatsService.java
@@ -162,6 +162,9 @@
return FileUtils.roundStorageSize(mStorage.getPrimaryStorageSize());
} else {
final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid);
+ if (vol == null) {
+ throw new IllegalStateException("Volume was unexpected null");
+ }
return FileUtils.roundStorageSize(vol.disk.size);
}
}
@@ -185,6 +188,9 @@
return Environment.getDataDirectory().getUsableSpace() + cacheBytes;
} else {
final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid);
+ if (vol == null) {
+ throw new IllegalStateException("Volume was unexpected null");
+ }
return vol.getPath().getUsableSpace() + cacheBytes;
}
}
diff --git a/services/usb/Android.mk b/services/usb/Android.mk
index f560e71..f6d212b 100644
--- a/services/usb/Android.mk
+++ b/services/usb/Android.mk
@@ -8,7 +8,7 @@
$(call all-java-files-under,java)
LOCAL_JAVA_LIBRARIES := services.core
-LOCAL_STATIC_JAVA_LIBRARIES := android.hardware.usb@1.0-java-static \
-android.hidl.manager@1.0-java-static
+LOCAL_STATIC_JAVA_LIBRARIES := android.hardware.usb-V1.0-java-static \
+android.hidl.manager-V1.0-java-static
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index 01e36f5..93cfd11 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -543,9 +543,8 @@
}
@Override
- public boolean onPackageChanged(String packageName, int uid, String[] components) {
+ public void onPackageUpdateFinished(String packageName, int uid) {
handlePackageUpdate(packageName);
- return false;
}
@Override
@@ -1207,8 +1206,11 @@
boolean changed = false;
for (DeviceFilter test : mDevicePreferenceMap.keySet()) {
if (filter.matches(test)) {
- mDevicePreferenceMap.remove(test);
- changed = true;
+ UserPackage currentMatch = mDevicePreferenceMap.get(test);
+ if (!currentMatch.packageName.equals(packageName)) {
+ mDevicePreferenceMap.remove(test);
+ changed = true;
+ }
}
}
return changed;
@@ -1218,8 +1220,11 @@
boolean changed = false;
for (AccessoryFilter test : mAccessoryPreferenceMap.keySet()) {
if (filter.matches(test)) {
- mAccessoryPreferenceMap.remove(test);
- changed = true;
+ UserPackage currentMatch = mAccessoryPreferenceMap.get(test);
+ if (!currentMatch.packageName.equals(packageName)) {
+ mAccessoryPreferenceMap.remove(test);
+ changed = true;
+ }
}
}
return changed;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index dc4b41c..6c4ced4 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -302,9 +302,13 @@
ComponentName curInteractor = !TextUtils.isEmpty(curInteractorStr)
? ComponentName.unflattenFromString(curInteractorStr) : null;
try {
- recognizerInfo = pm.getServiceInfo(curRecognizer, 0, userHandle);
+ recognizerInfo = pm.getServiceInfo(curRecognizer,
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
if (curInteractor != null) {
- interactorInfo = pm.getServiceInfo(curInteractor, 0, userHandle);
+ interactorInfo = pm.getServiceInfo(curInteractor,
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
}
} catch (RemoteException e) {
}
@@ -492,7 +496,9 @@
ComponentName findAvailRecognizer(String prefPackage, int userHandle) {
List<ResolveInfo> available =
mContext.getPackageManager().queryIntentServicesAsUser(
- new Intent(RecognitionService.SERVICE_INTERFACE), 0, userHandle);
+ new Intent(RecognitionService.SERVICE_INTERFACE),
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
int numAvailable = available.size();
if (numAvailable == 0) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 8bfe413..1874d8d 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -755,6 +755,32 @@
}
/**
+ * Returns a list of {@link PhoneAccountHandle}s for self-managed {@link ConnectionService}s.
+ * <p>
+ * Self-Managed {@link ConnectionService}s have a {@link PhoneAccount} with
+ * {@link PhoneAccount#CAPABILITY_SELF_MANAGED}.
+ * <p>
+ * Requires permission {@link android.Manifest.permission#READ_PHONE_STATE}, or that the caller
+ * is the default dialer app.
+ * <p>
+ * A {@link SecurityException} will be thrown if a called is not the default dialer, or lacks
+ * the {@link android.Manifest.permission#READ_PHONE_STATE} permission.
+ *
+ * @return A list of {@code PhoneAccountHandle} objects.
+ */
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ public List<PhoneAccountHandle> getSelfManagedPhoneAccounts() {
+ try {
+ if (isServiceConnected()) {
+ return getTelecomService().getSelfManagedPhoneAccounts(mContext.getOpPackageName());
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecomService#getSelfManagedPhoneAccounts()", e);
+ }
+ return new ArrayList<>();
+ }
+
+ /**
* Returns a list of {@link PhoneAccountHandle}s including those which have not been enabled
* by the user.
*
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 8740224..8ebac2c 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -59,6 +59,11 @@
boolean includeDisabledAccounts, String callingPackage);
/**
+ * @see TelecomServiceImpl#getSelfManagedPhoneAccounts
+ */
+ List<PhoneAccountHandle> getSelfManagedPhoneAccounts(String callingPackage);
+
+ /**
* @see TelecomManager#getPhoneAccountsSupportingScheme
*/
List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(in String uriScheme,
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 1fd1929..397aa00 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -628,8 +628,14 @@
* @see #EXTRA_DATA_IFACE
* @see #EXTRA_DATA_FAILURE_CAUSE
* @hide
+ *
+ * @deprecated If the app is running in the background, it won't be able to receive this
+ * broadcast. Apps should use ConnectivityManager {@link #registerNetworkCallback(
+ * android.net.NetworkRequest, ConnectivityManager.NetworkCallback)} to listen for network
+ * changes.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @Deprecated
public static final String ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED =
"android.intent.action.PRECISE_DATA_CONNECTION_STATE_CHANGED";
@@ -1087,14 +1093,15 @@
* this method will return null. The implementation must not to try add LTE
* identifiers into the existing cdma/gsm classes.
*<p>
- * In the future this call will be deprecated.
- *<p>
* @return Current location of the device or null if not available.
*
* <p>Requires Permission:
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION}.
+ *
+ * @deprecated use {@link #getAllCellInfo} instead, which returns a superset of this API.
*/
+ @Deprecated
public CellLocation getCellLocation() {
try {
ITelephony telephony = getITelephony();
@@ -2703,19 +2710,12 @@
* @param phoneAccountHandle the phone account to change the client state
* @param enabled the new state of the client
* @hide
+ * @deprecated Visual voicemail no longer in telephony. {@link VisualVoicemailService} should
+ * be implemented instead.
*/
@SystemApi
public void setVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle, boolean enabled){
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- telephony.setVisualVoicemailEnabled(mContext.getOpPackageName(), phoneAccountHandle,
- enabled);
- }
- } catch (RemoteException ex) {
- } catch (NullPointerException ex) {
- // This could happen before phone restarts due to crashing
- }
+
}
/**
@@ -2727,19 +2727,11 @@
* @param phoneAccountHandle the phone account to check for.
* @return {@code true} when the visual voicemail client is enabled for this client
* @hide
+ * @deprecated Visual voicemail no longer in telephony. {@link VisualVoicemailService} should
+ * be implemented instead.
*/
@SystemApi
public boolean isVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle){
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- return telephony.isVisualVoicemailEnabled(
- mContext.getOpPackageName(), phoneAccountHandle);
- }
- } catch (RemoteException ex) {
- } catch (NullPointerException ex) {
- // This could happen before phone restarts due to crashing
- }
return false;
}
@@ -3643,9 +3635,28 @@
*
* @param AID Application id. See ETSI 102.221 and 101.220.
* @return an IccOpenLogicalChannelResponse object.
+ * @deprecated Replaced by {@link #iccOpenLogicalChannel(String, int)}
*/
+ @Deprecated
public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID) {
- return iccOpenLogicalChannel(getSubId(), AID);
+ return iccOpenLogicalChannel(getSubId(), AID, -1);
+ }
+
+ /**
+ * Opens a logical channel to the ICC card.
+ *
+ * Input parameters equivalent to TS 27.007 AT+CCHO command.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+ *
+ * @param AID Application id. See ETSI 102.221 and 101.220.
+ * @param p2 P2 parameter (described in ISO 7816-4).
+ * @return an IccOpenLogicalChannelResponse object.
+ */
+ public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID, int p2) {
+ return iccOpenLogicalChannel(getSubId(), AID, p2);
}
/**
@@ -3659,14 +3670,15 @@
*
* @param subId The subscription to use.
* @param AID Application id. See ETSI 102.221 and 101.220.
+ * @param p2 P2 parameter (described in ISO 7816-4).
* @return an IccOpenLogicalChannelResponse object.
* @hide
*/
- public IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID) {
+ public IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID, int p2) {
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.iccOpenLogicalChannel(subId, AID);
+ return telephony.iccOpenLogicalChannel(subId, AID, p2);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -6451,5 +6463,33 @@
return null;
}
+
+ /**
+ * Check if phone is in emergency callback mode
+ * @return true if phone is in emergency callback mode
+ * @hide
+ */
+ public boolean getEmergencyCallbackMode() {
+ return getEmergencyCallbackMode(getSubId());
+ }
+
+ /**
+ * Check if phone is in emergency callback mode
+ * @return true if phone is in emergency callback mode
+ * @param subId the subscription ID that this action applies to.
+ * @hide
+ */
+ public boolean getEmergencyCallbackMode(int subId) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony == null) {
+ return false;
+ }
+ return telephony.getEmergencyCallbackMode(subId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#getEmergencyCallbackMode", e);
+ }
+ return false;
+ }
}
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index f1f683c..ba70374 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -16,7 +16,9 @@
package android.telephony.ims;
+import android.annotation.SystemApi;
import android.app.PendingIntent;
+import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.IBinder;
@@ -72,26 +74,30 @@
* {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}.
*
* The features that are currently supported in an ImsService are:
- * - RCS_FEATURE: This ImsService implements the {@link RcsFeature} class.
- * - MMTEL_FEATURE: This ImsService implements the {@link MMTelFeature} class.
- * - EMERGENCY_MMTEL_FEATURE: This ImsService implements the {@link MMTelFeature} class and will be
+ * - RCS_FEATURE: This ImsService implements the RcsFeature class.
+ * - MMTEL_FEATURE: This ImsService implements the MMTelFeature class.
+ * - EMERGENCY_MMTEL_FEATURE: This ImsService implements the MMTelFeature class and will be
* available to place emergency calls at all times. This MUST be implemented by the default
* ImsService provided in the device overlay.
- *
- * @hide
+ * @hide
*/
-public abstract class ImsService extends ImsServiceBase {
+@SystemApi
+public class ImsService extends Service {
private static final String LOG_TAG = "ImsService";
/**
* The intent that must be defined as an intent-filter in the AndroidManifest of the ImsService.
+ * @hide
*/
public static final String SERVICE_INTERFACE = "android.telephony.ims.ImsService";
// A map of slot Id -> Set of features corresponding to that slot.
private final SparseArray<SparseArray<ImsFeature>> mFeatures = new SparseArray<>();
+ /**
+ * @hide
+ */
// Implements all supported features as a flat interface.
protected final IBinder mImsServiceController = new IImsServiceController.Stub() {
@@ -328,6 +334,9 @@
};
+ /**
+ * @hide
+ */
@Override
public IBinder onBind(Intent intent) {
if(SERVICE_INTERFACE.equals(intent.getAction())) {
@@ -409,12 +418,18 @@
return null;
}
+ /**
+ * @hide
+ */
@VisibleForTesting
// Be sure to lock on mFeatures before accessing this method
public SparseArray<ImsFeature> getImsFeatureMap(int slotId) {
return mFeatures.get(slotId);
}
+ /**
+ * @hide
+ */
@VisibleForTesting
// Be sure to lock on mFeatures before accessing this method
public ImsFeature getImsFeatureFromType(SparseArray<ImsFeature> set, int featureType) {
@@ -451,17 +466,26 @@
/**
* @return An implementation of MMTelFeature that will be used by the system for MMTel
* functionality. Must be able to handle emergency calls at any time as well.
+ * @hide
*/
- public abstract MMTelFeature onCreateEmergencyMMTelImsFeature(int slotId);
+ public MMTelFeature onCreateEmergencyMMTelImsFeature(int slotId) {
+ return null;
+ }
/**
* @return An implementation of MMTelFeature that will be used by the system for MMTel
* functionality.
+ * @hide
*/
- public abstract MMTelFeature onCreateMMTelImsFeature(int slotId);
+ public MMTelFeature onCreateMMTelImsFeature(int slotId) {
+ return null;
+ }
/**
* @return An implementation of RcsFeature that will be used by the system for RCS.
+ * @hide
*/
- public abstract RcsFeature onCreateRcsFeature(int slotId);
+ public RcsFeature onCreateRcsFeature(int slotId) {
+ return null;
+ }
}
diff --git a/telephony/java/android/telephony/ims/ImsServiceBase.java b/telephony/java/android/telephony/ims/ImsServiceBase.java
deleted file mode 100644
index bb36862..0000000
--- a/telephony/java/android/telephony/ims/ImsServiceBase.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.telephony.ims;
-
-import android.annotation.SystemApi;
-import android.app.Service;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.IBinder;
-
-/**
- * Base ImsService Implementation, which is used by the ImsResolver to bind. ImsServices that do not
- * need to provide an ImsService implementation but still wish to be managed by the ImsResolver
- * lifecycle may implement this class directly.
- * @hide
- */
-@SystemApi
-public class ImsServiceBase extends Service {
-
- /**
- * Binder connection that does nothing but keep the connection between this Service and the
- * framework active. If this service crashes, the framework will be notified.
- */
- private IBinder mConnection = new Binder();
-
- @Override
- public IBinder onBind(Intent intent) {
- return mConnection;
- }
-
-}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index db7e417..dd08f67 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -498,12 +498,6 @@
*/
boolean isConcurrentVoiceAndDataAllowed(int subId);
- oneway void setVisualVoicemailEnabled(String callingPackage,
- in PhoneAccountHandle accountHandle, boolean enabled);
-
- boolean isVisualVoicemailEnabled(String callingPackage,
- in PhoneAccountHandle accountHandle);
-
String getVisualVoicemailPackageName(String callingPackage, int subId);
// Not oneway, caller needs to make sure the vaule is set before receiving a SMS
@@ -623,9 +617,10 @@
*
* @param subId The subscription to use.
* @param AID Application id. See ETSI 102.221 and 101.220.
+ * @param p2 P2 parameter (described in ISO 7816-4).
* @return an IccOpenLogicalChannelResponse object.
*/
- IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID);
+ IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID, int p2);
/**
* Closes a previously opened logical channel to the ICC card.
@@ -1315,4 +1310,12 @@
* @param appType the icc application type, like {@link #APPTYPE_USIM}
*/
String[] getForbiddenPlmns(int subId, int appType);
+
+ /**
+ * Check if phone is in emergency callback mode
+ * @return true if phone is in emergency callback mode
+ * @param subId the subscription ID that this action applies to.
+ * @hide
+ */
+ boolean getEmergencyCallbackMode(int subId);
}
diff --git a/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/SinkActivity.java b/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/SinkActivity.java
index 6fe2cfb..fc1d47b 100644
--- a/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/SinkActivity.java
+++ b/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/SinkActivity.java
@@ -95,13 +95,13 @@
setContentView(R.layout.sink_activity);
- mLogTextView = (TextView) findViewById(R.id.logTextView);
+ mLogTextView = findViewById(R.id.logTextView);
mLogTextView.setMovementMethod(ScrollingMovementMethod.getInstance());
mLogger = new TextLogger();
- mFpsTextView = (TextView) findViewById(R.id.fpsTextView);
+ mFpsTextView = findViewById(R.id.fpsTextView);
- mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
+ mSurfaceView = findViewById(R.id.surfaceView);
mSurfaceView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
diff --git a/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/SourceActivity.java b/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/SourceActivity.java
index c59c958..a216102 100644
--- a/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/SourceActivity.java
+++ b/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/SourceActivity.java
@@ -63,7 +63,7 @@
setContentView(R.layout.source_activity);
- mLogTextView = (TextView) findViewById(R.id.logTextView);
+ mLogTextView = findViewById(R.id.logTextView);
mLogTextView.setMovementMethod(ScrollingMovementMethod.getInstance());
mLogger = new TextLogger();
mPresenter = new Presenter();
diff --git a/tests/ActivityTests/AndroidManifest.xml b/tests/ActivityTests/AndroidManifest.xml
index 64cdcf7..b381cbf 100644
--- a/tests/ActivityTests/AndroidManifest.xml
+++ b/tests/ActivityTests/AndroidManifest.xml
@@ -87,5 +87,13 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <activity android:name="CustomSplashscreenActivity"
+ android:label="CustomSplashscreen"
+ android:theme="@style/CustomSplashscreen">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/tests/ActivityTests/res/drawable/splashscreen.xml b/tests/ActivityTests/res/drawable/splashscreen.xml
new file mode 100644
index 0000000..01fb646
--- /dev/null
+++ b/tests/ActivityTests/res/drawable/splashscreen.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@drawable/icon"/>
+ </item>
+</layer-list>
\ No newline at end of file
diff --git a/tests/ActivityTests/res/values/themes.xml b/tests/ActivityTests/res/values/themes.xml
index b8dd830..c11d2e4 100644
--- a/tests/ActivityTests/res/values/themes.xml
+++ b/tests/ActivityTests/res/values/themes.xml
@@ -26,4 +26,7 @@
<item name="android:colorBackground">@color/blue</item>
<item name="android:windowBackground">@color/blue</item>
</style>
+ <style name="CustomSplashscreen" parent="@android:style/Theme.Material.Light.NoActionBar">
+ <item name="android:windowSplashscreenContent">@drawable/splashscreen</item>
+ </style>
</resources>
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/CustomSplashscreenActivity.java b/tests/ActivityTests/src/com/google/android/test/activity/CustomSplashscreenActivity.java
new file mode 100644
index 0000000..0683df6
--- /dev/null
+++ b/tests/ActivityTests/src/com/google/android/test/activity/CustomSplashscreenActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.google.android.test.activity;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.SystemClock;
+
+/**
+ * Activity for which we set a custom splash screen.
+ */
+public class CustomSplashscreenActivity extends Activity {
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ SystemClock.sleep(2000);
+ }
+}
diff --git a/tests/AmSlam/Android.mk b/tests/AmSlam/Android.mk
index 8dafac7..934bae0 100644
--- a/tests/AmSlam/Android.mk
+++ b/tests/AmSlam/Android.mk
@@ -21,7 +21,7 @@
LOCAL_PACKAGE_NAME := AmSlam
-LOCAL_SDK_VERSION := 21
+LOCAL_SDK_VERSION := current
LOCAL_MIN_SDK_VERSION := 21
LOCAL_JAVA_LANGUAGE_VERSION := 1.8
diff --git a/tests/AmSlam/src/test/amslam/MainActivity.java b/tests/AmSlam/src/test/amslam/MainActivity.java
index cce955e..17fca09 100644
--- a/tests/AmSlam/src/test/amslam/MainActivity.java
+++ b/tests/AmSlam/src/test/amslam/MainActivity.java
@@ -60,7 +60,7 @@
super.onCreate(savedInstanceState);
sAppContext = getApplicationContext();
setContentView(R.layout.activity_main);
- mOutput = (TextView) findViewById(R.id.output);
+ mOutput = findViewById(R.id.output);
PongReceiver.addListener(this);
findViewById(R.id.run).setOnClickListener(view -> {
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
index b88a885..f85e82d 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
@@ -75,7 +75,7 @@
setContentView(R.layout.main);
- mList = (ListView) findViewById(R.id.testlist);
+ mList = findViewById(R.id.testlist);
mList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
mList.setFocusableInTouchMode(true);
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/AutomaticActivity.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/AutomaticActivity.java
index 1ed4723..8ccd4e2 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/AutomaticActivity.java
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/AutomaticActivity.java
@@ -111,8 +111,8 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.automatic_layout);
- mSoftwareImageView = (ImageView) findViewById(R.id.software_image_view);
- mHardwareImageView = (ImageView) findViewById(R.id.hardware_image_view);
+ mSoftwareImageView = findViewById(R.id.software_image_view);
+ mHardwareImageView = findViewById(R.id.hardware_image_view);
onCreateCommon(mRunnable);
beginTest();
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java
index 8d8d9de..0dec1de 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java
@@ -57,7 +57,7 @@
getWindow().setBackgroundDrawable(new ColorDrawable(0xffefefef));
ResourceModifiers.init(getResources());
- mHardwareView = (MainView) findViewById(R.id.hardware_view);
+ mHardwareView = findViewById(R.id.hardware_view);
mHardwareView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mHardwareView.setBackgroundColor(Color.WHITE);
mHardwareView.addDrawCallback(mDrawCallback);
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
index 78e360b..723c460 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
@@ -162,19 +162,19 @@
// in res/layout/hello_activity.xml
setContentView(R.layout.main);
- mFgSpinner = (Spinner) findViewById(R.id.fgspinner);
+ mFgSpinner = findViewById(R.id.fgspinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, mAvailOpLabels);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mFgSpinner.setAdapter(adapter);
mFgSpinner.setOnItemSelectedListener(this);
- mBgSpinner = (Spinner) findViewById(R.id.bgspinner);
+ mBgSpinner = findViewById(R.id.bgspinner);
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, mAvailOpLabels);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mBgSpinner.setAdapter(adapter);
mBgSpinner.setOnItemSelectedListener(this);
- mLimitSpinner = (Spinner) findViewById(R.id.limitspinner);
+ mLimitSpinner = findViewById(R.id.limitspinner);
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, mLimitLabels);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
diff --git a/tests/HugeBackup/src/com/android/hugebackup/HugeBackupActivity.java b/tests/HugeBackup/src/com/android/hugebackup/HugeBackupActivity.java
index 84e31aa..83c27fb 100644
--- a/tests/HugeBackup/src/com/android/hugebackup/HugeBackupActivity.java
+++ b/tests/HugeBackup/src/com/android/hugebackup/HugeBackupActivity.java
@@ -71,9 +71,9 @@
setContentView(R.layout.backup_restore);
/** Once the UI has been inflated, cache the controls for later */
- mFillingGroup = (RadioGroup) findViewById(R.id.filling_group);
- mAddMayoCheckbox = (CheckBox) findViewById(R.id.mayo);
- mAddTomatoCheckbox = (CheckBox) findViewById(R.id.tomato);
+ mFillingGroup = findViewById(R.id.filling_group);
+ mAddMayoCheckbox = findViewById(R.id.mayo);
+ mAddTomatoCheckbox = findViewById(R.id.tomato);
/** Set up our file bookkeeping */
mDataFile = new File(getFilesDir(), HugeBackupActivity.DATA_FILE_NAME);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java b/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java
index eb4e3fd..492d158 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java
@@ -101,7 +101,7 @@
Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.date_picker, this, true);
- mDayPicker = (NumberPicker) findViewById(R.id.day);
+ mDayPicker = findViewById(R.id.day);
mDayPicker.setFormatter(NumberPicker.getTwoDigitFormatter());
mDayPicker.setOnLongPressUpdateInterval(100);
mDayPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
@@ -110,7 +110,7 @@
notifyDateChanged();
}
});
- mMonthPicker = (NumberPicker) findViewById(R.id.month);
+ mMonthPicker = findViewById(R.id.month);
mMonthPicker.setFormatter(NumberPicker.getTwoDigitFormatter());
DateFormatSymbols dfs = new DateFormatSymbols();
String[] months = dfs.getShortMonths();
@@ -146,7 +146,7 @@
updateDaySpinner();
}
});
- mYearPicker = (NumberPicker) findViewById(R.id.year);
+ mYearPicker = findViewById(R.id.year);
mYearPicker.setOnLongPressUpdateInterval(100);
mYearPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
@@ -158,7 +158,7 @@
}
});
- mYearToggle = (CheckBox) findViewById(R.id.yearToggle);
+ mYearToggle = findViewById(R.id.yearToggle);
mYearToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
@@ -229,7 +229,7 @@
/* Remove the 3 pickers from their parent and then add them back in the
* required order.
*/
- LinearLayout parent = (LinearLayout) findViewById(R.id.parent);
+ LinearLayout parent = findViewById(R.id.parent);
parent.removeAllViews();
boolean quoted = false;
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
index 0defe92..134c2e0 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
@@ -82,7 +82,7 @@
ListAdapter adapter = new SimpleListAdapter(this);
- final ListView list = (ListView) findViewById(R.id.list);
+ final ListView list = findViewById(R.id.list);
list.setAdapter(adapter);
registerForContextMenu(list);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/StackActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/StackActivity.java
index 5655adf..262b0e9 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/StackActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/StackActivity.java
@@ -35,7 +35,7 @@
setContentView(R.layout.stack);
- StackView stack = (StackView) findViewById(R.id.stack_view);
+ StackView stack = findViewById(R.id.stack_view);
stack.setAdapter(new ArrayAdapter<Drawable>(this, android.R.layout.simple_list_item_1,
android.R.id.text1, new Drawable[] {
getResources().getDrawable(R.drawable.sunset1),
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TransformsAndAnimationsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TransformsAndAnimationsActivity.java
index 684d179..b5a5e02 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TransformsAndAnimationsActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TransformsAndAnimationsActivity.java
@@ -55,23 +55,23 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.transforms_and_animations);
- button1 = (Button) findViewById(R.id.button1);
- button2 = (Button) findViewById(R.id.button2);
- button3 = (Button) findViewById(R.id.button3);
- button1a = (Button) findViewById(R.id.button1a);
- button2a = (Button) findViewById(R.id.button2a);
- button3a = (Button) findViewById(R.id.button3a);
- button1b = (Button) findViewById(R.id.button1b);
- button2b = (Button) findViewById(R.id.button2b);
- button3b = (Button) findViewById(R.id.button3b);
- button4 = (Button) findViewById(R.id.button4);
- button5 = (Button) findViewById(R.id.button5);
- button6 = (Button) findViewById(R.id.button6);
- button7 = (Button) findViewById(R.id.button7);
- button8 = (Button) findViewById(R.id.button8);
- layersNoneCB = (CheckBox) findViewById(R.id.layersNoneCB);
- layersHardwareCB = (CheckBox) findViewById(R.id.layersHwCB);
- layersSoftwareCB = (CheckBox) findViewById(R.id.layersSwCB);
+ button1 = findViewById(R.id.button1);
+ button2 = findViewById(R.id.button2);
+ button3 = findViewById(R.id.button3);
+ button1a = findViewById(R.id.button1a);
+ button2a = findViewById(R.id.button2a);
+ button3a = findViewById(R.id.button3a);
+ button1b = findViewById(R.id.button1b);
+ button2b = findViewById(R.id.button2b);
+ button3b = findViewById(R.id.button3b);
+ button4 = findViewById(R.id.button4);
+ button5 = findViewById(R.id.button5);
+ button6 = findViewById(R.id.button6);
+ button7 = findViewById(R.id.button7);
+ button8 = findViewById(R.id.button8);
+ layersNoneCB = findViewById(R.id.layersNoneCB);
+ layersHardwareCB = findViewById(R.id.layersHwCB);
+ layersSoftwareCB = findViewById(R.id.layersSwCB);
layersNoneCB.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
@Override
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
index ffb8689..deb8585 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
@@ -84,7 +84,7 @@
ListAdapter adapter = new SimpleListAdapter(this);
- ListView list = (ListView) findViewById(R.id.list);
+ ListView list = findViewById(R.id.list);
list.setAdapter(adapter);
list.setCacheColorHint(0);
list.setVerticalFadingEdgeEnabled(true);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayerInvalidationActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayerInvalidationActivity.java
index 6d47d6c..a261fb7 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayerInvalidationActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayerInvalidationActivity.java
@@ -49,13 +49,13 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.view_layer_invalidation);
- container = (LinearLayout) findViewById(R.id.container);
- final LinearLayout container1 = (LinearLayout) findViewById(R.id.container1);
- final LinearLayout container2 = (LinearLayout) findViewById(R.id.container2);
- final LinearLayout container3 = (LinearLayout) findViewById(R.id.container3);
- nestedStatusTV = (TextView) findViewById(R.id.nestedStatus);
- invalidateStatusTV = (TextView) findViewById(R.id.invalidateStatus);
- final TextView tva = (TextView) findViewById(R.id.textviewa);
+ container = findViewById(R.id.container);
+ final LinearLayout container1 = findViewById(R.id.container1);
+ final LinearLayout container2 = findViewById(R.id.container2);
+ final LinearLayout container3 = findViewById(R.id.container3);
+ nestedStatusTV = findViewById(R.id.nestedStatus);
+ invalidateStatusTV = findViewById(R.id.invalidateStatus);
+ final TextView tva = findViewById(R.id.textviewa);
topLayouts.add(container1);
topLayouts.add(container2);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
index 7168478..07dc0a1 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
@@ -94,7 +94,7 @@
}
private void setupList(int listId) {
- final ListView list = (ListView) findViewById(listId);
+ final ListView list = findViewById(listId);
list.setAdapter(new SimpleListAdapter(this));
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java
index e65dd63..96cf43e 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java
@@ -39,7 +39,7 @@
}
private void setupList(int listId) {
- final ListView list = (ListView) findViewById(listId);
+ final ListView list = findViewById(listId);
list.setAdapter(new SimpleListAdapter(this));
list.setLayerType(View.LAYER_TYPE_HARDWARE, null);
((View) list.getParent()).setLayerType(View.LAYER_TYPE_HARDWARE, null);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java
index 17f78af..1f3f874 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java
@@ -47,7 +47,7 @@
}
private void setupList(int listId) {
- final ListView list = (ListView) findViewById(listId);
+ final ListView list = findViewById(listId);
list.setAdapter(new SimpleListAdapter(this));
list.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
index 2dd7b6a..715da20 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
@@ -113,7 +113,7 @@
}
private void setupList(int listId) {
- final ListView list = (ListView) findViewById(listId);
+ final ListView list = findViewById(listId);
list.setAdapter(new SimpleListAdapter(this));
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java
index 738801d..9ae3811 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java
@@ -60,12 +60,12 @@
startAnim(R.id.imageview);
startAnim(myViewAlphaDefault);
startAnim(myViewAlphaHandled);
- EditText selectedText = (EditText) findViewById(R.id.selectedtext);
+ EditText selectedText = findViewById(R.id.selectedtext);
selectedText.setSelection(3, 8);
}
}, 2000);
- Button invalidator = (Button) findViewById(R.id.invalidateButton);
+ Button invalidator = findViewById(R.id.invalidateButton);
invalidator.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -74,7 +74,7 @@
}
});
- TextView textView = (TextView) findViewById(R.id.spantext);
+ TextView textView = findViewById(R.id.spantext);
if (textView != null) {
SpannableStringBuilder text =
new SpannableStringBuilder("Now this is a short text message with spans");
@@ -93,7 +93,7 @@
textView.setText(text);
}
- LinearLayout container = (LinearLayout) findViewById(R.id.container);
+ LinearLayout container = findViewById(R.id.container);
myViewAlphaDefault = new MyView(this, false);
myViewAlphaDefault.setLayoutParams(new LinearLayout.LayoutParams(75, 75));
container.addView(myViewAlphaDefault);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ZOrderingActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ZOrderingActivity.java
index 45e77ed..08979bc 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ZOrderingActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ZOrderingActivity.java
@@ -12,7 +12,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.z_ordering);
- ViewGroup grandParent = (ViewGroup) findViewById(R.id.parent);
+ ViewGroup grandParent = findViewById(R.id.parent);
if (grandParent == null) throw new IllegalStateException();
View.OnClickListener l = new View.OnClickListener() {
@Override
diff --git a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java
index 292bbd2..6115fd5 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java
@@ -50,7 +50,7 @@
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line, COUNTRIES);
- AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.edit);
+ AutoCompleteTextView textView = findViewById(R.id.edit);
textView.setAdapter(adapter);
}
diff --git a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java
index 570cb6b..253c50f 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java
@@ -45,7 +45,7 @@
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line, COUNTRIES);
- AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.edit);
+ AutoCompleteTextView textView = findViewById(R.id.edit);
textView.setAdapter(adapter);
}
diff --git a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java
index 5aa0d4f..51cdbb5 100644
--- a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java
+++ b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java
@@ -56,16 +56,16 @@
stopJobColor = getColor(R.color.stop_received);
// Set up UI.
- mShowStartView = (TextView) findViewById(R.id.onstart_textview);
- mShowStopView = (TextView) findViewById(R.id.onstop_textview);
- mParamsTextView = (TextView) findViewById(R.id.task_params);
- mDelayEditText = (EditText) findViewById(R.id.delay_time);
- mDeadlineEditText = (EditText) findViewById(R.id.deadline_time);
- mWiFiConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_unmetered);
- mAnyConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_any);
- mRequiresChargingCheckBox = (CheckBox) findViewById(R.id.checkbox_charging);
- mRequiresIdleCheckbox = (CheckBox) findViewById(R.id.checkbox_idle);
- mIsPersistedCheckbox = (CheckBox) findViewById(R.id.checkbox_persisted);
+ mShowStartView = findViewById(R.id.onstart_textview);
+ mShowStopView = findViewById(R.id.onstop_textview);
+ mParamsTextView = findViewById(R.id.task_params);
+ mDelayEditText = findViewById(R.id.delay_time);
+ mDeadlineEditText = findViewById(R.id.deadline_time);
+ mWiFiConnectivityRadioButton = findViewById(R.id.checkbox_unmetered);
+ mAnyConnectivityRadioButton = findViewById(R.id.checkbox_any);
+ mRequiresChargingCheckBox = findViewById(R.id.checkbox_charging);
+ mRequiresIdleCheckbox = findViewById(R.id.checkbox_idle);
+ mIsPersistedCheckbox = findViewById(R.id.checkbox_persisted);
mServiceComponent = new ComponentName(this, TestJobService.class);
// Start service and provide it a way to communicate with us.
diff --git a/tests/LargeAssetTest/src/com/android/largeassettest/LargeAssetTest.java b/tests/LargeAssetTest/src/com/android/largeassettest/LargeAssetTest.java
index e3a9cf4..612c53e 100644
--- a/tests/LargeAssetTest/src/com/android/largeassettest/LargeAssetTest.java
+++ b/tests/LargeAssetTest/src/com/android/largeassettest/LargeAssetTest.java
@@ -43,8 +43,8 @@
super.onCreate(icicle);
setContentView(R.layout.lat);
- mResultText = (TextView) findViewById(R.id.result);
- mValidateButton = (Button) findViewById(R.id.validate);
+ mResultText = findViewById(R.id.result);
+ mValidateButton = findViewById(R.id.validate);
mValidateButton.setOnClickListener(mClickListener);
}
diff --git a/tests/LowStorageTest/src/com/android/lowstoragetest/LowStorageTest.java b/tests/LowStorageTest/src/com/android/lowstoragetest/LowStorageTest.java
index 9f297aa..c0091ad 100644
--- a/tests/LowStorageTest/src/com/android/lowstoragetest/LowStorageTest.java
+++ b/tests/LowStorageTest/src/com/android/lowstoragetest/LowStorageTest.java
@@ -52,9 +52,9 @@
StatFs stat = new StatFs(path.getPath());
int totalBlocks = stat.getBlockCount();
mBlockSize = (int) (stat.getBlockSize());
- TextView startSizeTextView = (TextView) findViewById(R.id.totalsize);
+ TextView startSizeTextView = findViewById(R.id.totalsize);
startSizeTextView.setText(Long.toString((totalBlocks * mBlockSize) / BYTE_SIZE));
- Button button = (Button) findViewById(R.id.button_run);
+ Button button = findViewById(R.id.button_run);
button.setOnClickListener(mStartListener);
}
@@ -121,9 +121,9 @@
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
long availableBlocks = stat.getAvailableBlocks();
- TextView freeSizeTextView = (TextView) findViewById(R.id.freesize);
+ TextView freeSizeTextView = findViewById(R.id.freesize);
freeSizeTextView.setText(Long.toString((availableBlocks * mBlockSize) / BYTE_SIZE));
- TextView statusTextView = (TextView) findViewById(R.id.status);
+ TextView statusTextView = findViewById(R.id.status);
statusTextView.setText("Finished. You can start the test now.");
} catch (Exception e) {
Log.v(TAG, e.toString());
diff --git a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
index 2ff3e20..85cc8fb 100644
--- a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
+++ b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
@@ -68,16 +68,16 @@
mPlayer = new PlayerController(this, OnePlayerService.getServiceIntent(this));
- mStartButton = (Button) findViewById(R.id.start_button);
- mPlayButton = (Button) findViewById(R.id.play_button);
- mRouteButton = (Button) findViewById(R.id.route_button);
- mStatusView = (TextView) findViewById(R.id.status);
- mContentText = (EditText) findViewById(R.id.content);
- mNextContentText = (EditText) findViewById(R.id.next_content);
- mHasVideo = (CheckBox) findViewById(R.id.has_video);
- mArtView = (ImageView) findViewById(R.id.art);
+ mStartButton = findViewById(R.id.start_button);
+ mPlayButton = findViewById(R.id.play_button);
+ mRouteButton = findViewById(R.id.route_button);
+ mStatusView = findViewById(R.id.status);
+ mContentText = findViewById(R.id.content);
+ mNextContentText = findViewById(R.id.next_content);
+ mHasVideo = findViewById(R.id.has_video);
+ mArtView = findViewById(R.id.art);
- final Button artPicker = (Button) findViewById(R.id.art_picker);
+ final Button artPicker = findViewById(R.id.art_picker);
artPicker.setOnClickListener(mButtonListener);
mStartButton.setOnClickListener(mButtonListener);
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
index ee4c834..241206d 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
@@ -43,7 +43,7 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- ListView lv = (ListView) findViewById(android.R.id.list);
+ ListView lv = findViewById(android.R.id.list);
lv.setDrawSelectorOnTop(true);
lv.setAdapter(new SimpleAdapter(this, SAMPLES,
R.layout.item_layout, new String[] { KEY_NAME },
@@ -55,7 +55,7 @@
@Override
protected void onResume() {
super.onResume();
- ListView lv = (ListView) findViewById(android.R.id.list);
+ ListView lv = findViewById(android.R.id.list);
for (int i = 0; i < lv.getChildCount(); i++) {
lv.getChildAt(i).animate().translationY(0).setDuration(DURATION);
}
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/SubActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/SubActivity.java
index 892cbae..22fc691 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/SubActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/SubActivity.java
@@ -39,7 +39,7 @@
@Override
protected void onResume() {
super.onResume();
- ViewGroup container = (ViewGroup) findViewById(R.id.my_container);
+ ViewGroup container = findViewById(R.id.my_container);
int dx = getWindowManager().getDefaultDisplay().getWidth();
for (int i = 0; i < container.getChildCount(); i++) {
View child = container.getChildAt(i);
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestActivity.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestActivity.java
index 4841bc5..c3c4cf5 100644
--- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestActivity.java
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestActivity.java
@@ -81,14 +81,14 @@
super.onCreate(savedInstanceState);
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 = findViewById(R.id.console);
+ mScrollView = findViewById(R.id.scroller_id);
+ mRadioGroup = findViewById(R.id.model_group_id);
+ mPlayTriggerButton = findViewById(R.id.play_trigger_id);
mDebugView.setText(mDebugView.getText(), TextView.BufferType.EDITABLE);
mDebugView.setMovementMethod(new ScrollingMovementMethod());
- mCaptureAudioCheckBox = (CheckBox) findViewById(R.id.caputre_check_box);
- mPlayCapturedAudioButton = (Button) findViewById(R.id.play_captured_id);
+ mCaptureAudioCheckBox = findViewById(R.id.caputre_check_box);
+ mPlayCapturedAudioButton = findViewById(R.id.play_captured_id);
mHandler = new Handler();
mButtonModelUuidMap = new HashMap();
mModelButtons = new HashMap();
diff --git a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
index 7c13974..7632a6e 100644
--- a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
+++ b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
@@ -180,7 +180,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_touch_latency);
- mTouchView = (TouchLatencyView) findViewById(R.id.canvasView);
+ mTouchView = findViewById(R.id.canvasView);
}
diff --git a/tests/TransitionTests/src/com/android/transitiontests/ClippingText.java b/tests/TransitionTests/src/com/android/transitiontests/ClippingText.java
index 54c44e2..9985357 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/ClippingText.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/ClippingText.java
@@ -42,7 +42,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.clipping_text_1);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
mScene1 = Scene.getSceneForLayout(mSceneRoot, R.layout.clipping_text_1, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/ContactsExpansion.java b/tests/TransitionTests/src/com/android/transitiontests/ContactsExpansion.java
index f687da3..86ecf8e 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/ContactsExpansion.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/ContactsExpansion.java
@@ -49,7 +49,7 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.contacts_list);
- ViewGroup contactsContainer = (ViewGroup) findViewById(R.id.contactsContainer);
+ ViewGroup contactsContainer = findViewById(R.id.contactsContainer);
int contactsIndex = 0;
addContact(contactsContainer, contactsIndex, R.drawable.self_portrait_square_100);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/CrossFadeDemo.java b/tests/TransitionTests/src/com/android/transitiontests/CrossFadeDemo.java
index 5bb0e77..0d41d64 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/CrossFadeDemo.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/CrossFadeDemo.java
@@ -38,7 +38,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.crossfade);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
mScene1 = Scene.getSceneForLayout(mSceneRoot, R.layout.crossfade, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/CrossfadeImage.java b/tests/TransitionTests/src/com/android/transitiontests/CrossfadeImage.java
index 1f278b9..1fb732e 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/CrossfadeImage.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/CrossfadeImage.java
@@ -41,10 +41,10 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.crossfade_image);
- ViewGroup container = (ViewGroup) findViewById(R.id.container);
+ ViewGroup container = findViewById(R.id.container);
mSceneRoot = container;
- mImageView = (ImageView) findViewById(R.id.contact_picture);
+ mImageView = findViewById(R.id.contact_picture);
mImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
Crossfade mCrossfade = new Crossfade();
diff --git a/tests/TransitionTests/src/com/android/transitiontests/CrossfadeMultiple.java b/tests/TransitionTests/src/com/android/transitiontests/CrossfadeMultiple.java
index 469ee8b..15d15351 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/CrossfadeMultiple.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/CrossfadeMultiple.java
@@ -49,12 +49,12 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.crossfade_multiple);
- ViewGroup container = (ViewGroup) findViewById(R.id.container);
+ ViewGroup container = findViewById(R.id.container);
mSceneRoot = container;
- mButton = (Button) findViewById(R.id.button);
- mImageView = (ImageView) findViewById(R.id.imageview);
- mTextView = (TextView) findViewById(R.id.textview);
+ mButton = findViewById(R.id.button);
+ mImageView = findViewById(R.id.imageview);
+ mTextView = findViewById(R.id.textview);
mCrossfade = new Crossfade();
mCrossfade.addTarget(R.id.button).addTarget(R.id.textview).addTarget(R.id.imageview);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/Demo0.java b/tests/TransitionTests/src/com/android/transitiontests/Demo0.java
index d52ab1d..e172904 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/Demo0.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/Demo0.java
@@ -35,7 +35,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.search_screen);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
mCurrentScene = SEARCH_SCREEN;
diff --git a/tests/TransitionTests/src/com/android/transitiontests/Demo1.java b/tests/TransitionTests/src/com/android/transitiontests/Demo1.java
index 5b5eb15..e92dd03 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/Demo1.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/Demo1.java
@@ -40,7 +40,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.search_screen);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
// mResultsScreen = new MyScene(mSceneRoot, R.layout.results_screen);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/Demo2.java b/tests/TransitionTests/src/com/android/transitiontests/Demo2.java
index 0f3257b..c26723b 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/Demo2.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/Demo2.java
@@ -38,7 +38,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.search_screen);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
}
diff --git a/tests/TransitionTests/src/com/android/transitiontests/Demo3.java b/tests/TransitionTests/src/com/android/transitiontests/Demo3.java
index 0ffa1f5..094ab97 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/Demo3.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/Demo3.java
@@ -38,7 +38,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.search_screen);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
mSearchScreen = Scene.getSceneForLayout(mSceneRoot, R.layout.search_screen, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/Demo4.java b/tests/TransitionTests/src/com/android/transitiontests/Demo4.java
index 3aadbb0..af67f26 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/Demo4.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/Demo4.java
@@ -38,7 +38,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.search_screen);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
mSearchScreen = Scene.getSceneForLayout(mSceneRoot, R.layout.search_screen, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/Demo5.java b/tests/TransitionTests/src/com/android/transitiontests/Demo5.java
index c36abda..f01a29d 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/Demo5.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/Demo5.java
@@ -33,7 +33,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.search_screen);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
mSearchScreen = Scene.getSceneForLayout(mSceneRoot, R.layout.search_screen, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/FadingHierarchy.java b/tests/TransitionTests/src/com/android/transitiontests/FadingHierarchy.java
index d497abe..40bf975 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/FadingHierarchy.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/FadingHierarchy.java
@@ -34,11 +34,11 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.fading_hierarchy);
- mContainer = (ViewGroup) findViewById(R.id.container);
- mRemovingContainer = (ViewGroup) findViewById(R.id.removingContainer);
+ mContainer = findViewById(R.id.container);
+ mRemovingContainer = findViewById(R.id.removingContainer);
mInnerContainerParent = (ViewGroup) mRemovingContainer.getParent();
- mRemovingButton = (Button) findViewById(R.id.removingButton);
+ mRemovingButton = findViewById(R.id.removingButton);
}
public void sendMessage(View view) {
diff --git a/tests/TransitionTests/src/com/android/transitiontests/FadingTest.java b/tests/TransitionTests/src/com/android/transitiontests/FadingTest.java
index 29fb868..8307366 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/FadingTest.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/FadingTest.java
@@ -43,13 +43,13 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.fading_test);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
- mRemovingButton = (Button) findViewById(R.id.removingButton);
- mInvisibleButton = (Button) findViewById(R.id.invisibleButton);
- mGoneButton = (Button) findViewById(R.id.goneButton);
+ mRemovingButton = findViewById(R.id.removingButton);
+ mInvisibleButton = findViewById(R.id.invisibleButton);
+ mGoneButton = findViewById(R.id.goneButton);
mGoneButton.setOnClickListener(new View.OnClickListener() {
@Override
diff --git a/tests/TransitionTests/src/com/android/transitiontests/InstanceTargets.java b/tests/TransitionTests/src/com/android/transitiontests/InstanceTargets.java
index a06ba8f..025e4e3 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/InstanceTargets.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/InstanceTargets.java
@@ -37,7 +37,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.instance_targets);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container;
}
diff --git a/tests/TransitionTests/src/com/android/transitiontests/InterruptionTest.java b/tests/TransitionTests/src/com/android/transitiontests/InterruptionTest.java
index c26e93f..6186150 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/InterruptionTest.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/InterruptionTest.java
@@ -40,17 +40,17 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.interruption);
- ViewGroup sceneRoot = (ViewGroup) findViewById(R.id.sceneRoot);
+ ViewGroup sceneRoot = findViewById(R.id.sceneRoot);
mScene1 = Scene.getSceneForLayout(sceneRoot, R.layout.interruption_inner_1, this);
mScene2 = Scene.getSceneForLayout(sceneRoot, R.layout.interruption_inner_2, this);
mScene3 = Scene.getSceneForLayout(sceneRoot, R.layout.interruption_inner_3, this);
mScene4 = Scene.getSceneForLayout(sceneRoot, R.layout.interruption_inner_4, this);
- mScene1RB = (RadioButton) findViewById(R.id.scene1RB);
- mScene2RB = (RadioButton) findViewById(R.id.scene2RB);
- mScene3RB = (RadioButton) findViewById(R.id.scene3RB);
- mScene4RB = (RadioButton) findViewById(R.id.scene4RB);
+ mScene1RB = findViewById(R.id.scene1RB);
+ mScene2RB = findViewById(R.id.scene2RB);
+ mScene3RB = findViewById(R.id.scene3RB);
+ mScene4RB = findViewById(R.id.scene4RB);
ChangeBounds changeBounds1 = new ChangeBounds();
changeBounds1.addTarget(R.id.button);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/ListViewAddRemove.java b/tests/TransitionTests/src/com/android/transitiontests/ListViewAddRemove.java
index 251bf24..45b8286 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/ListViewAddRemove.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/ListViewAddRemove.java
@@ -47,9 +47,9 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.list_view_add_remove);
- final LinearLayout container = (LinearLayout) findViewById(R.id.container);
+ final LinearLayout container = findViewById(R.id.container);
- final ListView listview = (ListView) findViewById(R.id.listview);
+ final ListView listview = findViewById(R.id.listview);
for (int i = 0; i < 200; ++i) {
numList.add(Integer.toString(i));
}
diff --git a/tests/TransitionTests/src/com/android/transitiontests/LoginActivity.java b/tests/TransitionTests/src/com/android/transitiontests/LoginActivity.java
index 92bbb85..96b018b 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/LoginActivity.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/LoginActivity.java
@@ -40,7 +40,7 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
mLoginScene = Scene.getSceneForLayout(mSceneRoot, R.layout.activity_login, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/OverlayTest.java b/tests/TransitionTests/src/com/android/transitiontests/OverlayTest.java
index ef8cd37..384762b 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/OverlayTest.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/OverlayTest.java
@@ -32,12 +32,12 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.overlay_test);
- mContainer = (ViewGroup) findViewById(R.id.container);
+ mContainer = findViewById(R.id.container);
mRoot = (ViewGroup) mContainer.getParent();
}
public void onClick(View view) {
- final Button fadingButton = (Button) findViewById(R.id.fadingButton);
+ final Button fadingButton = findViewById(R.id.fadingButton);
if (fadingButton != null) {
mContainer.removeView(fadingButton);
mRoot.getOverlay().add(fadingButton);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/Reparenting.java b/tests/TransitionTests/src/com/android/transitiontests/Reparenting.java
index 1ee8621..772ddc7 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/Reparenting.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/Reparenting.java
@@ -34,9 +34,9 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.reparenting);
- ViewGroup container = (ViewGroup) findViewById(R.id.container);
- mContainer1 = (ViewGroup) findViewById(R.id.container1);
- mContainer2 = (ViewGroup) findViewById(R.id.container2);
+ ViewGroup container = findViewById(R.id.container);
+ mContainer1 = findViewById(R.id.container1);
+ mContainer2 = findViewById(R.id.container2);
System.out.println("container 1 and 2 " + mContainer1 + ", " + mContainer2);
setupButtons(0, mContainer1);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/ResourceLoadingTest.java b/tests/TransitionTests/src/com/android/transitiontests/ResourceLoadingTest.java
index 1aee258..96d3ae1 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/ResourceLoadingTest.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/ResourceLoadingTest.java
@@ -39,7 +39,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.search_screen);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
mCurrentScene = SEARCH_SCREEN;
diff --git a/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTargets.java b/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTargets.java
index 7504058..7ee4b3e 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTargets.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTargets.java
@@ -39,7 +39,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.search_screen);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
mSearchScreen = Scene.getSceneForLayout(mSceneRoot, R.layout.search_screen, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTransition.java b/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTransition.java
index 23b28ec..9333ea1 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTransition.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTransition.java
@@ -37,7 +37,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.search_screen);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
mSearchScreen = Scene.getSceneForLayout(mSceneRoot, R.layout.search_screen, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/ScenesTestv21.java b/tests/TransitionTests/src/com/android/transitiontests/ScenesTestv21.java
index ecf5ef3..a01f638 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/ScenesTestv21.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/ScenesTestv21.java
@@ -39,7 +39,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.search_screen);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
mSearchScreen = Scene.getSceneForLayout(mSceneRoot, R.layout.search_screen, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/SequenceTest.java b/tests/TransitionTests/src/com/android/transitiontests/SequenceTest.java
index c550e92..5f4560cc 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/SequenceTest.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/SequenceTest.java
@@ -41,12 +41,12 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.fading_test);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
- mRemovingButton = (Button) findViewById(R.id.removingButton);
- mInvisibleButton = (Button) findViewById(R.id.invisibleButton);
- mGoneButton = (Button) findViewById(R.id.goneButton);
+ mRemovingButton = findViewById(R.id.removingButton);
+ mInvisibleButton = findViewById(R.id.invisibleButton);
+ mGoneButton = findViewById(R.id.goneButton);
mScene1 = Scene.getSceneForLayout(mSceneRoot, R.layout.fading_test, this);
mScene2 = Scene.getSceneForLayout(mSceneRoot, R.layout.fading_test_scene_2, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/SequenceTestSimple.java b/tests/TransitionTests/src/com/android/transitiontests/SequenceTestSimple.java
index 92b169e..f478cb8 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/SequenceTestSimple.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/SequenceTestSimple.java
@@ -42,10 +42,10 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.fading_test_simple);
- View container = (View) findViewById(R.id.container);
+ View container = findViewById(R.id.container);
mSceneRoot = (ViewGroup) container.getParent();
- mRemovingButton = (Button) findViewById(R.id.removingButton);
+ mRemovingButton = findViewById(R.id.removingButton);
mScene1 = Scene.getSceneForLayout(mSceneRoot, R.layout.fading_test_simple, this);
mScene2 = Scene.getSceneForLayout(mSceneRoot, R.layout.fading_test_simple2, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/SurfaceAndTextureViews.java b/tests/TransitionTests/src/com/android/transitiontests/SurfaceAndTextureViews.java
index 9b246ad..8819c40 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/SurfaceAndTextureViews.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/SurfaceAndTextureViews.java
@@ -48,8 +48,8 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.surface_texture_views);
- final ViewGroup container = (ViewGroup) findViewById(R.id.container);
- Button toggleButton = (Button) findViewById(R.id.toggleButton);
+ final ViewGroup container = findViewById(R.id.container);
+ Button toggleButton = findViewById(R.id.toggleButton);
mView = new SimpleView(this);
mView.setId(0);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/UniqueIds.java b/tests/TransitionTests/src/com/android/transitiontests/UniqueIds.java
index c824956..b2b24bc 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/UniqueIds.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/UniqueIds.java
@@ -40,7 +40,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.unique_id_test);
- LinearLayout container = (LinearLayout) findViewById(R.id.container);
+ LinearLayout container = findViewById(R.id.container);
LayoutInflater inflater = getLayoutInflater();
Button button = (Button) inflater.inflate(R.layout.button_template, null);
container.addView(button);
diff --git a/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java b/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java
index 0a069c2..c212c4c 100644
--- a/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java
+++ b/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java
@@ -94,7 +94,7 @@
setupHero();
// Ensure that all images are visible regardless of orientation.
- GridLayout gridLayout = (GridLayout) findViewById(R.id.transition_grid_layout);
+ GridLayout gridLayout = findViewById(R.id.transition_grid_layout);
boolean isPortrait =
getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
gridLayout.setRowCount(isPortrait ? 4 : 2);
@@ -105,7 +105,7 @@
String name = getIntent().getStringExtra(KEY_ID);
mHero = null;
if (name != null) {
- mHero = (ImageView) findViewById(getIdForKey(name));
+ mHero = findViewById(getIdForKey(name));
setEnterSharedElementCallback(new SharedElementCallback() {
@Override
public void onMapSharedElements(List<String> names,
diff --git a/tests/UiBench/src/com/android/test/uibench/ActivityTransitionDetails.java b/tests/UiBench/src/com/android/test/uibench/ActivityTransitionDetails.java
index a654c61..a4d57e1 100644
--- a/tests/UiBench/src/com/android/test/uibench/ActivityTransitionDetails.java
+++ b/tests/UiBench/src/com/android/test/uibench/ActivityTransitionDetails.java
@@ -39,7 +39,7 @@
super.onCreate(savedInstanceState);
getWindow().setBackgroundDrawable(new ColorDrawable(Color.DKGRAY));
setContentView(R.layout.activity_transition_details);
- ImageView titleImage = (ImageView) findViewById(R.id.titleImage);
+ ImageView titleImage = findViewById(R.id.titleImage);
titleImage.setImageDrawable(getHeroDrawable());
}
diff --git a/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java b/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java
index e2bf897..235e0e6 100644
--- a/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java
@@ -80,7 +80,7 @@
setContentView(R.layout.activity_bitmap_upload);
// animate color to force bitmap uploads
- UploadView uploadView = (UploadView) findViewById(R.id.upload_view);
+ UploadView uploadView = findViewById(R.id.upload_view);
ObjectAnimator colorValueAnimator = ObjectAnimator.ofInt(uploadView, "colorValue", 0, 255);
colorValueAnimator.setRepeatMode(ValueAnimator.REVERSE);
colorValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
diff --git a/tests/UiBench/src/com/android/test/uibench/ClippedListActivity.java b/tests/UiBench/src/com/android/test/uibench/ClippedListActivity.java
index 7454124..fee7480 100644
--- a/tests/UiBench/src/com/android/test/uibench/ClippedListActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/ClippedListActivity.java
@@ -35,16 +35,16 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigation_drawer);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
- DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+ DrawerLayout drawer = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
- NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
+ NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
FragmentManager fm = getSupportFragmentManager();
@@ -59,7 +59,7 @@
@Override
public boolean onNavigationItemSelected(MenuItem item) {
- DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+ DrawerLayout drawer = findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
diff --git a/tests/UiBench/src/com/android/test/uibench/NavigationDrawerActivity.java b/tests/UiBench/src/com/android/test/uibench/NavigationDrawerActivity.java
index 1d68767..a541104 100644
--- a/tests/UiBench/src/com/android/test/uibench/NavigationDrawerActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/NavigationDrawerActivity.java
@@ -31,22 +31,22 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigation_drawer);
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
- DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+ DrawerLayout drawer = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
- NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
+ NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
@Override
public boolean onNavigationItemSelected(MenuItem item) {
- DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+ DrawerLayout drawer = findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
diff --git a/tests/UiBench/src/com/android/test/uibench/RenderingJitter.java b/tests/UiBench/src/com/android/test/uibench/RenderingJitter.java
index e2a9bcb..e1df7d3 100644
--- a/tests/UiBench/src/com/android/test/uibench/RenderingJitter.java
+++ b/tests/UiBench/src/com/android/test/uibench/RenderingJitter.java
@@ -85,12 +85,12 @@
View content = findViewById(android.R.id.content);
content.setBackground(new AnimatedBackgroundDrawable());
content.setKeepScreenOn(true);
- mJitterReport = (TextView) findViewById(R.id.jitter_mma);
- mMostlyTotalFrameTimeReport = (TextView) findViewById(R.id.totalish_mma);
- mUiFrameTimeReport = (TextView) findViewById(R.id.ui_frametime_mma);
- mRenderThreadTimeReport = (TextView) findViewById(R.id.rt_frametime_mma);
- mTotalFrameTimeReport = (TextView) findViewById(R.id.total_mma);
- mGraph = (PointGraphView) findViewById(R.id.graph);
+ mJitterReport = findViewById(R.id.jitter_mma);
+ mMostlyTotalFrameTimeReport = findViewById(R.id.totalish_mma);
+ mUiFrameTimeReport = findViewById(R.id.ui_frametime_mma);
+ mRenderThreadTimeReport = findViewById(R.id.rt_frametime_mma);
+ mTotalFrameTimeReport = findViewById(R.id.total_mma);
+ mGraph = findViewById(R.id.graph);
mJitterReport.setText("abcdefghijklmnopqrstuvwxyz");
mMostlyTotalFrameTimeReport.setText("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
mUiFrameTimeReport.setText("0123456789");
diff --git a/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/src/com/android/hardware/usb/externalmanagementtest/UsbHostManagementActivity.java b/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/src/com/android/hardware/usb/externalmanagementtest/UsbHostManagementActivity.java
index 2d9226f..af8b846 100644
--- a/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/src/com/android/hardware/usb/externalmanagementtest/UsbHostManagementActivity.java
+++ b/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/src/com/android/hardware/usb/externalmanagementtest/UsbHostManagementActivity.java
@@ -68,12 +68,12 @@
Log.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.host_management);
- mDeviceInfoText = (TextView) findViewById(R.id.device_info_text);
- mStartAoapButton = (Button) findViewById(R.id.start_aoap_button);
- mStartAoapActivityButton = (Button) findViewById(R.id.start_aoap_activity_button);
- mAoapAppLog = (TextView) findViewById(R.id.aoap_apps_text);
- mResetUsbButton = (Button) findViewById(R.id.reset_button);
- mFinishButton = (Button) findViewById(R.id.finish_button);
+ mDeviceInfoText = findViewById(R.id.device_info_text);
+ mStartAoapButton = findViewById(R.id.start_aoap_button);
+ mStartAoapActivityButton = findViewById(R.id.start_aoap_activity_button);
+ mAoapAppLog = findViewById(R.id.aoap_apps_text);
+ mResetUsbButton = findViewById(R.id.reset_button);
+ mFinishButton = findViewById(R.id.finish_button);
Intent intent = getIntent();
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) {
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableAttr.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableAttr.java
index 8de2f6b..47ca482 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableAttr.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableAttr.java
@@ -25,7 +25,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animated_vector_drawable_attr);
- ImageView avdIv = (ImageView) findViewById(R.id.avd);
+ ImageView avdIv = findViewById(R.id.avd);
AnimatedVectorDrawable avd = (AnimatedVectorDrawable) avdIv.getDrawable();
avd.start();
}
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java
index 41058c9..733f602 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java
@@ -55,9 +55,9 @@
mPickButton.setOnClickListener(this);
mCancelButton = (Button)findViewById(R.id.cancel);
mCancelButton.setOnClickListener(this);
- mStartButton = (Button) findViewById(R.id.start);
+ mStartButton = findViewById(R.id.start);
mStartButton.setOnClickListener(this);
- mStopButton = (Button) findViewById(R.id.stop);
+ mStopButton = findViewById(R.id.stop);
mStopButton.setOnClickListener(this);
mLog.append("Local Voice Interaction Supported = " + isLocalVoiceInteractionSupported());
diff --git a/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java b/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java
index 7880f67..63e11a7 100644
--- a/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java
+++ b/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java
@@ -58,28 +58,28 @@
mWallpaperManager = (WallpaperManager)getSystemService(Context.WALLPAPER_SERVICE);
mWindowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
- mDimenWidthView = (TextView) findViewById(R.id.dimen_width);
+ mDimenWidthView = findViewById(R.id.dimen_width);
mDimenWidthView.addTextChangedListener(mTextWatcher);
- mDimenHeightView = (TextView) findViewById(R.id.dimen_height);
+ mDimenHeightView = findViewById(R.id.dimen_height);
mDimenHeightView.addTextChangedListener(mTextWatcher);
- mWallOffXView = (TextView) findViewById(R.id.walloff_x);
+ mWallOffXView = findViewById(R.id.walloff_x);
mWallOffXView.addTextChangedListener(mTextWatcher);
- mWallOffYView = (TextView) findViewById(R.id.walloff_y);
+ mWallOffYView = findViewById(R.id.walloff_y);
mWallOffYView.addTextChangedListener(mTextWatcher);
- mPaddingLeftView = (TextView) findViewById(R.id.padding_left);
+ mPaddingLeftView = findViewById(R.id.padding_left);
mPaddingLeftView.addTextChangedListener(mTextWatcher);
- mPaddingRightView = (TextView) findViewById(R.id.padding_right);
+ mPaddingRightView = findViewById(R.id.padding_right);
mPaddingRightView.addTextChangedListener(mTextWatcher);
- mPaddingTopView = (TextView) findViewById(R.id.padding_top);
+ mPaddingTopView = findViewById(R.id.padding_top);
mPaddingTopView.addTextChangedListener(mTextWatcher);
- mPaddingBottomView = (TextView) findViewById(R.id.padding_bottom);
+ mPaddingBottomView = findViewById(R.id.padding_bottom);
mPaddingBottomView.addTextChangedListener(mTextWatcher);
- mDispOffXView = (TextView) findViewById(R.id.dispoff_x);
+ mDispOffXView = findViewById(R.id.dispoff_x);
mDispOffXView.addTextChangedListener(mTextWatcher);
- mDispOffYView = (TextView) findViewById(R.id.dispoff_y);
+ mDispOffYView = findViewById(R.id.dispoff_y);
mDispOffYView.addTextChangedListener(mTextWatcher);
updateDimens();
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index d819b96..d11565a 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -45,7 +45,9 @@
import android.net.metrics.RaEvent;
import android.net.metrics.ValidationProbeEvent;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
import java.util.Arrays;
+import java.util.List;
import junit.framework.TestCase;
// TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
@@ -57,7 +59,7 @@
aType(IpReachabilityEvent.class),
anInt(IpReachabilityEvent.NUD_FAILED));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -70,13 +72,13 @@
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
ev.netId = 123;
ev.transports = 3; // transports have priority for inferrence of link layer
ev.ifname = "wlan0";
- want = joinLines(
+ want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -89,12 +91,12 @@
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
ev.transports = 1;
ev.ifname = null;
- want = joinLines(
+ want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -107,12 +109,12 @@
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
ev.transports = 0;
ev.ifname = "not_inferred";
- want = joinLines(
+ want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"not_inferred\"",
@@ -125,11 +127,11 @@
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
ev.ifname = "bt-pan";
- want = joinLines(
+ want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -142,11 +144,11 @@
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
ev.ifname = "rmnet_ipa0";
- want = joinLines(
+ want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -159,11 +161,11 @@
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
ev.ifname = "wlan0";
- want = joinLines(
+ want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -176,7 +178,7 @@
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -190,7 +192,7 @@
aBool(true),
aBool(false));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -211,7 +213,7 @@
" transport_types: 3",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -223,7 +225,7 @@
aString("SomeState"),
anInt(192));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -237,7 +239,7 @@
" state_transition: \"SomeState\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -248,7 +250,7 @@
aType(DhcpErrorEvent.class),
anInt(DhcpErrorEvent.L4_NOT_UDP));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -262,59 +264,7 @@
" error_code: 50397184",
" >",
">",
- "version: 2");
-
- verifySerialization(want, ev);
- }
-
- @SmallTest
- public void testDnsEventSerialization() {
- ConnectivityMetricsEvent ev = describeIpEvent(
- aType(DnsEvent.class),
- anInt(101),
- aByteArray(b(1), b(1), b(2), b(1), b(1), b(1), b(2), b(2)),
- aByteArray(b(0), b(0), b(22), b(3), b(1), b(0), b(200), b(178)),
- anIntArray(3456, 267, 1230, 45, 2111, 450, 638, 1300));
-
- String want = joinLines(
- "dropped_events: 0",
- "events <",
- " if_name: \"\"",
- " link_layer: 0",
- " network_id: 0",
- " time_ms: 1",
- " transports: 0",
- " dns_lookup_batch <",
- " event_types: 1",
- " event_types: 1",
- " event_types: 2",
- " event_types: 1",
- " event_types: 1",
- " event_types: 1",
- " event_types: 2",
- " event_types: 2",
- " latencies_ms: 3456",
- " latencies_ms: 267",
- " latencies_ms: 1230",
- " latencies_ms: 45",
- " latencies_ms: 2111",
- " latencies_ms: 450",
- " latencies_ms: 638",
- " latencies_ms: 1300",
- " network_id <",
- " network_id: 101",
- " >",
- " return_codes: 0",
- " return_codes: 0",
- " return_codes: 22",
- " return_codes: 3",
- " return_codes: 1",
- " return_codes: 0",
- " return_codes: 200",
- " return_codes: 178",
- " >",
- ">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -326,7 +276,7 @@
anInt(IpManagerEvent.PROVISIONING_OK),
aLong(5678));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -340,7 +290,7 @@
" latency_ms: 5678",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -351,7 +301,7 @@
aType(IpReachabilityEvent.class),
anInt(IpReachabilityEvent.NUD_FAILED));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -364,7 +314,7 @@
" if_name: \"\"",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -377,7 +327,7 @@
anInt(5),
aLong(20410));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -393,7 +343,7 @@
" >",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -406,7 +356,7 @@
anInt(ValidationProbeEvent.PROBE_HTTP),
anInt(204));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -420,7 +370,7 @@
" probe_type: 1",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -436,7 +386,7 @@
anInt(2048),
anInt(3));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -454,7 +404,7 @@
" program_length: 2048",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -474,7 +424,7 @@
anInt(3),
anInt(2048));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -495,7 +445,7 @@
" zero_lifetime_ras: 1",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
@@ -511,7 +461,7 @@
aLong(1000),
aLong(-1));
- String want = joinLines(
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -528,28 +478,20 @@
" router_lifetime: 2000",
" >",
">",
- "version: 2");
+ "version: 2\n");
verifySerialization(want, ev);
}
static void verifySerialization(String want, ConnectivityMetricsEvent... input) {
try {
- byte[] got = IpConnectivityEventBuilder.serialize(0,
- IpConnectivityEventBuilder.toProto(Arrays.asList(input)));
+ List<IpConnectivityEvent> proto =
+ IpConnectivityEventBuilder.toProto(Arrays.asList(input));
+ byte[] got = IpConnectivityEventBuilder.serialize(0, proto);
IpConnectivityLog log = IpConnectivityLog.parseFrom(got);
assertEquals(want, log.toString());
} catch (Exception e) {
fail(e.toString());
}
}
-
- static String joinLines(String ... elems) {
- StringBuilder b = new StringBuilder();
- for (String s : elems) {
- b.append(s);
- b.append("\n");
- }
- return b.toString();
- }
}
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index 68786d0..e01469b 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -16,12 +16,22 @@
package com.android.server.connectivity;
+import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO;
+import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.content.Context;
+import android.net.ConnectivityManager;
import android.net.ConnectivityMetricsEvent;
import android.net.IIpConnectivityMetrics;
+import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.metrics.ApfProgramEvent;
import android.net.metrics.ApfStats;
import android.net.metrics.DefaultNetworkEvent;
@@ -31,7 +41,9 @@
import android.net.metrics.IpReachabilityEvent;
import android.net.metrics.RaEvent;
import android.net.metrics.ValidationProbeEvent;
+import android.system.OsConstants;
import android.os.Parcelable;
+import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Base64;
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
@@ -41,26 +53,38 @@
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
-import junit.framework.TestCase;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
-public class IpConnectivityMetricsTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IpConnectivityMetricsTest {
static final IpReachabilityEvent FAKE_EV =
new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED);
+ private static final String EXAMPLE_IPV4 = "192.0.2.1";
+ private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1";
+
@Mock Context mCtx;
@Mock IIpConnectivityMetrics mMockService;
+ @Mock ConnectivityManager mCm;
IpConnectivityMetrics mService;
+ NetdEventListenerService mNetdListener;
+ @Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mService = new IpConnectivityMetrics(mCtx, (ctx) -> 2000);
+ mNetdListener = new NetdEventListenerService(mCm);
+ mService.mNetdListener = mNetdListener;
}
- @SmallTest
+ @Test
public void testLoggingEvents() throws Exception {
IpConnectivityLog logger = new IpConnectivityLog(mMockService);
@@ -74,7 +98,7 @@
assertEventsEqual(expectedEvent(3), got.get(2));
}
- @SmallTest
+ @Test
public void testLoggingEventsWithMultipleCallers() throws Exception {
IpConnectivityLog logger = new IpConnectivityLog(mMockService);
@@ -91,7 +115,7 @@
}.start();
}
- List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 100);
+ List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 200);
Collections.sort(got, EVENT_COMPARATOR);
Iterator<ConnectivityMetricsEvent> iter = got.iterator();
for (int i = 0; i < nCallers; i++) {
@@ -102,7 +126,7 @@
}
}
- @SmallTest
+ @Test
public void testBufferFlushing() {
String output1 = getdump("flush");
assertEquals("", output1);
@@ -115,7 +139,7 @@
assertEquals("", output3);
}
- @SmallTest
+ @Test
public void testRateLimiting() {
final IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
final ApfProgramEvent ev = new ApfProgramEvent();
@@ -137,11 +161,19 @@
assertEquals("", output2);
}
- @SmallTest
- public void testEndToEndLogging() {
+ @Test
+ public void testEndToEndLogging() throws Exception {
// TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
+ NetworkCapabilities ncWifi = new NetworkCapabilities();
+ NetworkCapabilities ncCell = new NetworkCapabilities();
+ ncWifi.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+ ncCell.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+
+ when(mCm.getNetworkCapabilities(new Network(100))).thenReturn(ncWifi);
+ when(mCm.getNetworkCapabilities(new Network(101))).thenReturn(ncCell);
+
ApfStats apfStats = new ApfStats();
apfStats.durationMs = 45000;
apfStats.receivedRas = 10;
@@ -177,7 +209,22 @@
logger.log(ev);
}
- String want = joinLines(
+ // netId, errno, latency, destination
+ connectEvent(100, OsConstants.EALREADY, 0, EXAMPLE_IPV4);
+ connectEvent(100, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6);
+ connectEvent(100, 0, 110, EXAMPLE_IPV4);
+ connectEvent(101, 0, 23, EXAMPLE_IPV4);
+ connectEvent(101, 0, 45, EXAMPLE_IPV6);
+ connectEvent(100, OsConstants.EAGAIN, 0, EXAMPLE_IPV4);
+
+ // netId, type, return code, latency
+ dnsEvent(100, EVENT_GETADDRINFO, 0, 3456);
+ dnsEvent(100, EVENT_GETADDRINFO, 3, 45);
+ dnsEvent(100, EVENT_GETHOSTBYNAME, 0, 638);
+ dnsEvent(101, EVENT_GETADDRINFO, 0, 56);
+ dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 34);
+
+ String want = String.join("\n",
"dropped_events: 0",
"events <",
" if_name: \"\"",
@@ -279,7 +326,71 @@
" router_lifetime: 2000",
" >",
">",
- "version: 2");
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 4",
+ " network_id: 100",
+ " time_ms: 0",
+ " transports: 2",
+ " connect_statistics <",
+ " connect_blocking_count: 1",
+ " connect_count: 3",
+ " errnos_counters <",
+ " key: 11",
+ " value: 1",
+ " >",
+ " ipv6_addr_count: 1",
+ " latencies_ms: 110",
+ " >",
+ ">",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 2",
+ " network_id: 101",
+ " time_ms: 0",
+ " transports: 1",
+ " connect_statistics <",
+ " connect_blocking_count: 2",
+ " connect_count: 2",
+ " ipv6_addr_count: 1",
+ " latencies_ms: 23",
+ " latencies_ms: 45",
+ " >",
+ ">",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 4",
+ " network_id: 100",
+ " time_ms: 0",
+ " transports: 2",
+ " dns_lookup_batch <",
+ " event_types: 1",
+ " event_types: 1",
+ " event_types: 2",
+ " latencies_ms: 3456",
+ " latencies_ms: 45",
+ " latencies_ms: 638",
+ " return_codes: 0",
+ " return_codes: 3",
+ " return_codes: 0",
+ " >",
+ ">",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 2",
+ " network_id: 101",
+ " time_ms: 0",
+ " transports: 1",
+ " dns_lookup_batch <",
+ " event_types: 1",
+ " event_types: 2",
+ " latencies_ms: 56",
+ " latencies_ms: 34",
+ " return_codes: 0",
+ " return_codes: 0",
+ " >",
+ ">",
+ "version: 2\n");
verifySerialization(want, getdump("flush"));
}
@@ -291,6 +402,14 @@
return buffer.toString();
}
+ void connectEvent(int netid, int error, int latencyMs, String ipAddr) throws Exception {
+ mNetdListener.onConnectEvent(netid, error, latencyMs, ipAddr, 80, 1);
+ }
+
+ void dnsEvent(int netId, int type, int result, int latency) throws Exception {
+ mNetdListener.onDnsEvent(netId, type, result, latency, "", null, 0, 0);
+ }
+
List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
ArgumentCaptor<ConnectivityMetricsEvent> captor =
ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index 0ab4406..f98ab3d 100644
--- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -16,190 +16,182 @@
package com.android.server.connectivity;
-import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
-import android.net.Network;
-import android.net.metrics.ConnectStats;
-import android.net.metrics.DnsEvent;
-import android.net.metrics.INetdEventListener;
-import android.net.metrics.IpConnectivityLog;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.system.OsConstants;
-import android.test.suitebuilder.annotation.SmallTest;
-import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
-import java.io.FileOutputStream;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
-import java.util.OptionalInt;
-import java.util.stream.IntStream;
-import junit.framework.TestCase;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertTrue;
+import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO;
+import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
-public class NetdEventListenerServiceTest extends TestCase {
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.support.test.runner.AndroidJUnit4;
+import android.system.OsConstants;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Base64;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.DNSLookupBatch;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
- // TODO: read from NetdEventListenerService after this constant is read from system property
- static final int BATCH_SIZE = 100;
- static final int EVENT_TYPE = INetdEventListener.EVENT_GETADDRINFO;
- // TODO: read from INetdEventListener
- static final int RETURN_CODE = 1;
-
- static final byte[] EVENT_TYPES = new byte[BATCH_SIZE];
- static final byte[] RETURN_CODES = new byte[BATCH_SIZE];
- static final int[] LATENCIES = new int[BATCH_SIZE];
- static {
- for (int i = 0; i < BATCH_SIZE; i++) {
- EVENT_TYPES[i] = EVENT_TYPE;
- RETURN_CODES[i] = RETURN_CODE;
- LATENCIES[i] = i;
- }
- }
-
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NetdEventListenerServiceTest {
private static final String EXAMPLE_IPV4 = "192.0.2.1";
private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1";
NetdEventListenerService mNetdEventListenerService;
+ ConnectivityManager mCm;
- @Mock ConnectivityManager mCm;
- @Mock IpConnectivityLog mLog;
- ArgumentCaptor<NetworkCallback> mCallbackCaptor;
- ArgumentCaptor<DnsEvent> mDnsEvCaptor;
-
+ @Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
- mCallbackCaptor = ArgumentCaptor.forClass(NetworkCallback.class);
- mDnsEvCaptor = ArgumentCaptor.forClass(DnsEvent.class);
- mNetdEventListenerService = new NetdEventListenerService(mCm, mLog);
+ NetworkCapabilities ncWifi = new NetworkCapabilities();
+ NetworkCapabilities ncCell = new NetworkCapabilities();
+ ncWifi.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+ ncCell.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
- verify(mCm, times(1)).registerNetworkCallback(any(), mCallbackCaptor.capture());
+ mCm = mock(ConnectivityManager.class);
+ when(mCm.getNetworkCapabilities(new Network(100))).thenReturn(ncWifi);
+ when(mCm.getNetworkCapabilities(new Network(101))).thenReturn(ncCell);
+
+ mNetdEventListenerService = new NetdEventListenerService(mCm);
}
- @SmallTest
- public void testOneDnsBatch() throws Exception {
- log(105, LATENCIES);
- log(106, Arrays.copyOf(LATENCIES, BATCH_SIZE - 1)); // one lookup short of a batch event
+ @Test
+ public void testDnsLogging() throws Exception {
+ asyncDump(100);
- verifyLoggedDnsEvents(new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES));
+ dnsEvent(100, EVENT_GETADDRINFO, 0, 3456);
+ dnsEvent(100, EVENT_GETADDRINFO, 0, 267);
+ dnsEvent(100, EVENT_GETHOSTBYNAME, 22, 1230);
+ dnsEvent(100, EVENT_GETADDRINFO, 3, 45);
+ dnsEvent(100, EVENT_GETADDRINFO, 1, 2111);
+ dnsEvent(100, EVENT_GETADDRINFO, 0, 450);
+ dnsEvent(100, EVENT_GETHOSTBYNAME, 200, 638);
+ dnsEvent(100, EVENT_GETHOSTBYNAME, 178, 1300);
+ dnsEvent(101, EVENT_GETADDRINFO, 0, 56);
+ dnsEvent(101, EVENT_GETADDRINFO, 0, 78);
+ dnsEvent(101, EVENT_GETADDRINFO, 0, 14);
+ dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 56);
+ dnsEvent(101, EVENT_GETADDRINFO, 0, 78);
+ dnsEvent(101, EVENT_GETADDRINFO, 0, 14);
- log(106, Arrays.copyOfRange(LATENCIES, BATCH_SIZE - 1, BATCH_SIZE));
-
- mDnsEvCaptor = ArgumentCaptor.forClass(DnsEvent.class); // reset argument captor
- verifyLoggedDnsEvents(
- new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
- new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES));
+ String got = flushStatistics();
+ String want = String.join("\n",
+ "dropped_events: 0",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 4",
+ " network_id: 100",
+ " time_ms: 0",
+ " transports: 2",
+ " dns_lookup_batch <",
+ " event_types: 1",
+ " event_types: 1",
+ " event_types: 2",
+ " event_types: 1",
+ " event_types: 1",
+ " event_types: 1",
+ " event_types: 2",
+ " event_types: 2",
+ " latencies_ms: 3456",
+ " latencies_ms: 267",
+ " latencies_ms: 1230",
+ " latencies_ms: 45",
+ " latencies_ms: 2111",
+ " latencies_ms: 450",
+ " latencies_ms: 638",
+ " latencies_ms: 1300",
+ " return_codes: 0",
+ " return_codes: 0",
+ " return_codes: 22",
+ " return_codes: 3",
+ " return_codes: 1",
+ " return_codes: 0",
+ " return_codes: 200",
+ " return_codes: 178",
+ " >",
+ ">",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 2",
+ " network_id: 101",
+ " time_ms: 0",
+ " transports: 1",
+ " dns_lookup_batch <",
+ " event_types: 1",
+ " event_types: 1",
+ " event_types: 1",
+ " event_types: 2",
+ " event_types: 1",
+ " event_types: 1",
+ " latencies_ms: 56",
+ " latencies_ms: 78",
+ " latencies_ms: 14",
+ " latencies_ms: 56",
+ " latencies_ms: 78",
+ " latencies_ms: 14",
+ " return_codes: 0",
+ " return_codes: 0",
+ " return_codes: 0",
+ " return_codes: 0",
+ " return_codes: 0",
+ " return_codes: 0",
+ " >",
+ ">",
+ "version: 2\n");
+ assertEquals(want, got);
}
- @SmallTest
- public void testSeveralDmsBatches() throws Exception {
- log(105, LATENCIES);
- log(106, LATENCIES);
- log(105, LATENCIES);
- log(107, LATENCIES);
-
- verifyLoggedDnsEvents(
- new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
- new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES),
- new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
- new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES));
- }
-
- @SmallTest
- public void testDnsBatchAndNetworkLost() throws Exception {
- byte[] eventTypes = Arrays.copyOf(EVENT_TYPES, 20);
- byte[] returnCodes = Arrays.copyOf(RETURN_CODES, 20);
- int[] latencies = Arrays.copyOf(LATENCIES, 20);
-
- log(105, LATENCIES);
- log(105, latencies);
- mCallbackCaptor.getValue().onLost(new Network(105));
- log(105, LATENCIES);
-
- verifyLoggedDnsEvents(
- new DnsEvent(105, eventTypes, returnCodes, latencies),
- new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
- new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES));
- }
-
- @SmallTest
- public void testConcurrentDnsBatchesAndDumps() throws Exception {
- final long stop = System.currentTimeMillis() + 100;
- final PrintWriter pw = new PrintWriter(new FileOutputStream("/dev/null"));
- new Thread() {
- public void run() {
- while (System.currentTimeMillis() < stop) {
- mNetdEventListenerService.dump(pw);
- }
- }
- }.start();
-
- logDnsAsync(105, LATENCIES);
- logDnsAsync(106, LATENCIES);
- logDnsAsync(107, LATENCIES);
-
- verifyLoggedDnsEvents(500,
- new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
- new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES),
- new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES));
- }
-
- @SmallTest
- public void testConcurrentDnsBatchesAndNetworkLoss() throws Exception {
- logDnsAsync(105, LATENCIES);
- Thread.sleep(10L);
- // call onLost() asynchronously to logDnsAsync's onDnsEvent() calls.
- mCallbackCaptor.getValue().onLost(new Network(105));
-
- // do not verify batch with unpredictable length
- verify(mLog, timeout(500).times(1)).log(any(Parcelable.class));
- }
-
- @SmallTest
+ @Test
public void testConnectLogging() throws Exception {
+ asyncDump(100);
+
final int OK = 0;
Thread[] logActions = {
// ignored
- connectEventAction(OsConstants.EALREADY, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.EALREADY, 0, EXAMPLE_IPV6),
- connectEventAction(OsConstants.EINPROGRESS, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6),
- connectEventAction(OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6),
+ connectEventAction(100, OsConstants.EALREADY, 0, EXAMPLE_IPV4),
+ connectEventAction(100, OsConstants.EALREADY, 0, EXAMPLE_IPV6),
+ connectEventAction(100, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV4),
+ connectEventAction(101, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6),
+ connectEventAction(101, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6),
// valid latencies
- connectEventAction(OK, 110, EXAMPLE_IPV4),
- connectEventAction(OK, 23, EXAMPLE_IPV4),
- connectEventAction(OK, 45, EXAMPLE_IPV4),
- connectEventAction(OK, 56, EXAMPLE_IPV4),
- connectEventAction(OK, 523, EXAMPLE_IPV6),
- connectEventAction(OK, 214, EXAMPLE_IPV6),
- connectEventAction(OK, 67, EXAMPLE_IPV6),
+ connectEventAction(100, OK, 110, EXAMPLE_IPV4),
+ connectEventAction(100, OK, 23, EXAMPLE_IPV4),
+ connectEventAction(100, OK, 45, EXAMPLE_IPV4),
+ connectEventAction(101, OK, 56, EXAMPLE_IPV4),
+ connectEventAction(101, OK, 523, EXAMPLE_IPV6),
+ connectEventAction(101, OK, 214, EXAMPLE_IPV6),
+ connectEventAction(101, OK, 67, EXAMPLE_IPV6),
// errors
- connectEventAction(OsConstants.EPERM, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.EPERM, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.EAGAIN, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.EACCES, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.EACCES, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.EACCES, 0, EXAMPLE_IPV6),
- connectEventAction(OsConstants.EADDRINUSE, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV4),
- connectEventAction(OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6),
- connectEventAction(OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6),
- connectEventAction(OsConstants.ECONNREFUSED, 0, EXAMPLE_IPV4),
+ connectEventAction(100, OsConstants.EPERM, 0, EXAMPLE_IPV4),
+ connectEventAction(101, OsConstants.EPERM, 0, EXAMPLE_IPV4),
+ connectEventAction(100, OsConstants.EAGAIN, 0, EXAMPLE_IPV4),
+ connectEventAction(100, OsConstants.EACCES, 0, EXAMPLE_IPV4),
+ connectEventAction(101, OsConstants.EACCES, 0, EXAMPLE_IPV4),
+ connectEventAction(101, OsConstants.EACCES, 0, EXAMPLE_IPV6),
+ connectEventAction(100, OsConstants.EADDRINUSE, 0, EXAMPLE_IPV4),
+ connectEventAction(101, OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV4),
+ connectEventAction(100, OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6),
+ connectEventAction(100, OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6),
+ connectEventAction(101, OsConstants.ECONNREFUSED, 0, EXAMPLE_IPV4),
};
for (Thread t : logActions) {
@@ -209,113 +201,124 @@
t.join();
}
- List<IpConnectivityEvent> events = new ArrayList<>();
- mNetdEventListenerService.flushStatistics(events);
-
- IpConnectivityEvent got = events.get(0);
+ String got = flushStatistics();
String want = String.join("\n",
- "if_name: \"\"",
- "link_layer: 0",
- "network_id: 0",
- "time_ms: 0",
- "transports: 0",
- "connect_statistics <",
- " connect_blocking_count: 7",
- " connect_count: 12",
- " errnos_counters <",
- " key: 1",
- " value: 2",
+ "dropped_events: 0",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 4",
+ " network_id: 100",
+ " time_ms: 0",
+ " transports: 2",
+ " connect_statistics <",
+ " connect_blocking_count: 3",
+ " connect_count: 6",
+ " errnos_counters <",
+ " key: 1",
+ " value: 1",
+ " >",
+ " errnos_counters <",
+ " key: 11",
+ " value: 1",
+ " >",
+ " errnos_counters <",
+ " key: 13",
+ " value: 1",
+ " >",
+ " errnos_counters <",
+ " key: 98",
+ " value: 1",
+ " >",
+ " errnos_counters <",
+ " key: 110",
+ " value: 2",
+ " >",
+ " ipv6_addr_count: 1",
+ " latencies_ms: 23",
+ " latencies_ms: 45",
+ " latencies_ms: 110",
" >",
- " errnos_counters <",
- " key: 11",
- " value: 1",
+ ">",
+ "events <",
+ " if_name: \"\"",
+ " link_layer: 2",
+ " network_id: 101",
+ " time_ms: 0",
+ " transports: 1",
+ " connect_statistics <",
+ " connect_blocking_count: 4",
+ " connect_count: 6",
+ " errnos_counters <",
+ " key: 1",
+ " value: 1",
+ " >",
+ " errnos_counters <",
+ " key: 13",
+ " value: 2",
+ " >",
+ " errnos_counters <",
+ " key: 110",
+ " value: 1",
+ " >",
+ " errnos_counters <",
+ " key: 111",
+ " value: 1",
+ " >",
+ " ipv6_addr_count: 5",
+ " latencies_ms: 56",
+ " latencies_ms: 67",
+ " latencies_ms: 214",
+ " latencies_ms: 523",
" >",
- " errnos_counters <",
- " key: 13",
- " value: 3",
- " >",
- " errnos_counters <",
- " key: 98",
- " value: 1",
- " >",
- " errnos_counters <",
- " key: 110",
- " value: 3",
- " >",
- " errnos_counters <",
- " key: 111",
- " value: 1",
- " >",
- " ipv6_addr_count: 6",
- " latencies_ms: 23",
- " latencies_ms: 45",
- " latencies_ms: 56",
- " latencies_ms: 67",
- " latencies_ms: 110",
- " latencies_ms: 214",
- " latencies_ms: 523",
- ">\n");
- verifyConnectEvent(want, got);
+ ">",
+ "version: 2\n");
+ assertEquals(want, got);
}
- Thread connectEventAction(int error, int latencyMs, String ipAddr) {
+ Thread connectEventAction(int netId, int error, int latencyMs, String ipAddr) {
return new Thread(() -> {
try {
- mNetdEventListenerService.onConnectEvent(100, error, latencyMs, ipAddr, 80, 1);
+ mNetdEventListenerService.onConnectEvent(netId, error, latencyMs, ipAddr, 80, 1);
} catch (Exception e) {
fail(e.toString());
}
});
}
- void log(int netId, int[] latencies) {
- try {
- for (int l : latencies) {
- mNetdEventListenerService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l, null, null,
- 0, 0);
+ void dnsEvent(int netId, int type, int result, int latency) throws Exception {
+ mNetdEventListenerService.onDnsEvent(netId, type, result, latency, "", null, 0, 0);
+ }
+
+ void asyncDump(long durationMs) throws Exception {
+ final long stop = System.currentTimeMillis() + durationMs;
+ final PrintWriter pw = new PrintWriter(new FileOutputStream("/dev/null"));
+ new Thread(() -> {
+ while (System.currentTimeMillis() < stop) {
+ mNetdEventListenerService.dump(pw);
}
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
+ }).start();
}
- void logDnsAsync(int netId, int[] latencies) {
- new Thread(() -> log(netId, latencies)).start();
- }
+ // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
+ String flushStatistics() throws Exception {
+ IpConnectivityMetrics metricsService =
+ new IpConnectivityMetrics(mock(Context.class), (ctx) -> 2000);
+ metricsService.mNetdListener = mNetdEventListenerService;
- void verifyLoggedDnsEvents(DnsEvent... expected) {
- verifyLoggedDnsEvents(0, expected);
- }
-
- void verifyLoggedDnsEvents(int wait, DnsEvent... expectedEvents) {
- verify(mLog, timeout(wait).times(expectedEvents.length)).log(mDnsEvCaptor.capture());
- for (DnsEvent got : mDnsEvCaptor.getAllValues()) {
- OptionalInt index = IntStream.range(0, expectedEvents.length)
- .filter(i -> dnsEventsEqual(expectedEvents[i], got))
- .findFirst();
- // Don't match same expected event more than once.
- index.ifPresent(i -> expectedEvents[i] = null);
- assertTrue(index.isPresent());
- }
- }
-
- /** equality function for DnsEvent to avoid overriding equals() and hashCode(). */
- static boolean dnsEventsEqual(DnsEvent expected, DnsEvent got) {
- return (expected == got) || ((expected != null) && (got != null)
- && (expected.netId == got.netId)
- && Arrays.equals(expected.eventTypes, got.eventTypes)
- && Arrays.equals(expected.returnCodes, got.returnCodes)
- && Arrays.equals(expected.latenciesMs, got.latenciesMs));
- }
-
- static void verifyConnectEvent(String expected, IpConnectivityEvent got) {
- try {
- Arrays.sort(got.getConnectStatistics().latenciesMs);
- Arrays.sort(got.getConnectStatistics().errnosCounters,
+ StringWriter buffer = new StringWriter();
+ PrintWriter writer = new PrintWriter(buffer);
+ metricsService.impl.dump(null, writer, new String[]{"flush"});
+ byte[] bytes = Base64.decode(buffer.toString(), Base64.DEFAULT);
+ IpConnectivityLog log = IpConnectivityLog.parseFrom(bytes);
+ for (IpConnectivityEvent ev : log.events) {
+ if (ev.getConnectStatistics() == null) {
+ continue;
+ }
+ // Sort repeated fields of connect() events arriving in non-deterministic order.
+ Arrays.sort(ev.getConnectStatistics().latenciesMs);
+ Arrays.sort(ev.getConnectStatistics().errnosCounters,
Comparator.comparingInt((p) -> p.key));
- assertEquals(expected, got.toString());
- } catch (Exception e) {
- fail(e.toString());
}
+ return log.toString();
}
}
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index ef3797c..b460258 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -15,11 +15,12 @@
//
toolSources = [
- "compile/Compile.cpp",
- "diff/Diff.cpp",
- "dump/Dump.cpp",
- "link/Link.cpp",
- "optimize/Optimize.cpp",
+ "cmd/Compile.cpp",
+ "cmd/Diff.cpp",
+ "cmd/Dump.cpp",
+ "cmd/Link.cpp",
+ "cmd/Optimize.cpp",
+ "cmd/Util.cpp",
]
cc_defaults {
@@ -90,7 +91,7 @@
"io/BigBufferStreams.cpp",
"io/File.cpp",
"io/FileSystem.cpp",
- "io/Io.cpp",
+ "io/Util.cpp",
"io/ZipArchive.cpp",
"link/AutoVersioner.cpp",
"link/ManifestFixer.cpp",
diff --git a/tools/aapt2/AppInfo.h b/tools/aapt2/AppInfo.h
index 9db21aa..d6f5995 100644
--- a/tools/aapt2/AppInfo.h
+++ b/tools/aapt2/AppInfo.h
@@ -29,7 +29,7 @@
std::string package;
// The app's minimum SDK version, if it is defined.
- Maybe<std::string> min_sdk_version;
+ Maybe<int> min_sdk_version;
// The app's version code, if it is defined.
Maybe<uint32_t> version_code;
diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp
index b855f8f..8a8f8be 100644
--- a/tools/aapt2/LoadedApk.cpp
+++ b/tools/aapt2/LoadedApk.cpp
@@ -21,6 +21,7 @@
#include "flatten/Archive.h"
#include "flatten/TableFlattener.h"
#include "io/BigBufferInputStream.h"
+#include "io/Util.h"
namespace aapt {
@@ -47,11 +48,10 @@
}
std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
- BinaryResourceParser parser(context, table.get(), source, data->data(), data->size());
+ BinaryResourceParser parser(context, table.get(), source, data->data(), data->size(), apk.get());
if (!parser.Parse()) {
return {};
}
-
return util::make_unique<LoadedApk>(source, std::move(apk), std::move(table));
}
@@ -100,20 +100,16 @@
}
io::BigBufferInputStream input_stream(&buffer);
- if (!writer->WriteFile(path, ArchiveEntry::kAlign, &input_stream)) {
- context->GetDiagnostics()->Error(DiagMessage()
- << "Error when writing file '" << path << "' in APK.");
+ if (!io::CopyInputStreamToArchive(context, &input_stream, path, ArchiveEntry::kAlign,
+ writer)) {
return false;
}
- continue;
- }
- std::unique_ptr<io::IData> data = file->OpenAsData();
- uint32_t compression_flags = file->WasCompressed() ? ArchiveEntry::kCompress : 0u;
- if (!writer->WriteFile(path, compression_flags, data.get())) {
- context->GetDiagnostics()->Error(DiagMessage()
- << "Error when writing file '" << path << "' in APK.");
- return false;
+ } else {
+ uint32_t compression_flags = file->WasCompressed() ? ArchiveEntry::kCompress : 0u;
+ if (!io::CopyFileToArchive(context, file, path, compression_flags, writer)) {
+ return false;
+ }
}
}
return true;
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index 36c1de6..87fda16 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -25,7 +25,7 @@
static const char* sMajorVersion = "2";
// Update minor version whenever a feature or flag is added.
-static const char* sMinorVersion = "12";
+static const char* sMinorVersion = "13";
int PrintVersion() {
std::cerr << "Android Asset Packaging Tool (aapt) " << sMajorVersion << "."
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index ca6738b..1bb7d9b 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -675,5 +675,65 @@
return out.str();
}
+std::unique_ptr<Item> ParseBinaryResValue(const ResourceType& type, const ConfigDescription& config,
+ const android::ResStringPool& src_pool,
+ const android::Res_value& res_value,
+ StringPool* dst_pool) {
+ if (type == ResourceType::kId) {
+ return util::make_unique<Id>();
+ }
+
+ const uint32_t data = util::DeviceToHost32(res_value.data);
+ switch (res_value.dataType) {
+ case android::Res_value::TYPE_STRING: {
+ const std::string str = util::GetString(src_pool, data);
+ const android::ResStringPool_span* spans = src_pool.styleAt(data);
+
+ // Check if the string has a valid style associated with it.
+ if (spans != nullptr && spans->name.index != android::ResStringPool_span::END) {
+ StyleString style_str = {str};
+ while (spans->name.index != android::ResStringPool_span::END) {
+ style_str.spans.push_back(Span{util::GetString(src_pool, spans->name.index),
+ spans->firstChar, spans->lastChar});
+ spans++;
+ }
+ return util::make_unique<StyledString>(dst_pool->MakeRef(
+ style_str, StringPool::Context(StringPool::Context::kStylePriority, config)));
+ } else {
+ if (type != ResourceType::kString && util::StartsWith(str, "res/")) {
+ // This must be a FileReference.
+ return util::make_unique<FileReference>(dst_pool->MakeRef(
+ str, StringPool::Context(StringPool::Context::kHighPriority, config)));
+ }
+
+ // There are no styles associated with this string, so treat it as a simple string.
+ return util::make_unique<String>(dst_pool->MakeRef(str, StringPool::Context(config)));
+ }
+ } break;
+
+ case android::Res_value::TYPE_REFERENCE:
+ case android::Res_value::TYPE_ATTRIBUTE:
+ case android::Res_value::TYPE_DYNAMIC_REFERENCE:
+ case android::Res_value::TYPE_DYNAMIC_ATTRIBUTE: {
+ Reference::Type ref_type = Reference::Type::kResource;
+ if (res_value.dataType == android::Res_value::TYPE_ATTRIBUTE ||
+ res_value.dataType == android::Res_value::TYPE_DYNAMIC_ATTRIBUTE) {
+ ref_type = Reference::Type::kAttribute;
+ }
+
+ if (data == 0) {
+ // A reference of 0, must be the magic @null reference.
+ return util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_REFERENCE, 0u);
+ }
+
+ // This is a normal reference.
+ return util::make_unique<Reference>(data, ref_type);
+ } break;
+ }
+
+ // Treat this as a raw binary primitive.
+ return util::make_unique<BinaryPrimitive>(res_value);
+}
+
} // namespace ResourceUtils
} // namespace aapt
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index 59b78f4..48922b7 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -20,11 +20,13 @@
#include <functional>
#include <memory>
+#include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h"
#include "NameMangler.h"
#include "Resource.h"
#include "ResourceValues.h"
+#include "StringPool.h"
namespace aapt {
namespace ResourceUtils {
@@ -200,6 +202,13 @@
std::string BuildResourceFileName(const ResourceFile& res_file,
const NameMangler* mangler = nullptr);
+// Parses the binary form of a resource value. `type` is used as a hint to know when a value is
+// an ID versus a False boolean value, etc. `config` is for sorting strings in the string pool.
+std::unique_ptr<Item> ParseBinaryResValue(const ResourceType& type, const ConfigDescription& config,
+ const android::ResStringPool& src_pool,
+ const android::Res_value& res_value,
+ StringPool* dst_pool);
+
} // namespace ResourceUtils
} // namespace aapt
diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h
index a626d37..d1232a2 100644
--- a/tools/aapt2/StringPool.h
+++ b/tools/aapt2/StringPool.h
@@ -23,6 +23,7 @@
#include <unordered_map>
#include <vector>
+#include "android-base/macros.h"
#include "androidfw/StringPiece.h"
#include "ConfigDescription.h"
@@ -148,7 +149,8 @@
static bool FlattenUtf16(BigBuffer* out, const StringPool& pool);
StringPool() = default;
- StringPool(const StringPool&) = delete;
+ StringPool(StringPool&&) = default;
+ StringPool& operator=(StringPool&&) = default;
/**
* Adds a string to the pool, unless it already exists. Returns
@@ -208,6 +210,8 @@
void Prune();
private:
+ DISALLOW_COPY_AND_ASSIGN(StringPool);
+
friend const_iterator begin(const StringPool& pool);
friend const_iterator end(const StringPool& pool);
diff --git a/tools/aapt2/compile/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
similarity index 83%
rename from tools/aapt2/compile/Compile.cpp
rename to tools/aapt2/cmd/Compile.cpp
index 1fe30f0..578a8fb 100644
--- a/tools/aapt2/compile/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -38,6 +38,7 @@
#include "flatten/Archive.h"
#include "flatten/XmlFlattener.h"
#include "io/BigBufferOutputStream.h"
+#include "io/Util.h"
#include "proto/ProtoSerialize.h"
#include "util/Files.h"
#include "util/Maybe.h"
@@ -138,9 +139,8 @@
/**
* Walks the res directory structure, looking for resource files.
*/
-static bool LoadInputFilesFromDir(
- IAaptContext* context, const CompileOptions& options,
- std::vector<ResourcePathData>* out_path_data) {
+static bool LoadInputFilesFromDir(IAaptContext* context, const CompileOptions& options,
+ std::vector<ResourcePathData>* out_path_data) {
const std::string& root_dir = options.res_dir.value();
std::unique_ptr<DIR, decltype(closedir)*> d(opendir(root_dir.data()), closedir);
if (!d) {
@@ -190,8 +190,7 @@
}
static bool CompileTable(IAaptContext* context, const CompileOptions& options,
- const ResourcePathData& path_data,
- IArchiveWriter* writer,
+ const ResourcePathData& path_data, IArchiveWriter* writer,
const std::string& output_path) {
ResourceTable table;
{
@@ -210,11 +209,9 @@
// If the filename includes donottranslate, then the default translatable is
// false.
- parser_options.translatable =
- path_data.name.find("donottranslate") == std::string::npos;
+ parser_options.translatable = path_data.name.find("donottranslate") == std::string::npos;
- ResourceParser res_parser(context->GetDiagnostics(), &table,
- path_data.source, path_data.config,
+ ResourceParser res_parser(context->GetDiagnostics(), &table, path_data.source, path_data.config,
parser_options);
if (!res_parser.Parse(&xml_parser)) {
return false;
@@ -273,10 +270,8 @@
return true;
}
-static bool WriteHeaderAndBufferToWriter(const StringPiece& output_path,
- const ResourceFile& file,
- const BigBuffer& buffer,
- IArchiveWriter* writer,
+static bool WriteHeaderAndBufferToWriter(const StringPiece& output_path, const ResourceFile& file,
+ const BigBuffer& buffer, IArchiveWriter* writer,
IDiagnostics* diag) {
// Start the entry so we can write the header.
if (!writer->StartEntry(output_path, 0)) {
@@ -312,10 +307,8 @@
return true;
}
-static bool WriteHeaderAndMmapToWriter(const StringPiece& output_path,
- const ResourceFile& file,
- const android::FileMap& map,
- IArchiveWriter* writer,
+static bool WriteHeaderAndMmapToWriter(const StringPiece& output_path, const ResourceFile& file,
+ const android::FileMap& map, IArchiveWriter* writer,
IDiagnostics* diag) {
// Start the entry so we can write the header.
if (!writer->StartEntry(output_path, 0)) {
@@ -334,8 +327,7 @@
// Number of CompiledFiles.
output_stream.WriteLittleEndian32(1);
- std::unique_ptr<pb::CompiledFile> compiled_file =
- SerializeCompiledFileToPb(file);
+ std::unique_ptr<pb::CompiledFile> compiled_file = SerializeCompiledFileToPb(file);
output_stream.WriteCompiledFile(compiled_file.get());
output_stream.WriteData(map.getDataPtr(), map.getDataLength());
@@ -352,10 +344,8 @@
return true;
}
-static bool FlattenXmlToOutStream(IAaptContext* context,
- const StringPiece& output_path,
- xml::XmlResource* xmlres,
- CompiledFileOutputStream* out) {
+static bool FlattenXmlToOutStream(IAaptContext* context, const StringPiece& output_path,
+ xml::XmlResource* xmlres, CompiledFileOutputStream* out) {
BigBuffer buffer(1024);
XmlFlattenerOptions xml_flattener_options;
xml_flattener_options.keep_raw_values = true;
@@ -376,8 +366,8 @@
}
static bool CompileXml(IAaptContext* context, const CompileOptions& options,
- const ResourcePathData& path_data,
- IArchiveWriter* writer, const std::string& output_path) {
+ const ResourcePathData& path_data, IArchiveWriter* writer,
+ const std::string& output_path) {
if (context->IsVerbose()) {
context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling XML");
}
@@ -400,8 +390,7 @@
return false;
}
- xmlres->file.name = ResourceName(
- {}, *ParseResourceType(path_data.resource_dir), path_data.name);
+ xmlres->file.name = ResourceName({}, *ParseResourceType(path_data.resource_dir), path_data.name);
xmlres->file.config = path_data.config;
xmlres->file.source = path_data.source;
@@ -419,8 +408,7 @@
// Start the entry so we can write the header.
if (!writer->StartEntry(output_path, 0)) {
- context->GetDiagnostics()->Error(DiagMessage(output_path)
- << "failed to open file");
+ context->GetDiagnostics()->Error(DiagMessage(output_path) << "failed to open file");
return false;
}
@@ -439,48 +427,42 @@
// Number of CompiledFiles.
output_stream.WriteLittleEndian32(1 + inline_documents.size());
- if (!FlattenXmlToOutStream(context, output_path, xmlres.get(),
- &output_stream)) {
+ if (!FlattenXmlToOutStream(context, output_path, xmlres.get(), &output_stream)) {
return false;
}
for (auto& inline_xml_doc : inline_documents) {
- if (!FlattenXmlToOutStream(context, output_path, inline_xml_doc.get(),
- &output_stream)) {
+ if (!FlattenXmlToOutStream(context, output_path, inline_xml_doc.get(), &output_stream)) {
return false;
}
}
}
if (!writer->FinishEntry()) {
- context->GetDiagnostics()->Error(DiagMessage(output_path)
- << "failed to finish writing data");
+ context->GetDiagnostics()->Error(DiagMessage(output_path) << "failed to finish writing data");
return false;
}
return true;
}
static bool CompilePng(IAaptContext* context, const CompileOptions& options,
- const ResourcePathData& path_data,
- IArchiveWriter* writer, const std::string& output_path) {
+ const ResourcePathData& path_data, IArchiveWriter* writer,
+ const std::string& output_path) {
if (context->IsVerbose()) {
- context->GetDiagnostics()->Note(DiagMessage(path_data.source)
- << "compiling PNG");
+ context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling PNG");
}
BigBuffer buffer(4096);
ResourceFile res_file;
- res_file.name = ResourceName({}, *ParseResourceType(path_data.resource_dir),
- path_data.name);
+ res_file.name = ResourceName({}, *ParseResourceType(path_data.resource_dir), path_data.name);
res_file.config = path_data.config;
res_file.source = path_data.source;
{
std::string content;
if (!android::base::ReadFileToString(path_data.source.path, &content)) {
- context->GetDiagnostics()->Error(
- DiagMessage(path_data.source)
- << android::base::SystemErrorCodeToString(errno));
+ context->GetDiagnostics()->Error(DiagMessage(path_data.source)
+ << android::base::SystemErrorCodeToString(errno));
return false;
}
@@ -517,8 +499,8 @@
}
if (context->IsVerbose()) {
- context->GetDiagnostics()->Note(DiagMessage(path_data.source)
- << "9-patch: " << *nine_patch);
+ context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "9-patch: "
+ << *nine_patch);
}
}
@@ -572,26 +554,22 @@
}
static bool CompileFile(IAaptContext* context, const CompileOptions& options,
- const ResourcePathData& path_data,
- IArchiveWriter* writer,
+ const ResourcePathData& path_data, IArchiveWriter* writer,
const std::string& output_path) {
if (context->IsVerbose()) {
- context->GetDiagnostics()->Note(DiagMessage(path_data.source)
- << "compiling file");
+ context->GetDiagnostics()->Note(DiagMessage(path_data.source) << "compiling file");
}
BigBuffer buffer(256);
ResourceFile res_file;
- res_file.name = ResourceName({}, *ParseResourceType(path_data.resource_dir),
- path_data.name);
+ res_file.name = ResourceName({}, *ParseResourceType(path_data.resource_dir), path_data.name);
res_file.config = path_data.config;
res_file.source = path_data.source;
std::string error_str;
Maybe<android::FileMap> f = file::MmapPath(path_data.source.path, &error_str);
if (!f) {
- context->GetDiagnostics()->Error(DiagMessage(path_data.source)
- << error_str);
+ context->GetDiagnostics()->Error(DiagMessage(path_data.source) << error_str);
return false;
}
@@ -604,11 +582,17 @@
class CompileContext : public IAaptContext {
public:
- void SetVerbose(bool val) { verbose_ = val; }
+ void SetVerbose(bool val) {
+ verbose_ = val;
+ }
- bool IsVerbose() override { return verbose_; }
+ bool IsVerbose() override {
+ return verbose_;
+ }
- IDiagnostics* GetDiagnostics() override { return &diagnostics_; }
+ IDiagnostics* GetDiagnostics() override {
+ return &diagnostics_;
+ }
NameMangler* GetNameMangler() override {
abort();
@@ -620,14 +604,18 @@
return empty;
}
- uint8_t GetPackageId() override { return 0x0; }
+ uint8_t GetPackageId() override {
+ return 0x0;
+ }
SymbolTable* GetExternalSymbols() override {
abort();
return nullptr;
}
- int GetMinSdkVersion() override { return 0; }
+ int GetMinSdkVersion() override {
+ return 0;
+ }
private:
StdErrDiagnostics diagnostics_;
@@ -646,16 +634,13 @@
Flags flags =
Flags()
.RequiredFlag("-o", "Output path", &options.output_path)
- .OptionalFlag("--dir", "Directory to scan for resources",
- &options.res_dir)
+ .OptionalFlag("--dir", "Directory to scan for resources", &options.res_dir)
.OptionalSwitch("--pseudo-localize",
"Generate resources for pseudo-locales "
"(en-XA and ar-XB)",
&options.pseudolocalize)
- .OptionalSwitch(
- "--legacy",
- "Treat errors that used to be valid in AAPT as warnings",
- &options.legacy_mode)
+ .OptionalSwitch("--legacy", "Treat errors that used to be valid in AAPT as warnings",
+ &options.legacy_mode)
.OptionalSwitch("-v", "Enables verbose logging", &verbose);
if (!flags.Parse("aapt2 compile", args, &std::cerr)) {
return 1;
@@ -669,8 +654,7 @@
if (options.res_dir) {
if (!flags.GetArgs().empty()) {
// Can't have both files and a resource directory.
- context.GetDiagnostics()->Error(DiagMessage()
- << "files given but --dir specified");
+ context.GetDiagnostics()->Error(DiagMessage() << "files given but --dir specified");
flags.Usage("aapt2 compile", &std::cerr);
return 1;
}
@@ -679,8 +663,7 @@
return 1;
}
- archive_writer = CreateZipFileArchiveWriter(context.GetDiagnostics(),
- options.output_path);
+ archive_writer = CreateZipFileArchiveWriter(context.GetDiagnostics(), options.output_path);
} else {
input_data.reserve(flags.GetArgs().size());
@@ -688,18 +671,15 @@
// Collect data from the path for each input file.
for (const std::string& arg : flags.GetArgs()) {
std::string error_str;
- if (Maybe<ResourcePathData> path_data =
- ExtractResourcePathData(arg, &error_str)) {
+ if (Maybe<ResourcePathData> path_data = ExtractResourcePathData(arg, &error_str)) {
input_data.push_back(std::move(path_data.value()));
} else {
- context.GetDiagnostics()->Error(DiagMessage() << error_str << " ("
- << arg << ")");
+ context.GetDiagnostics()->Error(DiagMessage() << error_str << " (" << arg << ")");
return 1;
}
}
- archive_writer = CreateDirectoryArchiveWriter(context.GetDiagnostics(),
- options.output_path);
+ archive_writer = CreateDirectoryArchiveWriter(context.GetDiagnostics(), options.output_path);
}
if (!archive_writer) {
@@ -709,8 +689,7 @@
bool error = false;
for (ResourcePathData& path_data : input_data) {
if (options.verbose) {
- context.GetDiagnostics()->Note(DiagMessage(path_data.source)
- << "processing");
+ context.GetDiagnostics()->Note(DiagMessage(path_data.source) << "processing");
}
if (path_data.resource_dir == "values") {
@@ -718,42 +697,35 @@
path_data.extension = "arsc";
const std::string output_filename = BuildIntermediateFilename(path_data);
- if (!CompileTable(&context, options, path_data, archive_writer.get(),
- output_filename)) {
+ if (!CompileTable(&context, options, path_data, archive_writer.get(), output_filename)) {
error = true;
}
} else {
const std::string output_filename = BuildIntermediateFilename(path_data);
- if (const ResourceType* type =
- ParseResourceType(path_data.resource_dir)) {
+ if (const ResourceType* type = ParseResourceType(path_data.resource_dir)) {
if (*type != ResourceType::kRaw) {
if (path_data.extension == "xml") {
- if (!CompileXml(&context, options, path_data, archive_writer.get(),
- output_filename)) {
+ if (!CompileXml(&context, options, path_data, archive_writer.get(), output_filename)) {
error = true;
}
- } else if (path_data.extension == "png" ||
- path_data.extension == "9.png") {
- if (!CompilePng(&context, options, path_data, archive_writer.get(),
- output_filename)) {
+ } else if (path_data.extension == "png" || path_data.extension == "9.png") {
+ if (!CompilePng(&context, options, path_data, archive_writer.get(), output_filename)) {
error = true;
}
} else {
- if (!CompileFile(&context, options, path_data, archive_writer.get(),
- output_filename)) {
+ if (!CompileFile(&context, options, path_data, archive_writer.get(), output_filename)) {
error = true;
}
}
} else {
- if (!CompileFile(&context, options, path_data, archive_writer.get(),
- output_filename)) {
+ if (!CompileFile(&context, options, path_data, archive_writer.get(), output_filename)) {
error = true;
}
}
} else {
- context.GetDiagnostics()->Error(
- DiagMessage() << "invalid file path '" << path_data.source << "'");
+ context.GetDiagnostics()->Error(DiagMessage() << "invalid file path '" << path_data.source
+ << "'");
error = true;
}
}
diff --git a/tools/aapt2/diff/Diff.cpp b/tools/aapt2/cmd/Diff.cpp
similarity index 72%
rename from tools/aapt2/diff/Diff.cpp
rename to tools/aapt2/cmd/Diff.cpp
index dacf8d9..fdc89b2 100644
--- a/tools/aapt2/diff/Diff.cpp
+++ b/tools/aapt2/cmd/Diff.cpp
@@ -28,21 +28,36 @@
class DiffContext : public IAaptContext {
public:
- DiffContext() : name_mangler_({}), symbol_table_(&name_mangler_) {}
+ DiffContext() : name_mangler_({}), symbol_table_(&name_mangler_) {
+ }
- const std::string& GetCompilationPackage() override { return empty_; }
+ const std::string& GetCompilationPackage() override {
+ return empty_;
+ }
- uint8_t GetPackageId() override { return 0x0; }
+ uint8_t GetPackageId() override {
+ return 0x0;
+ }
- IDiagnostics* GetDiagnostics() override { return &diagnostics_; }
+ IDiagnostics* GetDiagnostics() override {
+ return &diagnostics_;
+ }
- NameMangler* GetNameMangler() override { return &name_mangler_; }
+ NameMangler* GetNameMangler() override {
+ return &name_mangler_;
+ }
- SymbolTable* GetExternalSymbols() override { return &symbol_table_; }
+ SymbolTable* GetExternalSymbols() override {
+ return &symbol_table_;
+ }
- bool IsVerbose() override { return false; }
+ bool IsVerbose() override {
+ return false;
+ }
- int GetMinSdkVersion() override { return 0; }
+ int GetMinSdkVersion() override {
+ return 0;
+ }
private:
std::string empty_;
@@ -55,34 +70,31 @@
std::cerr << source << ": " << message << "\n";
}
-static bool IsSymbolVisibilityDifferent(const Symbol& symbol_a,
- const Symbol& symbol_b) {
+static bool IsSymbolVisibilityDifferent(const Symbol& symbol_a, const Symbol& symbol_b) {
return symbol_a.state != symbol_b.state;
}
template <typename Id>
-static bool IsIdDiff(const Symbol& symbol_a, const Maybe<Id>& id_a,
- const Symbol& symbol_b, const Maybe<Id>& id_b) {
- if (symbol_a.state == SymbolState::kPublic ||
- symbol_b.state == SymbolState::kPublic) {
+static bool IsIdDiff(const Symbol& symbol_a, const Maybe<Id>& id_a, const Symbol& symbol_b,
+ const Maybe<Id>& id_b) {
+ if (symbol_a.state == SymbolState::kPublic || symbol_b.state == SymbolState::kPublic) {
return id_a != id_b;
}
return false;
}
-static bool EmitResourceConfigValueDiff(
- IAaptContext* context, LoadedApk* apk_a, ResourceTablePackage* pkg_a,
- ResourceTableType* type_a, ResourceEntry* entry_a,
- ResourceConfigValue* config_value_a, LoadedApk* apk_b,
- ResourceTablePackage* pkg_b, ResourceTableType* type_b,
- ResourceEntry* entry_b, ResourceConfigValue* config_value_b) {
+static bool EmitResourceConfigValueDiff(IAaptContext* context, LoadedApk* apk_a,
+ ResourceTablePackage* pkg_a, ResourceTableType* type_a,
+ ResourceEntry* entry_a, ResourceConfigValue* config_value_a,
+ LoadedApk* apk_b, ResourceTablePackage* pkg_b,
+ ResourceTableType* type_b, ResourceEntry* entry_b,
+ ResourceConfigValue* config_value_b) {
Value* value_a = config_value_a->value.get();
Value* value_b = config_value_b->value.get();
if (!value_a->Equals(value_b)) {
std::stringstream str_stream;
- str_stream << "value " << pkg_a->name << ":" << type_a->type << "/"
- << entry_a->name << " config=" << config_value_a->config
- << " does not match:\n";
+ str_stream << "value " << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
+ << " config=" << config_value_a->config << " does not match:\n";
value_a->Print(&str_stream);
str_stream << "\n vs \n";
value_b->Print(&str_stream);
@@ -93,37 +105,33 @@
}
static bool EmitResourceEntryDiff(IAaptContext* context, LoadedApk* apk_a,
- ResourceTablePackage* pkg_a,
- ResourceTableType* type_a,
+ ResourceTablePackage* pkg_a, ResourceTableType* type_a,
ResourceEntry* entry_a, LoadedApk* apk_b,
- ResourceTablePackage* pkg_b,
- ResourceTableType* type_b,
+ ResourceTablePackage* pkg_b, ResourceTableType* type_b,
ResourceEntry* entry_b) {
bool diff = false;
for (std::unique_ptr<ResourceConfigValue>& config_value_a : entry_a->values) {
- ResourceConfigValue* config_value_b =
- entry_b->FindValue(config_value_a->config);
+ ResourceConfigValue* config_value_b = entry_b->FindValue(config_value_a->config);
if (!config_value_b) {
std::stringstream str_stream;
- str_stream << "missing " << pkg_a->name << ":" << type_a->type << "/"
- << entry_a->name << " config=" << config_value_a->config;
+ str_stream << "missing " << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
+ << " config=" << config_value_a->config;
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
} else {
- diff |= EmitResourceConfigValueDiff(
- context, apk_a, pkg_a, type_a, entry_a, config_value_a.get(), apk_b,
- pkg_b, type_b, entry_b, config_value_b);
+ diff |=
+ EmitResourceConfigValueDiff(context, apk_a, pkg_a, type_a, entry_a, config_value_a.get(),
+ apk_b, pkg_b, type_b, entry_b, config_value_b);
}
}
// Check for any newly added config values.
for (std::unique_ptr<ResourceConfigValue>& config_value_b : entry_b->values) {
- ResourceConfigValue* config_value_a =
- entry_a->FindValue(config_value_b->config);
+ ResourceConfigValue* config_value_a = entry_a->FindValue(config_value_b->config);
if (!config_value_a) {
std::stringstream str_stream;
- str_stream << "new config " << pkg_b->name << ":" << type_b->type << "/"
- << entry_b->name << " config=" << config_value_b->config;
+ str_stream << "new config " << pkg_b->name << ":" << type_b->type << "/" << entry_b->name
+ << " config=" << config_value_b->config;
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
}
@@ -132,22 +140,19 @@
}
static bool EmitResourceTypeDiff(IAaptContext* context, LoadedApk* apk_a,
- ResourceTablePackage* pkg_a,
- ResourceTableType* type_a, LoadedApk* apk_b,
- ResourceTablePackage* pkg_b,
+ ResourceTablePackage* pkg_a, ResourceTableType* type_a,
+ LoadedApk* apk_b, ResourceTablePackage* pkg_b,
ResourceTableType* type_b) {
bool diff = false;
for (std::unique_ptr<ResourceEntry>& entry_a : type_a->entries) {
ResourceEntry* entry_b = type_b->FindEntry(entry_a->name);
if (!entry_b) {
std::stringstream str_stream;
- str_stream << "missing " << pkg_a->name << ":" << type_a->type << "/"
- << entry_a->name;
+ str_stream << "missing " << pkg_a->name << ":" << type_a->type << "/" << entry_a->name;
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
} else {
- if (IsSymbolVisibilityDifferent(entry_a->symbol_status,
- entry_b->symbol_status)) {
+ if (IsSymbolVisibilityDifferent(entry_a->symbol_status, entry_b->symbol_status)) {
std::stringstream str_stream;
str_stream << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
<< " has different visibility (";
@@ -165,8 +170,8 @@
str_stream << ")";
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
- } else if (IsIdDiff(entry_a->symbol_status, entry_a->id,
- entry_b->symbol_status, entry_b->id)) {
+ } else if (IsIdDiff(entry_a->symbol_status, entry_a->id, entry_b->symbol_status,
+ entry_b->id)) {
std::stringstream str_stream;
str_stream << pkg_a->name << ":" << type_a->type << "/" << entry_a->name
<< " has different public ID (";
@@ -185,9 +190,8 @@
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
}
- diff |=
- EmitResourceEntryDiff(context, apk_a, pkg_a, type_a, entry_a.get(),
- apk_b, pkg_b, type_b, entry_b);
+ diff |= EmitResourceEntryDiff(context, apk_a, pkg_a, type_a, entry_a.get(), apk_b, pkg_b,
+ type_b, entry_b);
}
}
@@ -196,8 +200,7 @@
ResourceEntry* entry_a = type_a->FindEntry(entry_b->name);
if (!entry_a) {
std::stringstream str_stream;
- str_stream << "new entry " << pkg_b->name << ":" << type_b->type << "/"
- << entry_b->name;
+ str_stream << "new entry " << pkg_b->name << ":" << type_b->type << "/" << entry_b->name;
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
}
@@ -206,8 +209,7 @@
}
static bool EmitResourcePackageDiff(IAaptContext* context, LoadedApk* apk_a,
- ResourceTablePackage* pkg_a,
- LoadedApk* apk_b,
+ ResourceTablePackage* pkg_a, LoadedApk* apk_b,
ResourceTablePackage* pkg_b) {
bool diff = false;
for (std::unique_ptr<ResourceTableType>& type_a : pkg_a->types) {
@@ -218,11 +220,9 @@
EmitDiffLine(apk_a->GetSource(), str_stream.str());
diff = true;
} else {
- if (IsSymbolVisibilityDifferent(type_a->symbol_status,
- type_b->symbol_status)) {
+ if (IsSymbolVisibilityDifferent(type_a->symbol_status, type_b->symbol_status)) {
std::stringstream str_stream;
- str_stream << pkg_a->name << ":" << type_a->type
- << " has different visibility (";
+ str_stream << pkg_a->name << ":" << type_a->type << " has different visibility (";
if (type_b->symbol_status.state == SymbolState::kPublic) {
str_stream << "PUBLIC";
} else {
@@ -237,11 +237,9 @@
str_stream << ")";
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
- } else if (IsIdDiff(type_a->symbol_status, type_a->id,
- type_b->symbol_status, type_b->id)) {
+ } else if (IsIdDiff(type_a->symbol_status, type_a->id, type_b->symbol_status, type_b->id)) {
std::stringstream str_stream;
- str_stream << pkg_a->name << ":" << type_a->type
- << " has different public ID (";
+ str_stream << pkg_a->name << ":" << type_a->type << " has different public ID (";
if (type_b->id) {
str_stream << "0x" << std::hex << type_b->id.value();
} else {
@@ -257,8 +255,7 @@
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
}
- diff |= EmitResourceTypeDiff(context, apk_a, pkg_a, type_a.get(), apk_b,
- pkg_b, type_b);
+ diff |= EmitResourceTypeDiff(context, apk_a, pkg_a, type_a.get(), apk_b, pkg_b, type_b);
}
}
@@ -275,8 +272,7 @@
return diff;
}
-static bool EmitResourceTableDiff(IAaptContext* context, LoadedApk* apk_a,
- LoadedApk* apk_b) {
+static bool EmitResourceTableDiff(IAaptContext* context, LoadedApk* apk_a, LoadedApk* apk_b) {
ResourceTable* table_a = apk_a->GetResourceTable();
ResourceTable* table_b = apk_b->GetResourceTable();
@@ -307,8 +303,7 @@
EmitDiffLine(apk_b->GetSource(), str_stream.str());
diff = true;
}
- diff |=
- EmitResourcePackageDiff(context, apk_a, pkg_a.get(), apk_b, pkg_b);
+ diff |= EmitResourcePackageDiff(context, apk_a, pkg_a.get(), apk_b, pkg_b);
}
}
@@ -357,10 +352,8 @@
return 1;
}
- std::unique_ptr<LoadedApk> apk_a =
- LoadedApk::LoadApkFromPath(&context, flags.GetArgs()[0]);
- std::unique_ptr<LoadedApk> apk_b =
- LoadedApk::LoadApkFromPath(&context, flags.GetArgs()[1]);
+ std::unique_ptr<LoadedApk> apk_a = LoadedApk::LoadApkFromPath(&context, flags.GetArgs()[0]);
+ std::unique_ptr<LoadedApk> apk_b = LoadedApk::LoadApkFromPath(&context, flags.GetArgs()[1]);
if (!apk_a || !apk_b) {
return 1;
}
diff --git a/tools/aapt2/dump/Dump.cpp b/tools/aapt2/cmd/Dump.cpp
similarity index 71%
rename from tools/aapt2/dump/Dump.cpp
rename to tools/aapt2/cmd/Dump.cpp
index bcede72..1bbfb28 100644
--- a/tools/aapt2/dump/Dump.cpp
+++ b/tools/aapt2/cmd/Dump.cpp
@@ -31,13 +31,12 @@
namespace aapt {
-void DumpCompiledFile(const pb::CompiledFile& pb_file, const void* data,
- size_t len, const Source& source, IAaptContext* context) {
+void DumpCompiledFile(const pb::CompiledFile& pb_file, const void* data, size_t len,
+ const Source& source, IAaptContext* context) {
std::unique_ptr<ResourceFile> file =
DeserializeCompiledFileFromPb(pb_file, source, context->GetDiagnostics());
if (!file) {
- context->GetDiagnostics()->Warn(DiagMessage()
- << "failed to read compiled file");
+ context->GetDiagnostics()->Warn(DiagMessage() << "failed to read compiled file");
return;
}
@@ -50,27 +49,24 @@
std::unique_ptr<ResourceTable> table;
std::string err;
- std::unique_ptr<io::ZipFileCollection> zip =
- io::ZipFileCollection::Create(file_path, &err);
+ std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::Create(file_path, &err);
if (zip) {
io::IFile* file = zip->FindFile("resources.arsc.flat");
if (file) {
std::unique_ptr<io::IData> data = file->OpenAsData();
if (!data) {
- context->GetDiagnostics()->Error(
- DiagMessage(file_path) << "failed to open resources.arsc.flat");
+ context->GetDiagnostics()->Error(DiagMessage(file_path)
+ << "failed to open resources.arsc.flat");
return;
}
pb::ResourceTable pb_table;
if (!pb_table.ParseFromArray(data->data(), data->size())) {
- context->GetDiagnostics()->Error(DiagMessage(file_path)
- << "invalid resources.arsc.flat");
+ context->GetDiagnostics()->Error(DiagMessage(file_path) << "invalid resources.arsc.flat");
return;
}
- table = DeserializeTableFromPb(pb_table, Source(file_path),
- context->GetDiagnostics());
+ table = DeserializeTableFromPb(pb_table, Source(file_path), context->GetDiagnostics());
if (!table) {
return;
}
@@ -87,8 +83,8 @@
}
table = util::make_unique<ResourceTable>();
- BinaryResourceParser parser(context, table.get(), Source(file_path),
- data->data(), data->size());
+ BinaryResourceParser parser(context, table.get(), Source(file_path), data->data(),
+ data->size());
if (!parser.Parse()) {
return;
}
@@ -107,16 +103,13 @@
// Try as a compiled table.
pb::ResourceTable pb_table;
- if (pb_table.ParseFromArray(file_map->getDataPtr(),
- file_map->getDataLength())) {
- table = DeserializeTableFromPb(pb_table, Source(file_path),
- context->GetDiagnostics());
+ if (pb_table.ParseFromArray(file_map->getDataPtr(), file_map->getDataLength())) {
+ table = DeserializeTableFromPb(pb_table, Source(file_path), context->GetDiagnostics());
}
if (!table) {
// Try as a compiled file.
- CompiledFileInputStream input(file_map->getDataPtr(),
- file_map->getDataLength());
+ CompiledFileInputStream input(file_map->getDataPtr(), file_map->getDataLength());
uint32_t num_files = 0;
if (!input.ReadLittleEndian32(&num_files)) {
@@ -126,20 +119,17 @@
for (uint32_t i = 0; i < num_files; i++) {
pb::CompiledFile compiled_file;
if (!input.ReadCompiledFile(&compiled_file)) {
- context->GetDiagnostics()->Warn(DiagMessage()
- << "failed to read compiled file");
+ context->GetDiagnostics()->Warn(DiagMessage() << "failed to read compiled file");
return;
}
uint64_t offset, len;
if (!input.ReadDataMetaData(&offset, &len)) {
- context->GetDiagnostics()->Warn(DiagMessage()
- << "failed to read meta data");
+ context->GetDiagnostics()->Warn(DiagMessage() << "failed to read meta data");
return;
}
- const void* data =
- static_cast<const uint8_t*>(file_map->getDataPtr()) + offset;
+ const void* data = static_cast<const uint8_t*>(file_map->getDataPtr()) + offset;
DumpCompiledFile(compiled_file, data, len, Source(file_path), context);
}
}
@@ -154,7 +144,9 @@
class DumpContext : public IAaptContext {
public:
- IDiagnostics* GetDiagnostics() override { return &diagnostics_; }
+ IDiagnostics* GetDiagnostics() override {
+ return &diagnostics_;
+ }
NameMangler* GetNameMangler() override {
abort();
@@ -166,18 +158,26 @@
return empty;
}
- uint8_t GetPackageId() override { return 0; }
+ uint8_t GetPackageId() override {
+ return 0;
+ }
SymbolTable* GetExternalSymbols() override {
abort();
return nullptr;
}
- bool IsVerbose() override { return verbose_; }
+ bool IsVerbose() override {
+ return verbose_;
+ }
- void SetVerbose(bool val) { verbose_ = val; }
+ void SetVerbose(bool val) {
+ verbose_ = val;
+ }
- int GetMinSdkVersion() override { return 0; }
+ int GetMinSdkVersion() override {
+ return 0;
+ }
private:
StdErrDiagnostics diagnostics_;
@@ -189,8 +189,7 @@
*/
int Dump(const std::vector<StringPiece>& args) {
bool verbose = false;
- Flags flags =
- Flags().OptionalSwitch("-v", "increase verbosity of output", &verbose);
+ Flags flags = Flags().OptionalSwitch("-v", "increase verbosity of output", &verbose);
if (!flags.Parse("aapt2 dump", args, &std::cerr)) {
return 1;
}
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/cmd/Link.cpp
similarity index 72%
rename from tools/aapt2/link/Link.cpp
rename to tools/aapt2/cmd/Link.cpp
index 407eb52..b86188f 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -33,6 +33,7 @@
#include "Locale.h"
#include "NameMangler.h"
#include "ResourceUtils.h"
+#include "cmd/Util.h"
#include "compile/IdAssigner.h"
#include "filter/ConfigFilter.h"
#include "flatten/Archive.h"
@@ -40,6 +41,7 @@
#include "flatten/XmlFlattener.h"
#include "io/BigBufferInputStream.h"
#include "io/FileSystem.h"
+#include "io/Util.h"
#include "io/ZipArchive.h"
#include "java/JavaClassGenerator.h"
#include "java/ManifestClassGenerator.h"
@@ -60,7 +62,6 @@
using android::StringPiece;
using android::base::StringPrintf;
-using ::google::protobuf::io::CopyingOutputStreamAdaptor;
namespace aapt {
@@ -86,6 +87,7 @@
Maybe<std::string> generate_java_class_path;
Maybe<std::string> custom_java_package;
std::set<std::string> extra_java_packages;
+ Maybe<std::string> generate_text_symbols_path;
Maybe<std::string> generate_proguard_rules_path;
Maybe<std::string> generate_main_dex_proguard_rules_path;
bool generate_non_final_ids = false;
@@ -125,11 +127,16 @@
class LinkContext : public IAaptContext {
public:
- LinkContext() : name_mangler_({}), symbols_(&name_mangler_) {}
+ LinkContext() : name_mangler_({}), symbols_(&name_mangler_) {
+ }
- IDiagnostics* GetDiagnostics() override { return &diagnostics_; }
+ IDiagnostics* GetDiagnostics() override {
+ return &diagnostics_;
+ }
- NameMangler* GetNameMangler() override { return &name_mangler_; }
+ NameMangler* GetNameMangler() override {
+ return &name_mangler_;
+ }
void SetNameManglerPolicy(const NameManglerPolicy& policy) {
name_mangler_ = NameMangler(policy);
@@ -143,19 +150,33 @@
compilation_package_ = package_name.to_string();
}
- uint8_t GetPackageId() override { return package_id_; }
+ uint8_t GetPackageId() override {
+ return package_id_;
+ }
- void SetPackageId(uint8_t id) { package_id_ = id; }
+ void SetPackageId(uint8_t id) {
+ package_id_ = id;
+ }
- SymbolTable* GetExternalSymbols() override { return &symbols_; }
+ SymbolTable* GetExternalSymbols() override {
+ return &symbols_;
+ }
- bool IsVerbose() override { return verbose_; }
+ bool IsVerbose() override {
+ return verbose_;
+ }
- void SetVerbose(bool val) { verbose_ = val; }
+ void SetVerbose(bool val) {
+ verbose_ = val;
+ }
- int GetMinSdkVersion() override { return min_sdk_version_; }
+ int GetMinSdkVersion() override {
+ return min_sdk_version_;
+ }
- void SetMinSdkVersion(int minSdk) { min_sdk_version_ = minSdk; }
+ void SetMinSdkVersion(int minSdk) {
+ min_sdk_version_ = minSdk;
+ }
private:
DISALLOW_COPY_AND_ASSIGN(LinkContext);
@@ -169,63 +190,9 @@
int min_sdk_version_ = 0;
};
-static bool CopyInputStreamToArchive(io::InputStream* in, const std::string& out_path,
- uint32_t compression_flags, IArchiveWriter* writer,
- IAaptContext* context) {
- if (context->IsVerbose()) {
- context->GetDiagnostics()->Note(DiagMessage() << "writing " << out_path << " to archive");
- }
-
- if (!writer->WriteFile(out_path, compression_flags, in)) {
- context->GetDiagnostics()->Error(DiagMessage() << "failed to write " << out_path
- << " to archive: " << writer->GetError());
- return false;
- }
- return true;
-}
-
-static bool CopyFileToArchive(io::IFile* file, const std::string& out_path,
- uint32_t compression_flags,
- IArchiveWriter* writer, IAaptContext* context) {
- std::unique_ptr<io::IData> data = file->OpenAsData();
- if (!data) {
- context->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << "failed to open file");
- return false;
- }
- return CopyInputStreamToArchive(data.get(), out_path, compression_flags, writer, context);
-}
-
-static bool CopyProtoToArchive(::google::protobuf::MessageLite* proto_msg,
- const std::string& out_path, uint32_t compression_flags,
- IArchiveWriter* writer, IAaptContext* context) {
- if (context->IsVerbose()) {
- context->GetDiagnostics()->Note(DiagMessage() << "writing " << out_path << " to archive");
- }
-
- if (writer->StartEntry(out_path, compression_flags)) {
- // Make sure CopyingOutputStreamAdaptor is deleted before we call writer->FinishEntry().
- {
- // Wrap our IArchiveWriter with an adaptor that implements the ZeroCopyOutputStream interface.
- ::google::protobuf::io::CopyingOutputStreamAdaptor adaptor(writer);
- if (!proto_msg->SerializeToZeroCopyStream(&adaptor)) {
- context->GetDiagnostics()->Error(DiagMessage()
- << "failed to write " << out_path << " to archive");
- return false;
- }
- }
-
- if (writer->FinishEntry()) {
- return true;
- }
- }
- context->GetDiagnostics()->Error(DiagMessage() << "failed to write " << out_path
- << " to archive: " << writer->GetError());
- return false;
-}
-
static bool FlattenXml(xml::XmlResource* xml_res, const StringPiece& path,
- Maybe<size_t> max_sdk_level, bool keep_raw_values,
- IArchiveWriter* writer, IAaptContext* context) {
+ Maybe<size_t> max_sdk_level, bool keep_raw_values, IArchiveWriter* writer,
+ IAaptContext* context) {
BigBuffer buffer(1024);
XmlFlattenerOptions options = {};
options.keep_raw_values = keep_raw_values;
@@ -239,21 +206,18 @@
DiagMessage msg;
msg << "writing " << path << " to archive";
if (max_sdk_level) {
- msg << " maxSdkLevel=" << max_sdk_level.value()
- << " keepRawValues=" << keep_raw_values;
+ msg << " maxSdkLevel=" << max_sdk_level.value() << " keepRawValues=" << keep_raw_values;
}
context->GetDiagnostics()->Note(msg);
}
io::BigBufferInputStream input_stream(&buffer);
- return CopyInputStreamToArchive(&input_stream, path.to_string(), ArchiveEntry::kCompress, writer,
- context);
+ return io::CopyInputStreamToArchive(context, &input_stream, path.to_string(),
+ ArchiveEntry::kCompress, writer);
}
-static std::unique_ptr<ResourceTable> LoadTableFromPb(const Source& source,
- const void* data,
- size_t len,
- IDiagnostics* diag) {
+static std::unique_ptr<ResourceTable> LoadTableFromPb(const Source& source, const void* data,
+ size_t len, IDiagnostics* diag) {
pb::ResourceTable pb_table;
if (!pb_table.ParseFromArray(data, len)) {
diag->Error(DiagMessage(source) << "invalid compiled table");
@@ -270,8 +234,7 @@
/**
* Inflates an XML file from the source path.
*/
-static std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path,
- IDiagnostics* diag) {
+static std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path, IDiagnostics* diag) {
std::ifstream fin(path, std::ifstream::binary);
if (!fin) {
diag->Error(DiagMessage(path) << strerror(errno));
@@ -293,9 +256,10 @@
class ResourceFileFlattener {
public:
- ResourceFileFlattener(const ResourceFileFlattenerOptions& options,
- IAaptContext* context, proguard::KeepSet* keep_set)
- : options_(options), context_(context), keep_set_(keep_set) {}
+ ResourceFileFlattener(const ResourceFileFlattenerOptions& options, IAaptContext* context,
+ proguard::KeepSet* keep_set)
+ : options_(options), context_(context), keep_set_(keep_set) {
+ }
bool Flatten(ResourceTable* table, IArchiveWriter* archive_writer);
@@ -341,25 +305,15 @@
}
static bool IsTransitionElement(const std::string& name) {
- return
- name == "fade" ||
- name == "changeBounds" ||
- name == "slide" ||
- name == "explode" ||
- name == "changeImageTransform" ||
- name == "changeTransform" ||
- name == "changeClipBounds" ||
- name == "autoTransition" ||
- name == "recolor" ||
- name == "changeScroll" ||
- name == "transitionSet" ||
- name == "transition" ||
- name == "transitionManager";
+ return name == "fade" || name == "changeBounds" || name == "slide" || name == "explode" ||
+ name == "changeImageTransform" || name == "changeTransform" ||
+ name == "changeClipBounds" || name == "autoTransition" || name == "recolor" ||
+ name == "changeScroll" || name == "transitionSet" || name == "transition" ||
+ name == "transitionManager";
}
-bool ResourceFileFlattener::LinkAndVersionXmlFile(
- ResourceTable* table, FileOperation* file_op,
- std::queue<FileOperation>* out_file_op_queue) {
+bool ResourceFileFlattener::LinkAndVersionXmlFile(ResourceTable* table, FileOperation* file_op,
+ std::queue<FileOperation>* out_file_op_queue) {
xml::XmlResource* doc = file_op->xml_to_flatten.get();
const Source& src = doc->file.source;
@@ -372,8 +326,7 @@
return false;
}
- if (options_.update_proguard_spec &&
- !proguard::CollectProguardRules(src, doc, keep_set_)) {
+ if (options_.update_proguard_spec && !proguard::CollectProguardRules(src, doc, keep_set_)) {
return false;
}
@@ -415,8 +368,7 @@
const int min_sdk_version = context_->GetMinSdkVersion();
for (int sdk_level : xml_linker.sdk_levels()) {
if (sdk_level > min_sdk_version && sdk_level > config.sdkVersion) {
- if (!ShouldGenerateVersionedResource(file_op->entry, config,
- sdk_level)) {
+ if (!ShouldGenerateVersionedResource(file_op->entry, config, sdk_level)) {
// If we shouldn't generate a versioned resource, stop checking.
break;
}
@@ -426,23 +378,21 @@
FileOperation new_file_op;
new_file_op.xml_to_flatten = util::make_unique<xml::XmlResource>(
- versioned_file_desc, doc->root->Clone());
+ versioned_file_desc, StringPool{}, doc->root->Clone());
new_file_op.config = versioned_file_desc.config;
new_file_op.entry = file_op->entry;
- new_file_op.dst_path = ResourceUtils::BuildResourceFileName(
- versioned_file_desc, context_->GetNameMangler());
+ new_file_op.dst_path =
+ ResourceUtils::BuildResourceFileName(versioned_file_desc, context_->GetNameMangler());
if (context_->IsVerbose()) {
- context_->GetDiagnostics()->Note(
- DiagMessage(versioned_file_desc.source)
- << "auto-versioning resource from config '" << config << "' -> '"
- << versioned_file_desc.config << "'");
+ context_->GetDiagnostics()->Note(DiagMessage(versioned_file_desc.source)
+ << "auto-versioning resource from config '" << config
+ << "' -> '" << versioned_file_desc.config << "'");
}
bool added = table->AddFileReferenceAllowMangled(
- versioned_file_desc.name, versioned_file_desc.config,
- versioned_file_desc.source, new_file_op.dst_path, nullptr,
- context_->GetDiagnostics());
+ versioned_file_desc.name, versioned_file_desc.config, versioned_file_desc.source,
+ new_file_op.dst_path, nullptr, context_->GetDiagnostics());
if (!added) {
return false;
}
@@ -460,11 +410,9 @@
* will
* corrupt the iteration order.
*/
-bool ResourceFileFlattener::Flatten(ResourceTable* table,
- IArchiveWriter* archive_writer) {
+bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archive_writer) {
bool error = false;
- std::map<std::pair<ConfigDescription, StringPiece>, FileOperation>
- config_sorted_files;
+ std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files;
for (auto& pkg : table->packages) {
for (auto& type : pkg->types) {
@@ -476,8 +424,7 @@
// Populate the queue with all files in the ResourceTable.
for (auto& entry : type->entries) {
for (auto& config_value : entry->values) {
- FileReference* file_ref =
- ValueCast<FileReference>(config_value->value.get());
+ FileReference* file_ref = ValueCast<FileReference>(config_value->value.get());
if (!file_ref) {
continue;
}
@@ -496,8 +443,7 @@
const StringPiece src_path = file->GetSource().path;
if (type->type != ResourceType::kRaw &&
- (util::EndsWith(src_path, ".xml.flat") ||
- util::EndsWith(src_path, ".xml"))) {
+ (util::EndsWith(src_path, ".xml.flat") || util::EndsWith(src_path, ".xml"))) {
std::unique_ptr<io::IData> data = file->OpenAsData();
if (!data) {
context_->GetDiagnostics()->Error(DiagMessage(file->GetSource())
@@ -505,9 +451,8 @@
return false;
}
- file_op.xml_to_flatten =
- xml::Inflate(data->data(), data->size(),
- context_->GetDiagnostics(), file->GetSource());
+ file_op.xml_to_flatten = xml::Inflate(data->data(), data->size(),
+ context_->GetDiagnostics(), file->GetSource());
if (!file_op.xml_to_flatten) {
return false;
@@ -515,8 +460,7 @@
file_op.xml_to_flatten->file.config = config_value->config;
file_op.xml_to_flatten->file.source = file_ref->GetSource();
- file_op.xml_to_flatten->file.name =
- ResourceName(pkg->name, type->type, entry->name);
+ file_op.xml_to_flatten->file.name = ResourceName(pkg->name, type->type, entry->name);
// Enqueue the XML files to be processed.
file_operations.push(std::move(file_op));
@@ -528,8 +472,8 @@
// then creating a StringPiece from the copy, which would cause us
// to end up referencing garbage in the map.
const StringPiece entry_name(entry->name);
- config_sorted_files[std::make_pair(
- config_value->config, entry_name)] = std::move(file_op);
+ config_sorted_files[std::make_pair(config_value->config, entry_name)] =
+ std::move(file_op);
}
}
}
@@ -548,8 +492,7 @@
// creating a StringPiece from the copy, which would cause us to end up
// referencing garbage in the map.
const StringPiece entry_name(file_op.entry->name);
- config_sorted_files[std::make_pair(file_op.config, entry_name)] =
- std::move(file_op);
+ config_sorted_files[std::make_pair(file_op.config, entry_name)] = std::move(file_op);
}
if (error) {
@@ -564,21 +507,19 @@
if (file_op.xml_to_flatten) {
Maybe<size_t> max_sdk_level;
if (!options_.no_auto_version && !file_op.skip_version) {
- max_sdk_level =
- std::max<size_t>(std::max<size_t>(config.sdkVersion, 1u),
- context_->GetMinSdkVersion());
+ max_sdk_level = std::max<size_t>(std::max<size_t>(config.sdkVersion, 1u),
+ context_->GetMinSdkVersion());
}
- bool result = FlattenXml(
- file_op.xml_to_flatten.get(), file_op.dst_path, max_sdk_level,
- options_.keep_raw_values, archive_writer, context_);
+ bool result = FlattenXml(file_op.xml_to_flatten.get(), file_op.dst_path, max_sdk_level,
+ options_.keep_raw_values, archive_writer, context_);
if (!result) {
error = true;
}
} else {
- bool result = CopyFileToArchive(
- file_op.file_to_copy, file_op.dst_path,
- GetCompressionFlags(file_op.dst_path), archive_writer, context_);
+ bool result =
+ io::CopyFileToArchive(context_, file_op.file_to_copy, file_op.dst_path,
+ GetCompressionFlags(file_op.dst_path), archive_writer);
if (!result) {
error = true;
}
@@ -589,10 +530,9 @@
return !error;
}
-static bool WriteStableIdMapToPath(
- IDiagnostics* diag,
- const std::unordered_map<ResourceName, ResourceId>& id_map,
- const std::string& id_map_path) {
+static bool WriteStableIdMapToPath(IDiagnostics* diag,
+ const std::unordered_map<ResourceName, ResourceId>& id_map,
+ const std::string& id_map_path) {
std::ofstream fout(id_map_path, std::ofstream::binary);
if (!fout) {
diag->Error(DiagMessage(id_map_path) << strerror(errno));
@@ -606,18 +546,16 @@
}
if (!fout) {
- diag->Error(DiagMessage(id_map_path)
- << "failed writing to file: "
- << android::base::SystemErrorCodeToString(errno));
+ diag->Error(DiagMessage(id_map_path) << "failed writing to file: "
+ << android::base::SystemErrorCodeToString(errno));
return false;
}
return true;
}
-static bool LoadStableIdMap(
- IDiagnostics* diag, const std::string& path,
- std::unordered_map<ResourceName, ResourceId>* out_id_map) {
+static bool LoadStableIdMap(IDiagnostics* diag, const std::string& path,
+ std::unordered_map<ResourceName, ResourceId>* out_id_map) {
std::string content;
if (!android::base::ReadFileToString(path, &content)) {
diag->Error(DiagMessage(path) << "failed reading stable ID file");
@@ -643,20 +581,19 @@
StringPiece res_name_str =
util::TrimWhitespace(line.substr(0, std::distance(line.begin(), iter)));
if (!ResourceUtils::ParseResourceName(res_name_str, &name)) {
- diag->Error(DiagMessage(Source(path, line_no))
- << "invalid resource name '" << res_name_str << "'");
+ diag->Error(DiagMessage(Source(path, line_no)) << "invalid resource name '" << res_name_str
+ << "'");
return false;
}
const size_t res_id_start_idx = std::distance(line.begin(), iter) + 1;
const size_t res_id_str_len = line.size() - res_id_start_idx;
- StringPiece res_id_str =
- util::TrimWhitespace(line.substr(res_id_start_idx, res_id_str_len));
+ StringPiece res_id_str = util::TrimWhitespace(line.substr(res_id_start_idx, res_id_str_len));
Maybe<ResourceId> maybe_id = ResourceUtils::ParseResourceId(res_id_str);
if (!maybe_id) {
- diag->Error(DiagMessage(Source(path, line_no)) << "invalid resource ID '"
- << res_id_str << "'");
+ diag->Error(DiagMessage(Source(path, line_no)) << "invalid resource ID '" << res_id_str
+ << "'");
return false;
}
@@ -665,38 +602,14 @@
return true;
}
-static bool ParseSplitParameter(const StringPiece& arg, IDiagnostics* diag,
- std::string* out_path,
- SplitConstraints* out_split) {
- std::vector<std::string> parts = util::Split(arg, ':');
- if (parts.size() != 2) {
- diag->Error(DiagMessage() << "invalid split parameter '" << arg << "'");
- diag->Note(
- DiagMessage()
- << "should be --split path/to/output.apk:<config>[,<config>...]");
- return false;
- }
- *out_path = parts[0];
- std::vector<ConfigDescription> configs;
- for (const StringPiece& config_str : util::Tokenize(parts[1], ',')) {
- configs.push_back({});
- if (!ConfigDescription::Parse(config_str, &configs.back())) {
- diag->Error(DiagMessage() << "invalid config '" << config_str
- << "' in split parameter '" << arg << "'");
- return false;
- }
- }
- out_split->configs.insert(configs.begin(), configs.end());
- return true;
-}
-
class LinkCommand {
public:
LinkCommand(LinkContext* context, const LinkOptions& options)
: options_(options),
context_(context),
final_table_(),
- file_collection_(util::make_unique<io::FileCollection>()) {}
+ file_collection_(util::make_unique<io::FileCollection>()) {
+ }
/**
* Creates a SymbolTable that loads symbols from the various APKs and caches
@@ -707,8 +620,7 @@
util::make_unique<AssetManagerSymbolSource>();
for (const std::string& path : options_.include_paths) {
if (context_->IsVerbose()) {
- context_->GetDiagnostics()->Note(DiagMessage(path)
- << "loading include path");
+ context_->GetDiagnostics()->Note(DiagMessage(path) << "loading include path");
}
// First try to load the file as a static lib.
@@ -820,7 +732,7 @@
if (xml::Element* uses_sdk_el = manifest_el->FindChild({}, "uses-sdk")) {
if (xml::Attribute* min_sdk =
uses_sdk_el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion")) {
- app_info.min_sdk_version = min_sdk->value;
+ app_info.min_sdk_version = ResourceUtils::ParseSdkVersion(min_sdk->value);
}
}
return app_info;
@@ -832,8 +744,7 @@
* stripped, or there is an error and false is returned.
*/
bool VerifyNoExternalPackages() {
- auto is_ext_package_func =
- [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool {
+ auto is_ext_package_func = [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool {
return context_->GetCompilationPackage() != pkg->name || !pkg->id ||
pkg->id.value() != context_->GetPackageId();
};
@@ -849,17 +760,16 @@
for (const auto& config_value : entry->values) {
// Special case the occurrence of an ID that is being generated
// for the 'android' package. This is due to legacy reasons.
- if (ValueCast<Id>(config_value->value.get()) &&
- package->name == "android") {
- context_->GetDiagnostics()->Warn(
- DiagMessage(config_value->value->GetSource())
- << "generated id '" << res_name
- << "' for external package '" << package->name << "'");
+ if (ValueCast<Id>(config_value->value.get()) && package->name == "android") {
+ context_->GetDiagnostics()->Warn(DiagMessage(config_value->value->GetSource())
+ << "generated id '" << res_name
+ << "' for external package '" << package->name
+ << "'");
} else {
- context_->GetDiagnostics()->Error(
- DiagMessage(config_value->value->GetSource())
- << "defined resource '" << res_name
- << "' for external package '" << package->name << "'");
+ context_->GetDiagnostics()->Error(DiagMessage(config_value->value->GetSource())
+ << "defined resource '" << res_name
+ << "' for external package '" << package->name
+ << "'");
error = true;
}
}
@@ -868,9 +778,8 @@
}
}
- auto new_end_iter =
- std::remove_if(final_table_.packages.begin(),
- final_table_.packages.end(), is_ext_package_func);
+ auto new_end_iter = std::remove_if(final_table_.packages.begin(), final_table_.packages.end(),
+ is_ext_package_func);
final_table_.packages.erase(new_end_iter, final_table_.packages.end());
return !error;
}
@@ -919,19 +828,18 @@
}
io::BigBufferInputStream input_stream(&buffer);
- return CopyInputStreamToArchive(&input_stream, "resources.arsc", ArchiveEntry::kAlign, writer,
- context_);
+ return io::CopyInputStreamToArchive(context_, &input_stream, "resources.arsc",
+ ArchiveEntry::kAlign, writer);
}
bool FlattenTableToPb(ResourceTable* table, IArchiveWriter* writer) {
std::unique_ptr<pb::ResourceTable> pb_table = SerializeTableToPb(table);
- return CopyProtoToArchive(pb_table.get(), "resources.arsc.flat", 0, writer, context_);
+ return io::CopyProtoToArchive(context_, pb_table.get(), "resources.arsc.flat", 0, writer);
}
- bool WriteJavaFile(ResourceTable* table,
- const StringPiece& package_name_to_generate,
- const StringPiece& out_package,
- const JavaClassGeneratorOptions& java_options) {
+ bool WriteJavaFile(ResourceTable* table, const StringPiece& package_name_to_generate,
+ const StringPiece& out_package, const JavaClassGeneratorOptions& java_options,
+ const Maybe<std::string> out_text_symbols_path = {}) {
if (!options_.generate_java_class_path) {
return true;
}
@@ -939,8 +847,8 @@
std::string out_path = options_.generate_java_class_path.value();
file::AppendPath(&out_path, file::PackageToPath(out_package));
if (!file::mkdirs(out_path)) {
- context_->GetDiagnostics()->Error(
- DiagMessage() << "failed to create directory '" << out_path << "'");
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed to create directory '" << out_path
+ << "'");
return false;
}
@@ -948,22 +856,34 @@
std::ofstream fout(out_path, std::ofstream::binary);
if (!fout) {
- context_->GetDiagnostics()->Error(
- DiagMessage() << "failed writing to '" << out_path << "': "
- << android::base::SystemErrorCodeToString(errno));
+ context_->GetDiagnostics()->Error(DiagMessage()
+ << "failed writing to '" << out_path
+ << "': " << android::base::SystemErrorCodeToString(errno));
return false;
}
+ std::unique_ptr<std::ofstream> fout_text;
+ if (out_text_symbols_path) {
+ fout_text =
+ util::make_unique<std::ofstream>(out_text_symbols_path.value(), std::ofstream::binary);
+ if (!*fout_text) {
+ context_->GetDiagnostics()->Error(
+ DiagMessage() << "failed writing to '" << out_text_symbols_path.value()
+ << "': " << android::base::SystemErrorCodeToString(errno));
+ return false;
+ }
+ }
+
JavaClassGenerator generator(context_, table, java_options);
- if (!generator.Generate(package_name_to_generate, out_package, &fout)) {
+ if (!generator.Generate(package_name_to_generate, out_package, &fout, fout_text.get())) {
context_->GetDiagnostics()->Error(DiagMessage(out_path) << generator.getError());
return false;
}
if (!fout) {
- context_->GetDiagnostics()->Error(
- DiagMessage() << "failed writing to '" << out_path << "': "
- << android::base::SystemErrorCodeToString(errno));
+ context_->GetDiagnostics()->Error(DiagMessage()
+ << "failed writing to '" << out_path
+ << "': " << android::base::SystemErrorCodeToString(errno));
}
return true;
}
@@ -999,8 +919,8 @@
file::AppendPath(&out_path, file::PackageToPath(package_utf8));
if (!file::mkdirs(out_path)) {
- context_->GetDiagnostics()->Error(
- DiagMessage() << "failed to create directory '" << out_path << "'");
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed to create directory '" << out_path
+ << "'");
return false;
}
@@ -1008,24 +928,22 @@
std::ofstream fout(out_path, std::ofstream::binary);
if (!fout) {
- context_->GetDiagnostics()->Error(
- DiagMessage() << "failed writing to '" << out_path << "': "
- << android::base::SystemErrorCodeToString(errno));
+ context_->GetDiagnostics()->Error(DiagMessage()
+ << "failed writing to '" << out_path
+ << "': " << android::base::SystemErrorCodeToString(errno));
return false;
}
- if (!ClassDefinition::WriteJavaFile(manifest_class.get(), package_utf8,
- true, &fout)) {
- context_->GetDiagnostics()->Error(
- DiagMessage() << "failed writing to '" << out_path << "': "
- << android::base::SystemErrorCodeToString(errno));
+ if (!ClassDefinition::WriteJavaFile(manifest_class.get(), package_utf8, true, &fout)) {
+ context_->GetDiagnostics()->Error(DiagMessage()
+ << "failed writing to '" << out_path
+ << "': " << android::base::SystemErrorCodeToString(errno));
return false;
}
return true;
}
- bool WriteProguardFile(const Maybe<std::string>& out,
- const proguard::KeepSet& keep_set) {
+ bool WriteProguardFile(const Maybe<std::string>& out, const proguard::KeepSet& keep_set) {
if (!out) {
return true;
}
@@ -1033,17 +951,17 @@
const std::string& out_path = out.value();
std::ofstream fout(out_path, std::ofstream::binary);
if (!fout) {
- context_->GetDiagnostics()->Error(
- DiagMessage() << "failed to open '" << out_path << "': "
- << android::base::SystemErrorCodeToString(errno));
+ context_->GetDiagnostics()->Error(DiagMessage()
+ << "failed to open '" << out_path
+ << "': " << android::base::SystemErrorCodeToString(errno));
return false;
}
proguard::WriteKeepSet(&fout, keep_set);
if (!fout) {
- context_->GetDiagnostics()->Error(
- DiagMessage() << "failed writing to '" << out_path << "': "
- << android::base::SystemErrorCodeToString(errno));
+ context_->GetDiagnostics()->Error(DiagMessage()
+ << "failed writing to '" << out_path
+ << "': " << android::base::SystemErrorCodeToString(errno));
return false;
}
return true;
@@ -1059,8 +977,7 @@
return LoadTablePbFromCollection(collection.get());
}
- std::unique_ptr<ResourceTable> LoadTablePbFromCollection(
- io::IFileCollection* collection) {
+ std::unique_ptr<ResourceTable> LoadTablePbFromCollection(io::IFileCollection* collection) {
io::IFile* file = collection->FindFile("resources.arsc.flat");
if (!file) {
return {};
@@ -1073,8 +990,7 @@
bool MergeStaticLibrary(const std::string& input, bool override) {
if (context_->IsVerbose()) {
- context_->GetDiagnostics()->Note(DiagMessage()
- << "merging static library " << input);
+ context_->GetDiagnostics()->Note(DiagMessage() << "merging static library " << input);
}
std::string error_str;
@@ -1118,8 +1034,8 @@
} else {
// This is the proper way to merge libraries, where the package name is
// preserved and resource names are mangled.
- result = table_merger_->MergeAndMangle(Source(input), pkg->name,
- table.get(), collection.get());
+ result =
+ table_merger_->MergeAndMangle(Source(input), pkg->name, table.get(), collection.get());
}
if (!result) {
@@ -1133,20 +1049,18 @@
bool MergeResourceTable(io::IFile* file, bool override) {
if (context_->IsVerbose()) {
- context_->GetDiagnostics()->Note(
- DiagMessage() << "merging resource table " << file->GetSource());
+ context_->GetDiagnostics()->Note(DiagMessage() << "merging resource table "
+ << file->GetSource());
}
std::unique_ptr<io::IData> data = file->OpenAsData();
if (!data) {
- context_->GetDiagnostics()->Error(DiagMessage(file->GetSource())
- << "failed to open file");
+ context_->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << "failed to open file");
return false;
}
std::unique_ptr<ResourceTable> table =
- LoadTableFromPb(file->GetSource(), data->data(), data->size(),
- context_->GetDiagnostics());
+ LoadTableFromPb(file->GetSource(), data->data(), data->size(), context_->GetDiagnostics());
if (!table) {
return false;
}
@@ -1160,12 +1074,11 @@
return result;
}
- bool MergeCompiledFile(io::IFile* file, ResourceFile* file_desc,
- bool override) {
+ bool MergeCompiledFile(io::IFile* file, ResourceFile* file_desc, bool override) {
if (context_->IsVerbose()) {
- context_->GetDiagnostics()->Note(
- DiagMessage() << "merging '" << file_desc->name
- << "' from compiled file " << file->GetSource());
+ context_->GetDiagnostics()->Note(DiagMessage() << "merging '" << file_desc->name
+ << "' from compiled file "
+ << file->GetSource());
}
bool result = false;
@@ -1196,8 +1109,8 @@
std::unique_ptr<Id> id = util::make_unique<Id>();
id->SetSource(file_desc->source.WithLine(exported_symbol.line));
bool result = final_table_.AddResourceAllowMangled(
- res_name, ConfigDescription::DefaultConfig(), std::string(),
- std::move(id), context_->GetDiagnostics());
+ res_name, ConfigDescription::DefaultConfig(), std::string(), std::move(id),
+ context_->GetDiagnostics());
if (!result) {
return false;
}
@@ -1216,8 +1129,7 @@
*/
bool MergeArchive(const std::string& input, bool override) {
if (context_->IsVerbose()) {
- context_->GetDiagnostics()->Note(DiagMessage() << "merging archive "
- << input);
+ context_->GetDiagnostics()->Note(DiagMessage() << "merging archive " << input);
}
std::string error_str;
@@ -1296,49 +1208,43 @@
CompiledFileInputStream input_stream(data->data(), data->size());
uint32_t num_files = 0;
if (!input_stream.ReadLittleEndian32(&num_files)) {
- context_->GetDiagnostics()->Error(DiagMessage(src)
- << "failed read num files");
+ context_->GetDiagnostics()->Error(DiagMessage(src) << "failed read num files");
return false;
}
for (uint32_t i = 0; i < num_files; i++) {
pb::CompiledFile compiled_file;
if (!input_stream.ReadCompiledFile(&compiled_file)) {
- context_->GetDiagnostics()->Error(
- DiagMessage(src) << "failed to read compiled file header");
+ context_->GetDiagnostics()->Error(DiagMessage(src)
+ << "failed to read compiled file header");
return false;
}
uint64_t offset, len;
if (!input_stream.ReadDataMetaData(&offset, &len)) {
- context_->GetDiagnostics()->Error(DiagMessage(src)
- << "failed to read data meta data");
+ context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to read data meta data");
return false;
}
- std::unique_ptr<ResourceFile> resource_file =
- DeserializeCompiledFileFromPb(compiled_file, file->GetSource(),
- context_->GetDiagnostics());
+ std::unique_ptr<ResourceFile> resource_file = DeserializeCompiledFileFromPb(
+ compiled_file, file->GetSource(), context_->GetDiagnostics());
if (!resource_file) {
return false;
}
- if (!MergeCompiledFile(file->CreateFileSegment(offset, len),
- resource_file.get(), override)) {
+ if (!MergeCompiledFile(file->CreateFileSegment(offset, len), resource_file.get(),
+ override)) {
return false;
}
}
return true;
- } else if (util::EndsWith(src.path, ".xml") ||
- util::EndsWith(src.path, ".png")) {
+ } else if (util::EndsWith(src.path, ".xml") || util::EndsWith(src.path, ".png")) {
// Since AAPT compiles these file types and appends .flat to them, seeing
// their raw extensions is a sign that they weren't compiled.
- const StringPiece file_type =
- util::EndsWith(src.path, ".xml") ? "XML" : "PNG";
- context_->GetDiagnostics()->Error(DiagMessage(src)
- << "uncompiled " << file_type
- << " file passed as argument. Must be "
- "compiled first into .flat file.");
+ const StringPiece file_type = util::EndsWith(src.path, ".xml") ? "XML" : "PNG";
+ context_->GetDiagnostics()->Error(DiagMessage(src) << "uncompiled " << file_type
+ << " file passed as argument. Must be "
+ "compiled first into .flat file.");
return false;
}
@@ -1348,51 +1254,6 @@
return true;
}
- std::unique_ptr<xml::XmlResource> GenerateSplitManifest(const AppInfo& app_info,
- const SplitConstraints& constraints) {
- std::unique_ptr<xml::XmlResource> doc = util::make_unique<xml::XmlResource>();
-
- std::unique_ptr<xml::Namespace> namespace_android = util::make_unique<xml::Namespace>();
- namespace_android->namespace_uri = xml::kSchemaAndroid;
- namespace_android->namespace_prefix = "android";
-
- std::unique_ptr<xml::Element> manifest_el = util::make_unique<xml::Element>();
- manifest_el->name = "manifest";
- manifest_el->attributes.push_back(xml::Attribute{"", "package", app_info.package});
-
- if (app_info.version_code) {
- manifest_el->attributes.push_back(xml::Attribute{
- xml::kSchemaAndroid, "versionCode", std::to_string(app_info.version_code.value())});
- }
-
- if (app_info.revision_code) {
- manifest_el->attributes.push_back(xml::Attribute{
- xml::kSchemaAndroid, "revisionCode", std::to_string(app_info.revision_code.value())});
- }
-
- std::stringstream split_name;
- if (app_info.split_name) {
- split_name << app_info.split_name.value() << ".";
- }
- split_name << "config." << util::Joiner(constraints.configs, "_");
-
- manifest_el->attributes.push_back(xml::Attribute{"", "split", split_name.str()});
-
- if (app_info.split_name) {
- manifest_el->attributes.push_back(
- xml::Attribute{"", "configForSplit", app_info.split_name.value()});
- }
-
- std::unique_ptr<xml::Element> application_el = util::make_unique<xml::Element>();
- application_el->name = "application";
- application_el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, "hasCode", "false"});
-
- manifest_el->AppendChild(std::move(application_el));
- namespace_android->AppendChild(std::move(manifest_el));
- doc->root = std::move(namespace_android);
- return doc;
- }
-
bool CopyAssetsDirsToApk(IArchiveWriter* writer) {
std::map<std::string, std::unique_ptr<io::RegularFile>> merged_assets;
for (const std::string& assets_dir : options_.assets_dirs) {
@@ -1425,8 +1286,8 @@
compression_flags = 0u;
}
- if (!CopyFileToArchive(entry.second.get(), entry.first, compression_flags, writer,
- context_)) {
+ if (!io::CopyFileToArchive(context_, entry.second.get(), entry.first, compression_flags,
+ writer)) {
return false;
}
}
@@ -1437,21 +1298,19 @@
* Writes the AndroidManifest, ResourceTable, and all XML files referenced by
* the ResourceTable to the IArchiveWriter.
*/
- bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set,
- xml::XmlResource* manifest, ResourceTable* table) {
+ bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set, xml::XmlResource* manifest,
+ ResourceTable* table) {
const bool keep_raw_values = options_.package_type == PackageType::kStaticLib;
- bool result = FlattenXml(manifest, "AndroidManifest.xml", {},
- keep_raw_values, writer, context_);
+ bool result =
+ FlattenXml(manifest, "AndroidManifest.xml", {}, keep_raw_values, writer, context_);
if (!result) {
return false;
}
ResourceFileFlattenerOptions file_flattener_options;
file_flattener_options.keep_raw_values = keep_raw_values;
- file_flattener_options.do_not_compress_anything =
- options_.do_not_compress_anything;
- file_flattener_options.extensions_to_not_compress =
- options_.extensions_to_not_compress;
+ file_flattener_options.do_not_compress_anything = options_.do_not_compress_anything;
+ file_flattener_options.extensions_to_not_compress = options_.extensions_to_not_compress;
file_flattener_options.no_auto_version = options_.no_auto_version;
file_flattener_options.no_version_vectors = options_.no_version_vectors;
file_flattener_options.no_version_transitions = options_.no_version_transitions;
@@ -1487,10 +1346,9 @@
return 1;
}
- // First extract the Package name without modifying it (via
- // --rename-manifest-package).
- if (Maybe<AppInfo> maybe_app_info = ExtractAppInfoFromManifest(
- manifest_xml.get(), context_->GetDiagnostics())) {
+ // First extract the Package name without modifying it (via --rename-manifest-package).
+ if (Maybe<AppInfo> maybe_app_info =
+ ExtractAppInfoFromManifest(manifest_xml.get(), context_->GetDiagnostics())) {
const AppInfo& app_info = maybe_app_info.value();
context_->SetCompilationPackage(app_info.package);
}
@@ -1500,22 +1358,16 @@
return 1;
}
- Maybe<AppInfo> maybe_app_info = ExtractAppInfoFromManifest(
- manifest_xml.get(), context_->GetDiagnostics());
+ Maybe<AppInfo> maybe_app_info =
+ ExtractAppInfoFromManifest(manifest_xml.get(), context_->GetDiagnostics());
if (!maybe_app_info) {
return 1;
}
const AppInfo& app_info = maybe_app_info.value();
- if (app_info.min_sdk_version) {
- if (Maybe<int> maybe_min_sdk_version = ResourceUtils::ParseSdkVersion(
- app_info.min_sdk_version.value())) {
- context_->SetMinSdkVersion(maybe_min_sdk_version.value());
- }
- }
+ context_->SetMinSdkVersion(app_info.min_sdk_version.value_or_default(0));
- context_->SetNameManglerPolicy(
- NameManglerPolicy{context_->GetCompilationPackage()});
+ context_->SetNameManglerPolicy(NameManglerPolicy{context_->GetCompilationPackage()});
// Override the package ID when it is "android".
if (context_->GetCompilationPackage() == "android") {
@@ -1535,8 +1387,7 @@
TableMergerOptions table_merger_options;
table_merger_options.auto_add_overlay = options_.auto_add_overlay;
- table_merger_ = util::make_unique<TableMerger>(context_, &final_table_,
- table_merger_options);
+ table_merger_ = util::make_unique<TableMerger>(context_, &final_table_, table_merger_options);
if (context_->IsVerbose()) {
context_->GetDiagnostics()->Note(DiagMessage()
@@ -1547,16 +1398,14 @@
for (const std::string& input : input_files) {
if (!MergePath(input, false)) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed parsing input");
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed parsing input");
return 1;
}
}
for (const std::string& input : options_.overlay_files) {
if (!MergePath(input, true)) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed parsing overlays");
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed parsing overlays");
return 1;
}
}
@@ -1568,8 +1417,7 @@
if (options_.package_type != PackageType::kStaticLib) {
PrivateAttributeMover mover;
if (!mover.Consume(context_, &final_table_)) {
- context_->GetDiagnostics()->Error(
- DiagMessage() << "failed moving private attributes");
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed moving private attributes");
return 1;
}
@@ -1587,14 +1435,13 @@
for (auto& entry : type->entries) {
ResourceName name(package->name, type->type, entry->name);
// The IDs are guaranteed to exist.
- options_.stable_id_map[std::move(name)] = ResourceId(
- package->id.value(), type->id.value(), entry->id.value());
+ options_.stable_id_map[std::move(name)] =
+ ResourceId(package->id.value(), type->id.value(), entry->id.value());
}
}
}
- if (!WriteStableIdMapToPath(context_->GetDiagnostics(),
- options_.stable_id_map,
+ if (!WriteStableIdMapToPath(context_->GetDiagnostics(), options_.stable_id_map,
options_.resource_id_map_path.value())) {
return 1;
}
@@ -1609,8 +1456,8 @@
}
// Add the names to mangle based on our source merge earlier.
- context_->SetNameManglerPolicy(NameManglerPolicy{
- context_->GetCompilationPackage(), table_merger_->merged_packages()});
+ context_->SetNameManglerPolicy(
+ NameManglerPolicy{context_->GetCompilationPackage(), table_merger_->merged_packages()});
// Add our table to the symbol table.
context_->GetExternalSymbols()->PrependSource(
@@ -1618,8 +1465,7 @@
ReferenceLinker linker;
if (!linker.Consume(context_, &final_table_)) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed linking references");
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed linking references");
return 1;
}
@@ -1639,17 +1485,16 @@
if (!options_.no_auto_version) {
AutoVersioner versioner;
if (!versioner.Consume(context_, &final_table_)) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed versioning styles");
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed versioning styles");
return 1;
}
}
if (options_.package_type != PackageType::kStaticLib && context_->GetMinSdkVersion() > 0) {
if (context_->IsVerbose()) {
- context_->GetDiagnostics()->Note(
- DiagMessage() << "collapsing resource versions for minimum SDK "
- << context_->GetMinSdkVersion());
+ context_->GetDiagnostics()->Note(DiagMessage()
+ << "collapsing resource versions for minimum SDK "
+ << context_->GetMinSdkVersion());
}
VersionCollapser collapser;
@@ -1676,27 +1521,12 @@
<< "can't strip resources when building static library");
}
} else {
- // Adjust the SplitConstraints so that their SDK version is stripped if it
- // is less
- // than or equal to the minSdk. Otherwise the resources that have had
- // their SDK version
- // stripped due to minSdk won't ever match.
- std::vector<SplitConstraints> adjusted_constraints_list;
- adjusted_constraints_list.reserve(options_.split_constraints.size());
- for (const SplitConstraints& constraints : options_.split_constraints) {
- SplitConstraints adjusted_constraints;
- for (const ConfigDescription& config : constraints.configs) {
- if (config.sdkVersion <= context_->GetMinSdkVersion()) {
- adjusted_constraints.configs.insert(config.CopyWithoutSdkVersion());
- } else {
- adjusted_constraints.configs.insert(config);
- }
- }
- adjusted_constraints_list.push_back(std::move(adjusted_constraints));
- }
+ // Adjust the SplitConstraints so that their SDK version is stripped if it is less than or
+ // equal to the minSdk.
+ options_.split_constraints =
+ AdjustSplitConstraintsForMinSdk(context_->GetMinSdkVersion(), options_.split_constraints);
- TableSplitter table_splitter(adjusted_constraints_list,
- options_.table_splitter_options);
+ TableSplitter table_splitter(options_.split_constraints, options_.table_splitter_options);
if (!table_splitter.VerifySplitConstraints(context_)) {
return 1;
}
@@ -1704,21 +1534,18 @@
// Now we need to write out the Split APKs.
auto path_iter = options_.split_paths.begin();
- auto split_constraints_iter = adjusted_constraints_list.begin();
- for (std::unique_ptr<ResourceTable>& split_table :
- table_splitter.splits()) {
+ auto split_constraints_iter = options_.split_constraints.begin();
+ for (std::unique_ptr<ResourceTable>& split_table : table_splitter.splits()) {
if (context_->IsVerbose()) {
- context_->GetDiagnostics()->Note(
- DiagMessage(*path_iter)
- << "generating split with configurations '"
- << util::Joiner(split_constraints_iter->configs, ", ") << "'");
+ context_->GetDiagnostics()->Note(DiagMessage(*path_iter)
+ << "generating split with configurations '"
+ << util::Joiner(split_constraints_iter->configs, ", ")
+ << "'");
}
- std::unique_ptr<IArchiveWriter> archive_writer =
- MakeArchiveWriter(*path_iter);
+ std::unique_ptr<IArchiveWriter> archive_writer = MakeArchiveWriter(*path_iter);
if (!archive_writer) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed to create archive");
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed to create archive");
return 1;
}
@@ -1728,13 +1555,13 @@
XmlReferenceLinker linker;
if (!linker.Consume(context_, split_manifest.get())) {
- context_->GetDiagnostics()->Error(
- DiagMessage() << "failed to create Split AndroidManifest.xml");
+ context_->GetDiagnostics()->Error(DiagMessage()
+ << "failed to create Split AndroidManifest.xml");
return 1;
}
- if (!WriteApk(archive_writer.get(), &proguard_keep_set,
- split_manifest.get(), split_table.get())) {
+ if (!WriteApk(archive_writer.get(), &proguard_keep_set, split_manifest.get(),
+ split_table.get())) {
return 1;
}
@@ -1869,7 +1696,8 @@
std::move(packages_to_callback);
}
- if (!WriteJavaFile(&final_table_, actual_package, output_package, options)) {
+ if (!WriteJavaFile(&final_table_, actual_package, output_package, options,
+ options_.generate_text_symbols_path)) {
return 1;
}
}
@@ -1925,10 +1753,10 @@
std::vector<std::string> split_args;
Flags flags =
Flags()
- .RequiredFlag("-o", "Output path", &options.output_path)
- .RequiredFlag("--manifest", "Path to the Android manifest to build",
+ .RequiredFlag("-o", "Output path.", &options.output_path)
+ .RequiredFlag("--manifest", "Path to the Android manifest to build.",
&options.manifest_path)
- .OptionalFlagList("-I", "Adds an Android APK to link against", &options.include_paths)
+ .OptionalFlagList("-I", "Adds an Android APK to link against.", &options.include_paths)
.OptionalFlagList("-A",
"An assets directory to include in the APK. These are unprocessed.",
&options.assets_dirs)
@@ -1940,24 +1768,23 @@
"Specify the package ID to use for this app. Must be greater or equal to\n"
"0x7f and can't be used with --static-lib or --shared-lib.",
&package_id)
- .OptionalFlag("--java", "Directory in which to generate R.java",
+ .OptionalFlag("--java", "Directory in which to generate R.java.",
&options.generate_java_class_path)
- .OptionalFlag("--proguard", "Output file for generated Proguard rules",
+ .OptionalFlag("--proguard", "Output file for generated Proguard rules.",
&options.generate_proguard_rules_path)
.OptionalFlag("--proguard-main-dex",
- "Output file for generated Proguard rules for the main dex",
+ "Output file for generated Proguard rules for the main dex.",
&options.generate_main_dex_proguard_rules_path)
- .OptionalSwitch("--no-auto-version", "Disables automatic style and layout SDK versioning",
+ .OptionalSwitch("--no-auto-version",
+ "Disables automatic style and layout SDK versioning.",
&options.no_auto_version)
.OptionalSwitch("--no-version-vectors",
- "Disables automatic versioning of vector drawables. "
- "Use this only\n"
- "when building with vector drawable support library",
+ "Disables automatic versioning of vector drawables. Use this only\n"
+ "when building with vector drawable support library.",
&options.no_version_vectors)
.OptionalSwitch("--no-version-transitions",
- "Disables automatic versioning of transition resources. "
- "Use this only\n"
- "when building with transition support library",
+ "Disables automatic versioning of transition resources. Use this only\n"
+ "when building with transition support library.",
&options.no_version_transitions)
.OptionalSwitch("--no-resource-deduping",
"Disables automatic deduping of resources with\n"
@@ -1967,100 +1794,95 @@
"Enables encoding sparse entries using a binary search tree.\n"
"This decreases APK size at the cost of resource retrieval performance.",
&options.table_flattener_options.use_sparse_entries)
- .OptionalSwitch("-x", "Legacy flag that specifies to use the package identifier 0x01",
+ .OptionalSwitch("-x", "Legacy flag that specifies to use the package identifier 0x01.",
&legacy_x_flag)
- .OptionalSwitch("-z", "Require localization of strings marked 'suggested'",
+ .OptionalSwitch("-z", "Require localization of strings marked 'suggested'.",
&require_localization)
.OptionalFlagList("-c",
- "Comma separated list of configurations to include. The default\n"
- "is all configurations",
- &configs)
+ "Comma separated list of configurations to include. The default\n"
+ "is all configurations.",
+ &configs)
.OptionalFlag("--preferred-density",
"Selects the closest matching density and strips out all others.",
&preferred_density)
.OptionalFlag("--product", "Comma separated list of product names to keep", &product_list)
.OptionalSwitch("--output-to-dir",
- "Outputs the APK contents to a directory specified "
- "by -o",
+ "Outputs the APK contents to a directory specified by -o.",
&options.output_to_directory)
.OptionalSwitch("--no-xml-namespaces",
- "Removes XML namespace prefix and URI "
- "information from AndroidManifest.xml\nand XML "
- "binaries in res/*.",
+ "Removes XML namespace prefix and URI information from\n"
+ "AndroidManifest.xml and XML binaries in res/*.",
&options.no_xml_namespaces)
.OptionalFlag("--min-sdk-version",
- "Default minimum SDK version to use for "
- "AndroidManifest.xml",
+ "Default minimum SDK version to use for AndroidManifest.xml.",
&options.manifest_fixer_options.min_sdk_version_default)
.OptionalFlag("--target-sdk-version",
- "Default target SDK version to use for "
- "AndroidManifest.xml",
+ "Default target SDK version to use for AndroidManifest.xml.",
&options.manifest_fixer_options.target_sdk_version_default)
.OptionalFlag("--version-code",
- "Version code (integer) to inject into the "
- "AndroidManifest.xml if none is present",
+ "Version code (integer) to inject into the AndroidManifest.xml if none is\n"
+ "present.",
&options.manifest_fixer_options.version_code_default)
.OptionalFlag("--version-name",
- "Version name to inject into the AndroidManifest.xml "
- "if none is present",
+ "Version name to inject into the AndroidManifest.xml if none is present.",
&options.manifest_fixer_options.version_name_default)
- .OptionalSwitch("--shared-lib", "Generates a shared Android runtime library", &shared_lib)
- .OptionalSwitch("--static-lib", "Generate a static Android library", &static_lib)
+ .OptionalSwitch("--shared-lib", "Generates a shared Android runtime library.",
+ &shared_lib)
+ .OptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib)
.OptionalSwitch("--no-static-lib-packages",
- "Merge all library resources under the app's package",
+ "Merge all library resources under the app's package.",
&options.no_static_lib_packages)
.OptionalSwitch("--non-final-ids",
- "Generates R.java without the final modifier.\n"
- "This is implied when --static-lib is specified.",
+ "Generates R.java without the final modifier. This is implied when\n"
+ "--static-lib is specified.",
&options.generate_non_final_ids)
.OptionalFlag("--stable-ids", "File containing a list of name to ID mapping.",
&stable_id_file_path)
.OptionalFlag("--emit-ids",
- "Emit a file at the given path with a list of name to ID\n"
- "mappings, suitable for use with --stable-ids.",
+ "Emit a file at the given path with a list of name to ID mappings,\n"
+ "suitable for use with --stable-ids.",
&options.resource_id_map_path)
.OptionalFlag("--private-symbols",
- "Package name to use when generating R.java for "
- "private symbols.\n"
- "If not specified, public and private symbols will use "
- "the application's "
- "package name",
+ "Package name to use when generating R.java for private symbols.\n"
+ "If not specified, public and private symbols will use the application's\n"
+ "package name.",
&options.private_symbols)
- .OptionalFlag("--custom-package", "Custom Java package under which to generate R.java",
+ .OptionalFlag("--custom-package", "Custom Java package under which to generate R.java.",
&options.custom_java_package)
.OptionalFlagList("--extra-packages",
- "Generate the same R.java but with different "
- "package names",
+ "Generate the same R.java but with different package names.",
&extra_java_packages)
.OptionalFlagList("--add-javadoc-annotation",
- "Adds a JavaDoc annotation to all "
- "generated Java classes",
+ "Adds a JavaDoc annotation to all generated Java classes.",
&options.javadoc_annotations)
+ .OptionalFlag("--output-text-symbols",
+ "Generates a text file containing the resource symbols of the R class in\n"
+ "the specified folder.",
+ &options.generate_text_symbols_path)
.OptionalSwitch("--auto-add-overlay",
- "Allows the addition of new resources in "
- "overlays without <add-resource> tags",
+ "Allows the addition of new resources in overlays without\n"
+ "<add-resource> tags.",
&options.auto_add_overlay)
- .OptionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml",
+ .OptionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml.",
&options.manifest_fixer_options.rename_manifest_package)
.OptionalFlag("--rename-instrumentation-target-package",
- "Changes the name of the target package for instrumentation. "
- "Most useful "
- "when used\nin conjunction with --rename-manifest-package",
+ "Changes the name of the target package for instrumentation. Most useful\n"
+ "when used in conjunction with --rename-manifest-package.",
&options.manifest_fixer_options.rename_instrumentation_target_package)
- .OptionalFlagList("-0", "File extensions not to compress",
+ .OptionalFlagList("-0", "File extensions not to compress.",
&options.extensions_to_not_compress)
.OptionalFlagList("--split",
- "Split resources matching a set of configs out to a "
- "Split APK.\nSyntax: path/to/output.apk:<config>[,<config>[...]]",
+ "Split resources matching a set of configs out to a Split APK.\n"
+ "Syntax: path/to/output.apk:<config>[,<config>[...]].\n"
+ "On Windows, use a semicolon ';' separator instead.",
&split_args)
- .OptionalSwitch("-v", "Enables verbose logging", &verbose);
+ .OptionalSwitch("-v", "Enables verbose logging.", &verbose);
if (!flags.Parse("aapt2 link", args, &std::cerr)) {
return 1;
}
- // Expand all argument-files passed into the command line. These start with
- // '@'.
+ // Expand all argument-files passed into the command line. These start with '@'.
std::vector<std::string> arg_list;
for (const std::string& arg : flags.GetArgs()) {
if (util::StartsWith(arg, "@")) {
@@ -2150,55 +1972,32 @@
}
}
- AxisConfigFilter filter;
+ std::unique_ptr<IConfigFilter> filter;
if (!configs.empty()) {
- for (const std::string& config_arg : configs) {
- for (const StringPiece& config_str : util::Tokenize(config_arg, ',')) {
- ConfigDescription config;
- LocaleValue lv;
- if (lv.InitFromFilterString(config_str)) {
- lv.WriteTo(&config);
- } else if (!ConfigDescription::Parse(config_str, &config)) {
- context.GetDiagnostics()->Error(DiagMessage() << "invalid config '"
- << config_str
- << "' for -c option");
- return 1;
- }
-
- if (config.density != 0) {
- context.GetDiagnostics()->Warn(DiagMessage() << "ignoring density '"
- << config
- << "' for -c option");
- } else {
- filter.AddConfig(config);
- }
- }
+ filter = ParseConfigFilterParameters(configs, context.GetDiagnostics());
+ if (filter == nullptr) {
+ return 1;
}
- options.table_splitter_options.config_filter = &filter;
+ options.table_splitter_options.config_filter = filter.get();
}
if (preferred_density) {
- ConfigDescription preferred_density_config;
- if (!ConfigDescription::Parse(preferred_density.value(),
- &preferred_density_config)) {
- context.GetDiagnostics()->Error(
- DiagMessage() << "invalid density '" << preferred_density.value()
- << "' for --preferred-density option");
+ Maybe<uint16_t> density =
+ ParseTargetDensityParameter(preferred_density.value(), context.GetDiagnostics());
+ if (!density) {
return 1;
}
+ options.table_splitter_options.preferred_densities.push_back(density.value());
+ }
- // Clear the version that can be automatically added.
- preferred_density_config.sdkVersion = 0;
-
- if (preferred_density_config.diff(ConfigDescription::DefaultConfig()) !=
- ConfigDescription::CONFIG_DENSITY) {
- context.GetDiagnostics()->Error(
- DiagMessage() << "invalid preferred density '"
- << preferred_density.value() << "'. "
- << "Preferred density must only be a density value");
+ // Parse the split parameters.
+ for (const std::string& split_arg : split_args) {
+ options.split_paths.push_back({});
+ options.split_constraints.push_back({});
+ if (!ParseSplitParameter(split_arg, context.GetDiagnostics(), &options.split_paths.back(),
+ &options.split_constraints.back())) {
return 1;
}
- options.table_splitter_options.preferred_densities.push_back(preferred_density_config.density);
}
if (options.package_type != PackageType::kStaticLib && stable_id_file_path) {
@@ -2215,17 +2014,6 @@
".imy", ".xmf", ".mp4", ".m4a", ".m4v", ".3gp", ".3gpp", ".3g2",
".3gpp2", ".amr", ".awb", ".wma", ".wmv", ".webm", ".mkv"});
- // Parse the split parameters.
- for (const std::string& split_arg : split_args) {
- options.split_paths.push_back({});
- options.split_constraints.push_back({});
- if (!ParseSplitParameter(split_arg, context.GetDiagnostics(),
- &options.split_paths.back(),
- &options.split_constraints.back())) {
- return 1;
- }
- }
-
// Turn off auto versioning for static-libs.
if (options.package_type == PackageType::kStaticLib) {
options.no_auto_version = true;
diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp
new file mode 100644
index 0000000..e99ee8a
--- /dev/null
+++ b/tools/aapt2/cmd/Optimize.cpp
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <memory>
+#include <vector>
+
+#include "androidfw/StringPiece.h"
+
+#include "Diagnostics.h"
+#include "Flags.h"
+#include "LoadedApk.h"
+#include "ResourceUtils.h"
+#include "SdkConstants.h"
+#include "ValueVisitor.h"
+#include "cmd/Util.h"
+#include "flatten/TableFlattener.h"
+#include "flatten/XmlFlattener.h"
+#include "io/BigBufferInputStream.h"
+#include "io/Util.h"
+#include "optimize/ResourceDeduper.h"
+#include "optimize/VersionCollapser.h"
+#include "split/TableSplitter.h"
+
+using android::StringPiece;
+
+namespace aapt {
+
+struct OptimizeOptions {
+ // Path to the output APK.
+ std::string output_path;
+
+ // Details of the app extracted from the AndroidManifest.xml
+ AppInfo app_info;
+
+ // Split APK options.
+ TableSplitterOptions table_splitter_options;
+
+ // List of output split paths. These are in the same order as `split_constraints`.
+ std::vector<std::string> split_paths;
+
+ // List of SplitConstraints governing what resources go into each split. Ordered by `split_paths`.
+ std::vector<SplitConstraints> split_constraints;
+
+ TableFlattenerOptions table_flattener_options;
+};
+
+class OptimizeContext : public IAaptContext {
+ public:
+ IDiagnostics* GetDiagnostics() override {
+ return &diagnostics_;
+ }
+
+ NameMangler* GetNameMangler() override {
+ UNIMPLEMENTED(FATAL);
+ return nullptr;
+ }
+
+ const std::string& GetCompilationPackage() override {
+ static std::string empty;
+ return empty;
+ }
+
+ uint8_t GetPackageId() override {
+ return 0;
+ }
+
+ SymbolTable* GetExternalSymbols() override {
+ UNIMPLEMENTED(FATAL);
+ return nullptr;
+ }
+
+ bool IsVerbose() override {
+ return verbose_;
+ }
+
+ void SetVerbose(bool val) {
+ verbose_ = val;
+ }
+
+ void SetMinSdkVersion(int sdk_version) {
+ sdk_version_ = sdk_version;
+ }
+
+ int GetMinSdkVersion() override {
+ return sdk_version_;
+ }
+
+ private:
+ StdErrDiagnostics diagnostics_;
+ bool verbose_ = false;
+ int sdk_version_ = 0;
+};
+
+class OptimizeCommand {
+ public:
+ OptimizeCommand(OptimizeContext* context, const OptimizeOptions& options)
+ : options_(options), context_(context) {
+ }
+
+ int Run(std::unique_ptr<LoadedApk> apk) {
+ if (context_->IsVerbose()) {
+ context_->GetDiagnostics()->Note(DiagMessage() << "Optimizing APK...");
+ }
+
+ VersionCollapser collapser;
+ if (!collapser.Consume(context_, apk->GetResourceTable())) {
+ return 1;
+ }
+
+ ResourceDeduper deduper;
+ if (!deduper.Consume(context_, apk->GetResourceTable())) {
+ context_->GetDiagnostics()->Error(DiagMessage() << "failed deduping resources");
+ return 1;
+ }
+
+ // Adjust the SplitConstraints so that their SDK version is stripped if it is less than or
+ // equal to the minSdk.
+ options_.split_constraints =
+ AdjustSplitConstraintsForMinSdk(context_->GetMinSdkVersion(), options_.split_constraints);
+
+ // Stripping the APK using the TableSplitter. The resource table is modified in place in the
+ // LoadedApk.
+ TableSplitter splitter(options_.split_constraints, options_.table_splitter_options);
+ if (!splitter.VerifySplitConstraints(context_)) {
+ return 1;
+ }
+ splitter.SplitTable(apk->GetResourceTable());
+
+ auto path_iter = options_.split_paths.begin();
+ auto split_constraints_iter = options_.split_constraints.begin();
+ for (std::unique_ptr<ResourceTable>& split_table : splitter.splits()) {
+ if (context_->IsVerbose()) {
+ context_->GetDiagnostics()->Note(
+ DiagMessage(*path_iter) << "generating split with configurations '"
+ << util::Joiner(split_constraints_iter->configs, ", ") << "'");
+ }
+
+ // Generate an AndroidManifest.xml for each split.
+ std::unique_ptr<xml::XmlResource> split_manifest =
+ GenerateSplitManifest(options_.app_info, *split_constraints_iter);
+ std::unique_ptr<IArchiveWriter> split_writer =
+ CreateZipFileArchiveWriter(context_->GetDiagnostics(), *path_iter);
+ if (!split_writer) {
+ return 1;
+ }
+
+ if (!WriteSplitApk(split_table.get(), split_manifest.get(), split_writer.get())) {
+ return 1;
+ }
+
+ ++path_iter;
+ ++split_constraints_iter;
+ }
+
+ std::unique_ptr<IArchiveWriter> writer =
+ CreateZipFileArchiveWriter(context_->GetDiagnostics(), options_.output_path);
+ if (!apk->WriteToArchive(context_, options_.table_flattener_options, writer.get())) {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ private:
+ bool WriteSplitApk(ResourceTable* table, xml::XmlResource* manifest, IArchiveWriter* writer) {
+ BigBuffer manifest_buffer(4096);
+ XmlFlattener xml_flattener(&manifest_buffer, {});
+ if (!xml_flattener.Consume(context_, manifest)) {
+ return false;
+ }
+
+ io::BigBufferInputStream manifest_buffer_in(&manifest_buffer);
+ if (!io::CopyInputStreamToArchive(context_, &manifest_buffer_in, "AndroidManifest.xml",
+ ArchiveEntry::kCompress, writer)) {
+ return false;
+ }
+
+ std::map<std::pair<ConfigDescription, StringPiece>, FileReference*> config_sorted_files;
+ for (auto& pkg : table->packages) {
+ for (auto& type : pkg->types) {
+ // Sort by config and name, so that we get better locality in the zip file.
+ config_sorted_files.clear();
+
+ for (auto& entry : type->entries) {
+ for (auto& config_value : entry->values) {
+ FileReference* file_ref = ValueCast<FileReference>(config_value->value.get());
+ if (file_ref == nullptr) {
+ continue;
+ }
+
+ if (file_ref->file == nullptr) {
+ ResourceNameRef name(pkg->name, type->type, entry->name);
+ context_->GetDiagnostics()->Error(DiagMessage(file_ref->GetSource())
+ << "file for resource " << name << " with config '"
+ << config_value->config << "' not found");
+ return false;
+ }
+
+ const StringPiece entry_name = entry->name;
+ config_sorted_files[std::make_pair(config_value->config, entry_name)] = file_ref;
+ }
+ }
+
+ for (auto& entry : config_sorted_files) {
+ FileReference* file_ref = entry.second;
+ uint32_t compression_flags =
+ file_ref->file->WasCompressed() ? ArchiveEntry::kCompress : 0u;
+ if (!io::CopyFileToArchive(context_, file_ref->file, *file_ref->path, compression_flags,
+ writer)) {
+ return false;
+ }
+ }
+ }
+ }
+
+ BigBuffer table_buffer(4096);
+ TableFlattener table_flattener(options_.table_flattener_options, &table_buffer);
+ if (!table_flattener.Consume(context_, table)) {
+ return false;
+ }
+
+ io::BigBufferInputStream table_buffer_in(&table_buffer);
+ if (!io::CopyInputStreamToArchive(context_, &table_buffer_in, "resources.arsc",
+ ArchiveEntry::kAlign, writer)) {
+ return false;
+ }
+ return true;
+ }
+
+ OptimizeOptions options_;
+ OptimizeContext* context_;
+};
+
+bool ExtractAppDataFromManifest(OptimizeContext* context, LoadedApk* apk,
+ OptimizeOptions* out_options) {
+ io::IFile* manifest_file = apk->GetFileCollection()->FindFile("AndroidManifest.xml");
+ if (manifest_file == nullptr) {
+ context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+ << "missing AndroidManifest.xml");
+ return false;
+ }
+
+ std::unique_ptr<io::IData> data = manifest_file->OpenAsData();
+ if (data == nullptr) {
+ context->GetDiagnostics()->Error(DiagMessage(manifest_file->GetSource())
+ << "failed to open file");
+ return false;
+ }
+
+ std::unique_ptr<xml::XmlResource> manifest = xml::Inflate(
+ data->data(), data->size(), context->GetDiagnostics(), manifest_file->GetSource());
+ if (manifest == nullptr) {
+ context->GetDiagnostics()->Error(DiagMessage() << "failed to read binary AndroidManifest.xml");
+ return false;
+ }
+
+ Maybe<AppInfo> app_info =
+ ExtractAppInfoFromBinaryManifest(manifest.get(), context->GetDiagnostics());
+ if (!app_info) {
+ context->GetDiagnostics()->Error(DiagMessage()
+ << "failed to extract data from AndroidManifest.xml");
+ return false;
+ }
+
+ out_options->app_info = std::move(app_info.value());
+ context->SetMinSdkVersion(out_options->app_info.min_sdk_version.value_or_default(0));
+ return true;
+}
+
+int Optimize(const std::vector<StringPiece>& args) {
+ OptimizeContext context;
+ OptimizeOptions options;
+ Maybe<std::string> target_densities;
+ std::vector<std::string> configs;
+ std::vector<std::string> split_args;
+ bool verbose = false;
+ Flags flags =
+ Flags()
+ .RequiredFlag("-o", "Path to the output APK.", &options.output_path)
+ .OptionalFlag(
+ "--target-densities",
+ "Comma separated list of the screen densities that the APK will be optimized for.\n"
+ "All the resources that would be unused on devices of the given densities will be \n"
+ "removed from the APK.",
+ &target_densities)
+ .OptionalFlagList("-c",
+ "Comma separated list of configurations to include. The default\n"
+ "is all configurations.",
+ &configs)
+ .OptionalFlagList("--split",
+ "Split resources matching a set of configs out to a "
+ "Split APK.\nSyntax: path/to/output.apk;<config>[,<config>[...]].\n"
+ "On Windows, use a semicolon ';' separator instead.",
+ &split_args)
+ .OptionalSwitch("--enable-sparse-encoding",
+ "Enables encoding sparse entries using a binary search tree.\n"
+ "This decreases APK size at the cost of resource retrieval performance.",
+ &options.table_flattener_options.use_sparse_entries)
+ .OptionalSwitch("-v", "Enables verbose logging", &verbose);
+
+ if (!flags.Parse("aapt2 optimize", args, &std::cerr)) {
+ return 1;
+ }
+
+ if (flags.GetArgs().size() != 1u) {
+ std::cerr << "must have one APK as argument.\n\n";
+ flags.Usage("aapt2 optimize", &std::cerr);
+ return 1;
+ }
+
+ std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(&context, flags.GetArgs()[0]);
+ if (!apk) {
+ return 1;
+ }
+
+ context.SetVerbose(verbose);
+
+ if (target_densities) {
+ // Parse the target screen densities.
+ for (const StringPiece& config_str : util::Tokenize(target_densities.value(), ',')) {
+ Maybe<uint16_t> target_density =
+ ParseTargetDensityParameter(config_str, context.GetDiagnostics());
+ if (!target_density) {
+ return 1;
+ }
+ options.table_splitter_options.preferred_densities.push_back(target_density.value());
+ }
+ }
+
+ std::unique_ptr<IConfigFilter> filter;
+ if (!configs.empty()) {
+ filter = ParseConfigFilterParameters(configs, context.GetDiagnostics());
+ if (filter == nullptr) {
+ return 1;
+ }
+ options.table_splitter_options.config_filter = filter.get();
+ }
+
+ // Parse the split parameters.
+ for (const std::string& split_arg : split_args) {
+ options.split_paths.push_back({});
+ options.split_constraints.push_back({});
+ if (!ParseSplitParameter(split_arg, context.GetDiagnostics(), &options.split_paths.back(),
+ &options.split_constraints.back())) {
+ return 1;
+ }
+ }
+
+ if (!ExtractAppDataFromManifest(&context, apk.get(), &options)) {
+ return 1;
+ }
+
+ OptimizeCommand cmd(&context, options);
+ return cmd.Run(std::move(apk));
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/cmd/Util.cpp b/tools/aapt2/cmd/Util.cpp
new file mode 100644
index 0000000..14d4260
--- /dev/null
+++ b/tools/aapt2/cmd/Util.cpp
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "cmd/Util.h"
+
+#include <vector>
+
+#include "android-base/logging.h"
+
+#include "ConfigDescription.h"
+#include "Locale.h"
+#include "ResourceUtils.h"
+#include "ValueVisitor.h"
+#include "split/TableSplitter.h"
+#include "util/Maybe.h"
+#include "util/Util.h"
+
+using android::StringPiece;
+
+namespace aapt {
+
+Maybe<uint16_t> ParseTargetDensityParameter(const StringPiece& arg, IDiagnostics* diag) {
+ ConfigDescription preferred_density_config;
+ if (!ConfigDescription::Parse(arg, &preferred_density_config)) {
+ diag->Error(DiagMessage() << "invalid density '" << arg << "' for --preferred-density option");
+ return {};
+ }
+
+ // Clear the version that can be automatically added.
+ preferred_density_config.sdkVersion = 0;
+
+ if (preferred_density_config.diff(ConfigDescription::DefaultConfig()) !=
+ ConfigDescription::CONFIG_DENSITY) {
+ diag->Error(DiagMessage() << "invalid preferred density '" << arg << "'. "
+ << "Preferred density must only be a density value");
+ return {};
+ }
+ return preferred_density_config.density;
+}
+
+bool ParseSplitParameter(const StringPiece& arg, IDiagnostics* diag, std::string* out_path,
+ SplitConstraints* out_split) {
+ CHECK(diag != nullptr);
+ CHECK(out_path != nullptr);
+ CHECK(out_split != nullptr);
+
+#ifdef _WIN32
+ const char sSeparator = ';';
+#else
+ const char sSeparator = ':';
+#endif
+
+ std::vector<std::string> parts = util::Split(arg, sSeparator);
+ if (parts.size() != 2) {
+ diag->Error(DiagMessage() << "invalid split parameter '" << arg << "'");
+ diag->Note(DiagMessage() << "should be --split path/to/output.apk" << sSeparator
+ << "<config>[,<config>...].");
+ return false;
+ }
+
+ *out_path = parts[0];
+ std::vector<ConfigDescription> configs;
+ for (const StringPiece& config_str : util::Tokenize(parts[1], ',')) {
+ ConfigDescription config;
+ if (!ConfigDescription::Parse(config_str, &config)) {
+ diag->Error(DiagMessage() << "invalid config '" << config_str << "' in split parameter '"
+ << arg << "'");
+ return false;
+ }
+ out_split->configs.insert(config);
+ }
+ return true;
+}
+
+std::unique_ptr<IConfigFilter> ParseConfigFilterParameters(const std::vector<std::string>& args,
+ IDiagnostics* diag) {
+ std::unique_ptr<AxisConfigFilter> filter = util::make_unique<AxisConfigFilter>();
+ for (const std::string& config_arg : args) {
+ for (const StringPiece& config_str : util::Tokenize(config_arg, ',')) {
+ ConfigDescription config;
+ LocaleValue lv;
+ if (lv.InitFromFilterString(config_str)) {
+ lv.WriteTo(&config);
+ } else if (!ConfigDescription::Parse(config_str, &config)) {
+ diag->Error(DiagMessage() << "invalid config '" << config_str << "' for -c option");
+ return {};
+ }
+
+ if (config.density != 0) {
+ diag->Warn(DiagMessage() << "ignoring density '" << config << "' for -c option");
+ } else {
+ filter->AddConfig(config);
+ }
+ }
+ }
+ return std::move(filter);
+}
+
+// Adjust the SplitConstraints so that their SDK version is stripped if it
+// is less than or equal to the minSdk. Otherwise the resources that have had
+// their SDK version stripped due to minSdk won't ever match.
+std::vector<SplitConstraints> AdjustSplitConstraintsForMinSdk(
+ int min_sdk, const std::vector<SplitConstraints>& split_constraints) {
+ std::vector<SplitConstraints> adjusted_constraints;
+ adjusted_constraints.reserve(split_constraints.size());
+ for (const SplitConstraints& constraints : split_constraints) {
+ SplitConstraints constraint;
+ for (const ConfigDescription& config : constraints.configs) {
+ if (config.sdkVersion <= min_sdk) {
+ constraint.configs.insert(config.CopyWithoutSdkVersion());
+ } else {
+ constraint.configs.insert(config);
+ }
+ }
+ adjusted_constraints.push_back(std::move(constraint));
+ }
+ return adjusted_constraints;
+}
+
+static xml::AaptAttribute CreateAttributeWithId(const ResourceId& id) {
+ return xml::AaptAttribute{id, Attribute(true)};
+}
+
+std::unique_ptr<xml::XmlResource> GenerateSplitManifest(const AppInfo& app_info,
+ const SplitConstraints& constraints) {
+ const ResourceId kVersionCode(0x0101021b);
+ const ResourceId kRevisionCode(0x010104d5);
+ const ResourceId kHasCode(0x0101000c);
+
+ std::unique_ptr<xml::XmlResource> doc = util::make_unique<xml::XmlResource>();
+
+ std::unique_ptr<xml::Namespace> namespace_android = util::make_unique<xml::Namespace>();
+ namespace_android->namespace_uri = xml::kSchemaAndroid;
+ namespace_android->namespace_prefix = "android";
+
+ std::unique_ptr<xml::Element> manifest_el = util::make_unique<xml::Element>();
+ manifest_el->name = "manifest";
+ manifest_el->attributes.push_back(xml::Attribute{"", "package", app_info.package});
+
+ if (app_info.version_code) {
+ const uint32_t version_code = app_info.version_code.value();
+ manifest_el->attributes.push_back(xml::Attribute{
+ xml::kSchemaAndroid, "versionCode", std::to_string(version_code),
+ CreateAttributeWithId(kVersionCode),
+ util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_INT_DEC, version_code)});
+ }
+
+ if (app_info.revision_code) {
+ const uint32_t revision_code = app_info.revision_code.value();
+ manifest_el->attributes.push_back(xml::Attribute{
+ xml::kSchemaAndroid, "revisionCode", std::to_string(revision_code),
+ CreateAttributeWithId(kRevisionCode),
+ util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_INT_DEC, revision_code)});
+ }
+
+ std::stringstream split_name;
+ if (app_info.split_name) {
+ split_name << app_info.split_name.value() << ".";
+ }
+ split_name << "config." << util::Joiner(constraints.configs, "_");
+
+ manifest_el->attributes.push_back(xml::Attribute{"", "split", split_name.str()});
+
+ if (app_info.split_name) {
+ manifest_el->attributes.push_back(
+ xml::Attribute{"", "configForSplit", app_info.split_name.value()});
+ }
+
+ std::unique_ptr<xml::Element> application_el = util::make_unique<xml::Element>();
+ application_el->name = "application";
+ application_el->attributes.push_back(
+ xml::Attribute{xml::kSchemaAndroid, "hasCode", "false", CreateAttributeWithId(kHasCode),
+ util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_INT_BOOLEAN, 0u)});
+
+ manifest_el->AppendChild(std::move(application_el));
+ namespace_android->AppendChild(std::move(manifest_el));
+ doc->root = std::move(namespace_android);
+ return doc;
+}
+
+static Maybe<std::string> ExtractCompiledString(xml::Attribute* attr, std::string* out_error) {
+ if (attr->compiled_value != nullptr) {
+ String* compiled_str = ValueCast<String>(attr->compiled_value.get());
+ if (compiled_str != nullptr) {
+ if (!compiled_str->value->empty()) {
+ return *compiled_str->value;
+ } else {
+ *out_error = "compiled value is an empty string";
+ return {};
+ }
+ }
+ *out_error = "compiled value is not a string";
+ return {};
+ }
+
+ // Fallback to the plain text value if there is one.
+ if (!attr->value.empty()) {
+ return attr->value;
+ }
+ *out_error = "value is an empty string";
+ return {};
+}
+
+static Maybe<uint32_t> ExtractCompiledInt(xml::Attribute* attr, std::string* out_error) {
+ if (attr->compiled_value != nullptr) {
+ BinaryPrimitive* compiled_prim = ValueCast<BinaryPrimitive>(attr->compiled_value.get());
+ if (compiled_prim != nullptr) {
+ if (compiled_prim->value.dataType >= android::Res_value::TYPE_FIRST_INT &&
+ compiled_prim->value.dataType <= android::Res_value::TYPE_LAST_INT) {
+ return compiled_prim->value.data;
+ }
+ }
+ *out_error = "compiled value is not an integer";
+ return {};
+ }
+
+ // Fallback to the plain text value if there is one.
+ Maybe<uint32_t> integer = ResourceUtils::ParseInt(attr->value);
+ if (integer) {
+ return integer;
+ }
+ std::stringstream error_msg;
+ error_msg << "'" << attr->value << "' is not a valid integer";
+ *out_error = error_msg.str();
+ return {};
+}
+
+static Maybe<int> ExtractSdkVersion(xml::Attribute* attr, std::string* out_error) {
+ if (attr->compiled_value != nullptr) {
+ BinaryPrimitive* compiled_prim = ValueCast<BinaryPrimitive>(attr->compiled_value.get());
+ if (compiled_prim != nullptr) {
+ if (compiled_prim->value.dataType >= android::Res_value::TYPE_FIRST_INT &&
+ compiled_prim->value.dataType <= android::Res_value::TYPE_LAST_INT) {
+ return compiled_prim->value.data;
+ }
+ *out_error = "compiled value is not an integer or string";
+ return {};
+ }
+
+ String* compiled_str = ValueCast<String>(attr->compiled_value.get());
+ if (compiled_str != nullptr) {
+ Maybe<int> sdk_version = ResourceUtils::ParseSdkVersion(*compiled_str->value);
+ if (sdk_version) {
+ return sdk_version;
+ }
+
+ *out_error = "compiled string value is not a valid SDK version";
+ return {};
+ }
+ *out_error = "compiled value is not an integer or string";
+ return {};
+ }
+
+ // Fallback to the plain text value if there is one.
+ Maybe<int> sdk_version = ResourceUtils::ParseSdkVersion(attr->value);
+ if (sdk_version) {
+ return sdk_version;
+ }
+ std::stringstream error_msg;
+ error_msg << "'" << attr->value << "' is not a valid SDK version";
+ *out_error = error_msg.str();
+ return {};
+}
+
+Maybe<AppInfo> ExtractAppInfoFromBinaryManifest(xml::XmlResource* xml_res, IDiagnostics* diag) {
+ // Make sure the first element is <manifest> with package attribute.
+ xml::Element* manifest_el = xml::FindRootElement(xml_res->root.get());
+ if (manifest_el == nullptr) {
+ return {};
+ }
+
+ AppInfo app_info;
+
+ if (!manifest_el->namespace_uri.empty() || manifest_el->name != "manifest") {
+ diag->Error(DiagMessage(xml_res->file.source) << "root tag must be <manifest>");
+ return {};
+ }
+
+ xml::Attribute* package_attr = manifest_el->FindAttribute({}, "package");
+ if (!package_attr) {
+ diag->Error(DiagMessage(xml_res->file.source) << "<manifest> must have a 'package' attribute");
+ return {};
+ }
+
+ std::string error_msg;
+ Maybe<std::string> maybe_package = ExtractCompiledString(package_attr, &error_msg);
+ if (!maybe_package) {
+ diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number))
+ << "invalid package name: " << error_msg);
+ return {};
+ }
+ app_info.package = maybe_package.value();
+
+ if (xml::Attribute* version_code_attr =
+ manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode")) {
+ Maybe<uint32_t> maybe_code = ExtractCompiledInt(version_code_attr, &error_msg);
+ if (!maybe_code) {
+ diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number))
+ << "invalid android:versionCode: " << error_msg);
+ return {};
+ }
+ app_info.version_code = maybe_code.value();
+ }
+
+ if (xml::Attribute* revision_code_attr =
+ manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode")) {
+ Maybe<uint32_t> maybe_code = ExtractCompiledInt(revision_code_attr, &error_msg);
+ if (!maybe_code) {
+ diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number))
+ << "invalid android:revisionCode: " << error_msg);
+ return {};
+ }
+ app_info.revision_code = maybe_code.value();
+ }
+
+ if (xml::Attribute* split_name_attr = manifest_el->FindAttribute({}, "split")) {
+ Maybe<std::string> maybe_split_name = ExtractCompiledString(split_name_attr, &error_msg);
+ if (!maybe_split_name) {
+ diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number))
+ << "invalid split name: " << error_msg);
+ return {};
+ }
+ app_info.split_name = maybe_split_name.value();
+ }
+
+ if (xml::Element* uses_sdk_el = manifest_el->FindChild({}, "uses-sdk")) {
+ if (xml::Attribute* min_sdk =
+ uses_sdk_el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion")) {
+ Maybe<int> maybe_sdk = ExtractSdkVersion(min_sdk, &error_msg);
+ if (!maybe_sdk) {
+ diag->Error(DiagMessage(xml_res->file.source.WithLine(uses_sdk_el->line_number))
+ << "invalid android:minSdkVersion: " << error_msg);
+ return {};
+ }
+ app_info.min_sdk_version = maybe_sdk.value();
+ }
+ }
+ return app_info;
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/cmd/Util.h b/tools/aapt2/cmd/Util.h
new file mode 100644
index 0000000..fd9b39c
--- /dev/null
+++ b/tools/aapt2/cmd/Util.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_SPLIT_UTIL_H
+#define AAPT_SPLIT_UTIL_H
+
+#include "androidfw/StringPiece.h"
+
+#include "AppInfo.h"
+#include "Diagnostics.h"
+#include "SdkConstants.h"
+#include "filter/ConfigFilter.h"
+#include "split/TableSplitter.h"
+#include "util/Maybe.h"
+#include "xml/XmlDom.h"
+
+namespace aapt {
+
+// Parses a configuration density (ex. hdpi, xxhdpi, 234dpi, anydpi, etc).
+// Returns Nothing and logs a human friendly error message if the string was not legal.
+Maybe<uint16_t> ParseTargetDensityParameter(const android::StringPiece& arg, IDiagnostics* diag);
+
+// Parses a string of the form 'path/to/output.apk:<config>[,<config>...]' and fills in
+// `out_path` with the path and `out_split` with the set of ConfigDescriptions.
+// Returns false and logs a human friendly error message if the string was not legal.
+bool ParseSplitParameter(const android::StringPiece& arg, IDiagnostics* diag, std::string* out_path,
+ SplitConstraints* out_split);
+
+// Parses a set of config filter strings of the form 'en,fr-rFR' and returns an IConfigFilter.
+// Returns nullptr and logs a human friendly error message if the string was not legal.
+std::unique_ptr<IConfigFilter> ParseConfigFilterParameters(const std::vector<std::string>& args,
+ IDiagnostics* diag);
+
+// Adjust the SplitConstraints so that their SDK version is stripped if it
+// is less than or equal to the min_sdk. Otherwise the resources that have had
+// their SDK version stripped due to min_sdk won't ever match.
+std::vector<SplitConstraints> AdjustSplitConstraintsForMinSdk(
+ int min_sdk, const std::vector<SplitConstraints>& split_constraints);
+
+// Generates a split AndroidManifest.xml given the split constraints and app info. The resulting
+// XmlResource does not need to be linked via XmlReferenceLinker.
+// This will never fail/return nullptr.
+std::unique_ptr<xml::XmlResource> GenerateSplitManifest(const AppInfo& app_info,
+ const SplitConstraints& constraints);
+
+// Extracts relevant info from the AndroidManifest.xml.
+Maybe<AppInfo> ExtractAppInfoFromBinaryManifest(xml::XmlResource* xml_res, IDiagnostics* diag);
+
+} // namespace aapt
+
+#endif /* AAPT_SPLIT_UTIL_H */
diff --git a/tools/aapt2/io/Io.cpp b/tools/aapt2/io/Io.cpp
deleted file mode 100644
index f5c5737..0000000
--- a/tools/aapt2/io/Io.cpp
+++ /dev/null
@@ -1,43 +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.
- */
-
-#include "io/Io.h"
-
-#include <cstring>
-
-namespace aapt {
-namespace io {
-
-bool Copy(OutputStream* out, InputStream* in) {
- const void* in_buffer;
- size_t in_len;
- while (in->Next(&in_buffer, &in_len)) {
- void* out_buffer;
- size_t out_len;
- if (!out->Next(&out_buffer, &out_len)) {
- return !out->HadError();
- }
-
- const size_t bytes_to_copy = in_len < out_len ? in_len : out_len;
- memcpy(out_buffer, in_buffer, bytes_to_copy);
- out->BackUp(out_len - bytes_to_copy);
- in->BackUp(in_len - bytes_to_copy);
- }
- return !in->HadError();
-}
-
-} // namespace io
-} // namespace aapt
diff --git a/tools/aapt2/io/Io.h b/tools/aapt2/io/Io.h
index 2a34d4d..a656740 100644
--- a/tools/aapt2/io/Io.h
+++ b/tools/aapt2/io/Io.h
@@ -87,10 +87,6 @@
virtual bool HadError() const = 0;
};
-// Copies the data from in to out. Returns false if there was an error.
-// If there was an error, check the individual streams' HadError/GetError methods.
-bool Copy(OutputStream* out, InputStream* in);
-
} // namespace io
} // namespace aapt
diff --git a/tools/aapt2/io/Util.cpp b/tools/aapt2/io/Util.cpp
new file mode 100644
index 0000000..15114e8
--- /dev/null
+++ b/tools/aapt2/io/Util.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "io/Util.h"
+
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+
+namespace aapt {
+namespace io {
+
+bool CopyInputStreamToArchive(IAaptContext* context, InputStream* in, const std::string& out_path,
+ uint32_t compression_flags, IArchiveWriter* writer) {
+ if (context->IsVerbose()) {
+ context->GetDiagnostics()->Note(DiagMessage() << "writing " << out_path << " to archive");
+ }
+
+ if (!writer->WriteFile(out_path, compression_flags, in)) {
+ context->GetDiagnostics()->Error(DiagMessage() << "failed to write " << out_path
+ << " to archive: " << writer->GetError());
+ return false;
+ }
+ return true;
+}
+
+bool CopyFileToArchive(IAaptContext* context, io::IFile* file, const std::string& out_path,
+ uint32_t compression_flags, IArchiveWriter* writer) {
+ std::unique_ptr<io::IData> data = file->OpenAsData();
+ if (!data) {
+ context->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << "failed to open file");
+ return false;
+ }
+ return CopyInputStreamToArchive(context, data.get(), out_path, compression_flags, writer);
+}
+
+bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::MessageLite* proto_msg,
+ const std::string& out_path, uint32_t compression_flags,
+ IArchiveWriter* writer) {
+ if (context->IsVerbose()) {
+ context->GetDiagnostics()->Note(DiagMessage() << "writing " << out_path << " to archive");
+ }
+
+ if (writer->StartEntry(out_path, compression_flags)) {
+ // Make sure CopyingOutputStreamAdaptor is deleted before we call writer->FinishEntry().
+ {
+ // Wrap our IArchiveWriter with an adaptor that implements the ZeroCopyOutputStream interface.
+ ::google::protobuf::io::CopyingOutputStreamAdaptor adaptor(writer);
+ if (!proto_msg->SerializeToZeroCopyStream(&adaptor)) {
+ context->GetDiagnostics()->Error(DiagMessage() << "failed to write " << out_path
+ << " to archive");
+ return false;
+ }
+ }
+
+ if (writer->FinishEntry()) {
+ return true;
+ }
+ }
+ context->GetDiagnostics()->Error(DiagMessage() << "failed to write " << out_path
+ << " to archive: " << writer->GetError());
+ return false;
+}
+
+bool Copy(OutputStream* out, InputStream* in) {
+ const void* in_buffer;
+ size_t in_len;
+ while (in->Next(&in_buffer, &in_len)) {
+ void* out_buffer;
+ size_t out_len;
+ if (!out->Next(&out_buffer, &out_len)) {
+ return !out->HadError();
+ }
+
+ const size_t bytes_to_copy = in_len < out_len ? in_len : out_len;
+ memcpy(out_buffer, in_buffer, bytes_to_copy);
+ out->BackUp(out_len - bytes_to_copy);
+ in->BackUp(in_len - bytes_to_copy);
+ }
+ return !in->HadError();
+}
+
+} // namespace io
+} // namespace aapt
diff --git a/tools/aapt2/io/Util.h b/tools/aapt2/io/Util.h
new file mode 100644
index 0000000..ec1ddb8
--- /dev/null
+++ b/tools/aapt2/io/Util.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_IO_UTIL_H
+#define AAPT_IO_UTIL_H
+
+#include <string>
+
+#include "google/protobuf/message_lite.h"
+
+#include "flatten/Archive.h"
+#include "io/File.h"
+#include "io/Io.h"
+#include "process/IResourceTableConsumer.h"
+
+namespace aapt {
+namespace io {
+
+bool CopyInputStreamToArchive(IAaptContext* context, InputStream* in, const std::string& out_path,
+ uint32_t compression_flags, IArchiveWriter* writer);
+
+bool CopyFileToArchive(IAaptContext* context, IFile* file, const std::string& out_path,
+ uint32_t compression_flags, IArchiveWriter* writer);
+
+bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::MessageLite* proto_msg,
+ const std::string& out_path, uint32_t compression_flags,
+ IArchiveWriter* writer);
+
+// Copies the data from in to out. Returns false if there was an error.
+// If there was an error, check the individual streams' HadError/GetError methods.
+bool Copy(OutputStream* out, InputStream* in);
+
+} // namespace io
+} // namespace aapt
+
+#endif /* AAPT_IO_UTIL_H */
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 68bdb95..a8226c0 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -22,6 +22,7 @@
#include <sstream>
#include <tuple>
+#include "android-base/errors.h"
#include "android-base/logging.h"
#include "android-base/stringprintf.h"
#include "androidfw/StringPiece.h"
@@ -227,7 +228,8 @@
const Styleable& styleable,
const StringPiece& package_name_to_generate,
ClassDefinition* out_class_def,
- MethodDefinition* out_rewrite_method) {
+ MethodDefinition* out_rewrite_method,
+ std::ostream* out_r_txt) {
const std::string array_field_name = TransformToFieldName(name.entry);
std::unique_ptr<ResourceArrayMember> array_def =
util::make_unique<ResourceArrayMember>(array_field_name);
@@ -328,10 +330,25 @@
array_def->GetCommentBuilder()->AppendComment(styleable_comment.str());
}
+ if (out_r_txt != nullptr) {
+ *out_r_txt << "int[] styleable " << array_field_name << " {";
+ }
+
// Add the ResourceIds to the array member.
- for (const StyleableAttr& styleable_attr : sorted_attributes) {
- const ResourceId id = styleable_attr.attr_ref->id.value_or_default(ResourceId(0));
+ for (size_t i = 0; i < attr_count; i++) {
+ const ResourceId id = sorted_attributes[i].attr_ref->id.value_or_default(ResourceId(0));
array_def->AddElement(id);
+
+ if (out_r_txt != nullptr) {
+ if (i != 0) {
+ *out_r_txt << ",";
+ }
+ *out_r_txt << " " << id;
+ }
+ }
+
+ if (out_r_txt != nullptr) {
+ *out_r_txt << " }\n";
}
// Add the Styleable array to the Styleable class.
@@ -386,6 +403,11 @@
attr_processor->AppendComment(
StringPrintf("@attr name %s:%s", package_name.data(), attr_name.entry.data()));
+ if (out_r_txt != nullptr) {
+ *out_r_txt << StringPrintf("int styleable %s %d\n", sorted_attributes[i].field_name.data(),
+ (int)i);
+ }
+
out_class_def->AddMember(std::move(index_member));
}
@@ -406,7 +428,8 @@
void JavaClassGenerator::ProcessResource(const ResourceNameRef& name, const ResourceId& id,
const ResourceEntry& entry, ClassDefinition* out_class_def,
- MethodDefinition* out_rewrite_method) {
+ MethodDefinition* out_rewrite_method,
+ std::ostream* out_r_txt) {
const std::string field_name = TransformToFieldName(name.entry);
std::unique_ptr<ResourceMember> resource_member =
util::make_unique<ResourceMember>(field_name, id);
@@ -434,6 +457,10 @@
out_class_def->AddMember(std::move(resource_member));
+ if (out_r_txt != nullptr) {
+ *out_r_txt << "int " << name.type << " " << field_name << " " << id << "\n";
+ }
+
if (out_rewrite_method != nullptr) {
const StringPiece& type_str = ToString(name.type);
out_rewrite_method->AppendStatement(StringPrintf("%s.%s = (%s.%s & 0x00ffffff) | (p << 24);",
@@ -470,7 +497,8 @@
const ResourceTablePackage& package,
const ResourceTableType& type,
ClassDefinition* out_type_class_def,
- MethodDefinition* out_rewrite_method_def) {
+ MethodDefinition* out_rewrite_method_def,
+ std::ostream* out_r_txt) {
for (const auto& entry : type.entries) {
const Maybe<std::string> unmangled_name =
UnmangleResource(package.name, package_name_to_generate, *entry);
@@ -505,15 +533,17 @@
static_cast<const Styleable*>(entry->values.front()->value.get());
ProcessStyleable(resource_name, id, *styleable, package_name_to_generate, out_type_class_def,
- out_rewrite_method_def);
+ out_rewrite_method_def, out_r_txt);
} else {
- ProcessResource(resource_name, id, *entry, out_type_class_def, out_rewrite_method_def);
+ ProcessResource(resource_name, id, *entry, out_type_class_def, out_rewrite_method_def,
+ out_r_txt);
}
}
return true;
}
-bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, std::ostream* out) {
+bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, std::ostream* out,
+ std::ostream* out_r_txt) {
return Generate(package_name_to_generate, package_name_to_generate, out);
}
@@ -527,8 +557,8 @@
}
bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate,
- const StringPiece& out_package_name,
- std::ostream* out) {
+ const StringPiece& out_package_name, std::ostream* out,
+ std::ostream* out_r_txt) {
ClassDefinition r_class("R", ClassQualifier::kNone, true);
std::unique_ptr<MethodDefinition> rewrite_method;
@@ -558,7 +588,7 @@
std::unique_ptr<ClassDefinition> class_def = util::make_unique<ClassDefinition>(
ToString(type->type), ClassQualifier::kStatic, force_creation_if_empty);
if (!ProcessType(package_name_to_generate, *package, *type, class_def.get(),
- rewrite_method.get())) {
+ rewrite_method.get(), out_r_txt)) {
return false;
}
@@ -567,7 +597,7 @@
const ResourceTableType* priv_type = package->FindType(ResourceType::kAttrPrivate);
if (priv_type) {
if (!ProcessType(package_name_to_generate, *package, *priv_type, class_def.get(),
- rewrite_method.get())) {
+ rewrite_method.get(), out_r_txt)) {
return false;
}
}
@@ -597,6 +627,16 @@
}
out->flush();
+
+ if (out_r_txt != nullptr) {
+ out_r_txt->flush();
+
+ if (!*out_r_txt) {
+ error_ = android::base::SystemErrorCodeToString(errno);
+ return false;
+ }
+ }
+
return true;
}
diff --git a/tools/aapt2/java/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h
index 4510430..18746ff 100644
--- a/tools/aapt2/java/JavaClassGenerator.h
+++ b/tools/aapt2/java/JavaClassGenerator.h
@@ -59,7 +59,7 @@
std::vector<std::string> javadoc_annotations;
};
-// Generates the R.java file for a resource table.
+// Generates the R.java file for a resource table and optionally an R.txt file.
class JavaClassGenerator {
public:
JavaClassGenerator(IAaptContext* context, ResourceTable* table,
@@ -69,10 +69,12 @@
// All symbols technically belong to a single package, but linked libraries will
// have their names mangled, denoting that they came from a different package.
// We need to generate these symbols in a separate file. Returns true on success.
- bool Generate(const android::StringPiece& package_name_to_generate, std::ostream* out);
+ bool Generate(const android::StringPiece& package_name_to_generate, std::ostream* out,
+ std::ostream* out_r_txt = nullptr);
bool Generate(const android::StringPiece& package_name_to_generate,
- const android::StringPiece& output_package_name, std::ostream* out);
+ const android::StringPiece& output_package_name, std::ostream* out,
+ std::ostream* out_r_txt = nullptr);
const std::string& getError() const;
@@ -88,13 +90,14 @@
bool ProcessType(const android::StringPiece& package_name_to_generate,
const ResourceTablePackage& package, const ResourceTableType& type,
- ClassDefinition* out_type_class_def, MethodDefinition* out_rewrite_method_def);
+ ClassDefinition* out_type_class_def, MethodDefinition* out_rewrite_method_def,
+ std::ostream* out_r_txt);
// Writes a resource to the R.java file, optionally writing out a rewrite rule for its package
// ID if `out_rewrite_method` is not nullptr.
void ProcessResource(const ResourceNameRef& name, const ResourceId& id,
const ResourceEntry& entry, ClassDefinition* out_class_def,
- MethodDefinition* out_rewrite_method);
+ MethodDefinition* out_rewrite_method, std::ostream* out_r_txt);
// Writes a styleable resource to the R.java file, optionally writing out a rewrite rule for
// its package ID if `out_rewrite_method` is not nullptr.
@@ -102,7 +105,8 @@
void ProcessStyleable(const ResourceNameRef& name, const ResourceId& id,
const Styleable& styleable,
const android::StringPiece& package_name_to_generate,
- ClassDefinition* out_class_def, MethodDefinition* out_rewrite_method);
+ ClassDefinition* out_class_def, MethodDefinition* out_rewrite_method,
+ std::ostream* out_r_txt);
IAaptContext* context_;
ResourceTable* table_;
diff --git a/tools/aapt2/jni/aapt2_jni.cpp b/tools/aapt2/jni/aapt2_jni.cpp
index b029b20..ce3d282 100644
--- a/tools/aapt2/jni/aapt2_jni.cpp
+++ b/tools/aapt2/jni/aapt2_jni.cpp
@@ -77,20 +77,20 @@
return pieces;
}
-JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeCompile(
+JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeCompile(
JNIEnv *env, jclass aapt_obj, jobject arguments_obj) {
std::vector<ScopedUtfChars> compile_args_jni =
list_to_utfchars(env, arguments_obj);
std::vector<StringPiece> compile_args = extract_pieces(compile_args_jni);
- aapt::Compile(compile_args);
+ return aapt::Compile(compile_args);
}
-JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink(
+JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink(
JNIEnv *env, jclass aapt_obj, jobject arguments_obj) {
std::vector<ScopedUtfChars> link_args_jni =
list_to_utfchars(env, arguments_obj);
std::vector<StringPiece> link_args = extract_pieces(link_args_jni);
- aapt::Link(link_args);
+ return aapt::Link(link_args);
}
JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_ping(
diff --git a/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h b/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h
index 56c3c18..90150b4 100644
--- a/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h
+++ b/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h
@@ -18,17 +18,17 @@
/*
* Class: com_android_tools_aapt2_Aapt2Jni
* Method: nativeCompile
- * Signature: (Ljava/util/List;)V
+ * Signature: (Ljava/util/List;)I
*/
-JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeCompile
+JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeCompile
(JNIEnv *, jclass, jobject);
/*
* Class: com_android_tools_aapt2_Aapt2Jni
* Method: nativeLink
- * Signature: (Ljava/util/List;)V
+ * Signature: (Ljava/util/List;)I
*/
-JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink
+JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink
(JNIEnv *, jclass, jobject);
#ifdef __cplusplus
diff --git a/tools/aapt2/optimize/Optimize.cpp b/tools/aapt2/optimize/Optimize.cpp
deleted file mode 100644
index 9615962..0000000
--- a/tools/aapt2/optimize/Optimize.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <memory>
-#include <vector>
-
-#include "androidfw/StringPiece.h"
-
-#include "Diagnostics.h"
-#include "Flags.h"
-#include "LoadedApk.h"
-#include "SdkConstants.h"
-#include "flatten/TableFlattener.h"
-#include "optimize/ResourceDeduper.h"
-#include "optimize/VersionCollapser.h"
-#include "split/TableSplitter.h"
-
-using android::StringPiece;
-
-namespace aapt {
-
-struct OptimizeOptions {
- // Path to the output APK.
- std::string output_path;
-
- // List of screen density configurations the APK will be optimized for.
- std::vector<ConfigDescription> target_configs;
-
- TableFlattenerOptions table_flattener_options;
-};
-
-class OptimizeContext : public IAaptContext {
- public:
- IDiagnostics* GetDiagnostics() override { return &diagnostics_; }
-
- NameMangler* GetNameMangler() override {
- abort();
- return nullptr;
- }
-
- const std::string& GetCompilationPackage() override {
- static std::string empty;
- return empty;
- }
-
- uint8_t GetPackageId() override { return 0; }
-
- SymbolTable* GetExternalSymbols() override {
- abort();
- return nullptr;
- }
-
- bool IsVerbose() override { return verbose_; }
-
- void SetVerbose(bool val) { verbose_ = val; }
-
- void SetMinSdkVersion(int sdk_version) { sdk_version_ = sdk_version; }
-
- int GetMinSdkVersion() override { return sdk_version_; }
-
- private:
- StdErrDiagnostics diagnostics_;
- bool verbose_ = false;
- int sdk_version_ = 0;
-};
-
-class OptimizeCommand {
- public:
- OptimizeCommand(OptimizeContext* context, const OptimizeOptions& options)
- : options_(options),
- context_(context) {}
-
- int Run(std::unique_ptr<LoadedApk> apk) {
- if (context_->IsVerbose()) {
- context_->GetDiagnostics()->Note(DiagMessage() << "Optimizing APK...");
- }
-
- VersionCollapser collapser;
- if (!collapser.Consume(context_, apk->GetResourceTable())) {
- return 1;
- }
-
- ResourceDeduper deduper;
- if (!deduper.Consume(context_, apk->GetResourceTable())) {
- context_->GetDiagnostics()->Error(DiagMessage() << "failed deduping resources");
- return 1;
- }
-
- // Stripping the APK using the TableSplitter with no splits and the target
- // densities as the preferred densities. The resource table is modified in
- // place in the LoadedApk.
- TableSplitterOptions splitter_options;
- for (auto& config : options_.target_configs) {
- splitter_options.preferred_densities.push_back(config.density);
- }
- std::vector<SplitConstraints> splits;
- TableSplitter splitter(splits, splitter_options);
- splitter.SplitTable(apk->GetResourceTable());
-
- std::unique_ptr<IArchiveWriter> writer =
- CreateZipFileArchiveWriter(context_->GetDiagnostics(), options_.output_path);
- if (!apk->WriteToArchive(context_, options_.table_flattener_options, writer.get())) {
- return 1;
- }
-
- return 0;
- }
-
- private:
- OptimizeOptions options_;
- OptimizeContext* context_;
-};
-
-int Optimize(const std::vector<StringPiece>& args) {
- OptimizeContext context;
- OptimizeOptions options;
- Maybe<std::string> target_densities;
- bool verbose = false;
- Flags flags =
- Flags()
- .RequiredFlag("-o", "Path to the output APK.", &options.output_path)
- .OptionalFlag(
- "--target-densities",
- "Comma separated list of the screen densities that the APK will "
- "be optimized for. All the resources that would be unused on "
- "devices of the given densities will be removed from the APK.",
- &target_densities)
- .OptionalSwitch("--enable-sparse-encoding",
- "Enables encoding sparse entries using a binary search tree.\n"
- "This decreases APK size at the cost of resource retrieval performance.",
- &options.table_flattener_options.use_sparse_entries)
- .OptionalSwitch("-v", "Enables verbose logging", &verbose);
-
- if (!flags.Parse("aapt2 optimize", args, &std::cerr)) {
- return 1;
- }
-
- if (flags.GetArgs().size() != 1u) {
- std::cerr << "must have one APK as argument.\n\n";
- flags.Usage("aapt2 optimize", &std::cerr);
- return 1;
- }
-
- std::unique_ptr<LoadedApk> apk =
- LoadedApk::LoadApkFromPath(&context, flags.GetArgs()[0]);
- if (!apk) {
- return 1;
- }
-
- if (verbose) {
- context.SetVerbose(verbose);
- }
-
- if (target_densities) {
- // Parse the target screen densities.
- for (const StringPiece& config_str : util::Tokenize(target_densities.value(), ',')) {
- ConfigDescription config;
- if (!ConfigDescription::Parse(config_str, &config) || config.density == 0) {
- context.GetDiagnostics()->Error(
- DiagMessage() << "invalid density '" << config_str
- << "' for --target-densities option");
- return 1;
- }
-
- // Clear the version that can be automatically added.
- config.sdkVersion = 0;
-
- if (config.diff(ConfigDescription::DefaultConfig()) !=
- ConfigDescription::CONFIG_DENSITY) {
- context.GetDiagnostics()->Error(
- DiagMessage() << "invalid density '" << config_str
- << "' for --target-densities option. Must be only a "
- << "density value.");
- return 1;
- }
-
- options.target_configs.push_back(config);
- }
- }
-
- // TODO(adamlesinski): Read manfiest and set the proper minSdkVersion.
- // context.SetMinSdkVersion(SDK_O);
-
- OptimizeCommand cmd(&context, options);
- return cmd.Run(std::move(apk));
-}
-
-} // namespace aapt
diff --git a/tools/aapt2/readme.md b/tools/aapt2/readme.md
index 2e674bd..daf1ebc 100644
--- a/tools/aapt2/readme.md
+++ b/tools/aapt2/readme.md
@@ -1,5 +1,10 @@
# Android Asset Packaging Tool 2.0 (AAPT2) release notes
+## Version 2.13
+### `aapt2 optimize ...`
+- aapt2 optimize can now split a binary APK with the same --split parameters as the link
+ phase.
+
## Version 2.12
### `aapt2 optimize ...`
- aapt2 optimize now understands map (complex) values under the type `id`. It ignores their
diff --git a/tools/aapt2/unflatten/BinaryResourceParser.cpp b/tools/aapt2/unflatten/BinaryResourceParser.cpp
index 35bf618..20a4531 100644
--- a/tools/aapt2/unflatten/BinaryResourceParser.cpp
+++ b/tools/aapt2/unflatten/BinaryResourceParser.cpp
@@ -73,15 +73,16 @@
} // namespace
-BinaryResourceParser::BinaryResourceParser(IAaptContext* context,
- ResourceTable* table,
- const Source& source,
- const void* data, size_t len)
+BinaryResourceParser::BinaryResourceParser(IAaptContext* context, ResourceTable* table,
+ const Source& source, const void* data, size_t len,
+ io::IFileCollection* files)
: context_(context),
table_(table),
source_(source),
data_(data),
- data_len_(len) {}
+ data_len_(len),
+ files_(files) {
+}
bool BinaryResourceParser::Parse() {
ResChunkPullParser parser(data_, data_len_);
@@ -359,16 +360,14 @@
std::unique_ptr<Value> resource_value;
if (entry->flags & ResTable_entry::FLAG_COMPLEX) {
- const ResTable_map_entry* mapEntry =
- static_cast<const ResTable_map_entry*>(entry);
+ const ResTable_map_entry* mapEntry = static_cast<const ResTable_map_entry*>(entry);
// TODO(adamlesinski): Check that the entry count is valid.
resource_value = ParseMapEntry(name, config, mapEntry);
} else {
const Res_value* value =
- (const Res_value*)((const uint8_t*)entry +
- util::DeviceToHost32(entry->size));
- resource_value = ParseValue(name, config, value, entry->flags);
+ (const Res_value*)((const uint8_t*)entry + util::DeviceToHost32(entry->size));
+ resource_value = ParseValue(name, config, *value);
}
if (!resource_value) {
@@ -388,8 +387,7 @@
Symbol symbol;
symbol.state = SymbolState::kPublic;
symbol.source = source_.WithLine(0);
- if (!table_->SetSymbolStateAllowMangled(name, res_id, symbol,
- context_->GetDiagnostics())) {
+ if (!table_->SetSymbolStateAllowMangled(name, res_id, symbol, context_->GetDiagnostics())) {
return false;
}
}
@@ -419,70 +417,25 @@
return true;
}
-std::unique_ptr<Item> BinaryResourceParser::ParseValue(
- const ResourceNameRef& name, const ConfigDescription& config,
- const Res_value* value, uint16_t flags) {
- if (name.type == ResourceType::kId) {
- return util::make_unique<Id>();
- }
-
- const uint32_t data = util::DeviceToHost32(value->data);
-
- if (value->dataType == Res_value::TYPE_STRING) {
- const std::string str = util::GetString(value_pool_, data);
-
- const ResStringPool_span* spans = value_pool_.styleAt(data);
-
- // Check if the string has a valid style associated with it.
- if (spans != nullptr && spans->name.index != ResStringPool_span::END) {
- StyleString style_str = {str};
- while (spans->name.index != ResStringPool_span::END) {
- style_str.spans.push_back(
- Span{util::GetString(value_pool_, spans->name.index),
- spans->firstChar, spans->lastChar});
- spans++;
+std::unique_ptr<Item> BinaryResourceParser::ParseValue(const ResourceNameRef& name,
+ const ConfigDescription& config,
+ const android::Res_value& value) {
+ std::unique_ptr<Item> item = ResourceUtils::ParseBinaryResValue(name.type, config, value_pool_,
+ value, &table_->string_pool);
+ if (files_ != nullptr && item != nullptr) {
+ FileReference* file_ref = ValueCast<FileReference>(item.get());
+ if (file_ref != nullptr) {
+ file_ref->file = files_->FindFile(*file_ref->path);
+ if (file_ref->file == nullptr) {
+ context_->GetDiagnostics()->Error(DiagMessage() << "resource " << name << " for config '"
+ << config << "' is a file reference to '"
+ << *file_ref->path
+ << "' but no such path exists");
+ return {};
}
- return util::make_unique<StyledString>(table_->string_pool.MakeRef(
- style_str,
- StringPool::Context(StringPool::Context::kStylePriority, config)));
- } else {
- if (name.type != ResourceType::kString && util::StartsWith(str, "res/")) {
- // This must be a FileReference.
- return util::make_unique<FileReference>(table_->string_pool.MakeRef(
- str,
- StringPool::Context(StringPool::Context::kHighPriority, config)));
- }
-
- // There are no styles associated with this string, so treat it as
- // a simple string.
- return util::make_unique<String>(
- table_->string_pool.MakeRef(str, StringPool::Context(config)));
}
}
-
- if (value->dataType == Res_value::TYPE_REFERENCE ||
- value->dataType == Res_value::TYPE_ATTRIBUTE ||
- value->dataType == Res_value::TYPE_DYNAMIC_REFERENCE ||
- value->dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE) {
- Reference::Type type = Reference::Type::kResource;
- if (value->dataType == Res_value::TYPE_ATTRIBUTE ||
- value->dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE) {
- type = Reference::Type::kAttribute;
- }
-
- if (data == 0) {
- // A reference of 0, must be the magic @null reference.
- Res_value null_type = {};
- null_type.dataType = Res_value::TYPE_REFERENCE;
- return util::make_unique<BinaryPrimitive>(null_type);
- }
-
- // This is a normal reference.
- return util::make_unique<Reference>(data, type);
- }
-
- // Treat this as a raw binary primitive.
- return util::make_unique<BinaryPrimitive>(*value);
+ return item;
}
std::unique_ptr<Value> BinaryResourceParser::ParseMapEntry(
@@ -528,7 +481,7 @@
Style::Entry style_entry;
style_entry.key = Reference(util::DeviceToHost32(map_entry.name.ident));
- style_entry.value = ParseValue(name, config, &map_entry.value, 0);
+ style_entry.value = ParseValue(name, config, map_entry.value);
if (!style_entry.value) {
return {};
}
@@ -586,7 +539,7 @@
const ResTable_map_entry* map) {
std::unique_ptr<Array> array = util::make_unique<Array>();
for (const ResTable_map& map_entry : map) {
- array->items.push_back(ParseValue(name, config, &map_entry.value, 0));
+ array->items.push_back(ParseValue(name, config, map_entry.value));
}
return array;
}
@@ -596,7 +549,7 @@
const ResTable_map_entry* map) {
std::unique_ptr<Plural> plural = util::make_unique<Plural>();
for (const ResTable_map& map_entry : map) {
- std::unique_ptr<Item> item = ParseValue(name, config, &map_entry.value, 0);
+ std::unique_ptr<Item> item = ParseValue(name, config, map_entry.value);
if (!item) {
return {};
}
diff --git a/tools/aapt2/unflatten/BinaryResourceParser.h b/tools/aapt2/unflatten/BinaryResourceParser.h
index e3dd802..c41ada0 100644
--- a/tools/aapt2/unflatten/BinaryResourceParser.h
+++ b/tools/aapt2/unflatten/BinaryResourceParser.h
@@ -45,8 +45,8 @@
* Creates a parser, which will read `len` bytes from `data`, and
* add any resources parsed to `table`. `source` is for logging purposes.
*/
- BinaryResourceParser(IAaptContext* context, ResourceTable* table,
- const Source& source, const void* data, size_t data_len);
+ BinaryResourceParser(IAaptContext* context, ResourceTable* table, const Source& source,
+ const void* data, size_t data_len, io::IFileCollection* files = nullptr);
/*
* Parses the binary resource table and returns true if successful.
@@ -63,10 +63,8 @@
const android::ResChunk_header* chunk);
bool ParseLibrary(const android::ResChunk_header* chunk);
- std::unique_ptr<Item> ParseValue(const ResourceNameRef& name,
- const ConfigDescription& config,
- const android::Res_value* value,
- uint16_t flags);
+ std::unique_ptr<Item> ParseValue(const ResourceNameRef& name, const ConfigDescription& config,
+ const android::Res_value& value);
std::unique_ptr<Value> ParseMapEntry(const ResourceNameRef& name,
const ConfigDescription& config,
@@ -104,6 +102,9 @@
const void* data_;
const size_t data_len_;
+ // Optional file collection from which to create io::IFile objects.
+ io::IFileCollection* files_;
+
// The standard value string pool for resource values.
android::ResStringPool value_pool_;
diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h
index 7210d21..30b9af6 100644
--- a/tools/aapt2/util/Util.h
+++ b/tools/aapt2/util/Util.h
@@ -99,8 +99,7 @@
const android::StringPiece& class_name);
/**
- * Makes a std::unique_ptr<> with the template parameter inferred by the
- * compiler.
+ * Makes a std::unique_ptr<> with the template parameter inferred by the compiler.
* This will be present in C++14 and can be removed then.
*/
template <typename T, class... Args>
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index d9ea1bc..6055190 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -25,6 +25,7 @@
#include "android-base/logging.h"
+#include "ResourceUtils.h"
#include "XmlPullParser.h"
#include "util/Util.h"
@@ -193,16 +194,14 @@
stack->pending_comment += comment;
}
-std::unique_ptr<XmlResource> Inflate(std::istream* in, IDiagnostics* diag,
- const Source& source) {
+std::unique_ptr<XmlResource> Inflate(std::istream* in, IDiagnostics* diag, const Source& source) {
Stack stack;
XML_Parser parser = XML_ParserCreateNS(nullptr, kXmlNamespaceSep);
XML_SetUserData(parser, &stack);
XML_UseParserAsHandlerArg(parser);
XML_SetElementHandler(parser, StartElementHandler, EndElementHandler);
- XML_SetNamespaceDeclHandler(parser, StartNamespaceHandler,
- EndNamespaceHandler);
+ XML_SetNamespaceDeclHandler(parser, StartNamespaceHandler, EndNamespaceHandler);
XML_SetCharacterDataHandler(parser, CharacterDataHandler);
XML_SetCommentHandler(parser, CommentDataHandler);
@@ -215,8 +214,7 @@
break;
}
- if (XML_Parse(parser, buffer, in->gcount(), in->eof()) ==
- XML_STATUS_ERROR) {
+ if (XML_Parse(parser, buffer, in->gcount(), in->eof()) == XML_STATUS_ERROR) {
stack.root = {};
diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser)))
<< XML_ErrorString(XML_GetErrorCode(parser)));
@@ -226,13 +224,13 @@
XML_ParserFree(parser);
if (stack.root) {
- return util::make_unique<XmlResource>(ResourceFile{{}, {}, source},
+ return util::make_unique<XmlResource>(ResourceFile{{}, {}, source}, StringPool{},
std::move(stack.root));
}
return {};
}
-static void CopyAttributes(Element* el, android::ResXMLParser* parser) {
+static void CopyAttributes(Element* el, android::ResXMLParser* parser, StringPool* out_pool) {
const size_t attr_count = parser->getAttributeCount();
if (attr_count > 0) {
el->attributes.reserve(attr_count);
@@ -253,18 +251,26 @@
if (str16) {
attr.value = util::Utf16ToUtf8(StringPiece16(str16, len));
}
+
+ android::Res_value res_value;
+ if (parser->getAttributeValue(i, &res_value) > 0) {
+ attr.compiled_value = ResourceUtils::ParseBinaryResValue(
+ ResourceType::kAnim, {}, parser->getStrings(), res_value, out_pool);
+ }
+
el->attributes.push_back(std::move(attr));
}
}
}
-std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len,
- IDiagnostics* diag, const Source& source) {
+std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, IDiagnostics* diag,
+ const Source& source) {
// We import the android namespace because on Windows NO_ERROR is a macro, not
// an enum, which
// causes errors when qualifying it with android::
using namespace android;
+ StringPool string_pool;
std::unique_ptr<Node> root;
std::stack<Node*> node_stack;
@@ -307,7 +313,7 @@
node->name = util::Utf16ToUtf8(StringPiece16(str16, len));
}
- CopyAttributes(node.get(), &tree);
+ CopyAttributes(node.get(), &tree, &string_pool);
new_node = std::move(node);
break;
@@ -352,7 +358,7 @@
}
}
}
- return util::make_unique<XmlResource>(ResourceFile{}, std::move(root));
+ return util::make_unique<XmlResource>(ResourceFile{}, std::move(string_pool), std::move(root));
}
std::unique_ptr<Node> Namespace::Clone() {
diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h
index 90cdfb6..6950c30 100644
--- a/tools/aapt2/xml/XmlDom.h
+++ b/tools/aapt2/xml/XmlDom.h
@@ -128,6 +128,12 @@
class XmlResource {
public:
ResourceFile file;
+
+ // StringPool must come before the xml::Node. Destructors are called in reverse order, and
+ // the xml::Node may have StringPool references that need to be destroyed before the StringPool
+ // is destroyed.
+ StringPool string_pool;
+
std::unique_ptr<xml::Node> root;
};
@@ -135,15 +141,14 @@
* Inflates an XML DOM from a text stream, logging errors to the logger.
* Returns the root node on success, or nullptr on failure.
*/
-std::unique_ptr<XmlResource> Inflate(std::istream* in, IDiagnostics* diag,
- const Source& source);
+std::unique_ptr<XmlResource> Inflate(std::istream* in, IDiagnostics* diag, const Source& source);
/**
* Inflates an XML DOM from a binary ResXMLTree, logging errors to the logger.
* Returns the root node on success, or nullptr on failure.
*/
-std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len,
- IDiagnostics* diag, const Source& source);
+std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, IDiagnostics* diag,
+ const Source& source);
Element* FindRootElement(XmlResource* doc);
Element* FindRootElement(Node* node);
diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py
index baee21c..f5b9042 100755
--- a/tools/fonts/fontchain_lint.py
+++ b/tools/fonts/fontchain_lint.py
@@ -126,7 +126,10 @@
# 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'
+ if lookup.LookupType != 4:
+ # Other lookups are used in the emoji font for fallback.
+ # We ignore them for now.
+ continue
for subtable in lookup.SubTable:
ligatures = subtable.ligatures
for first_glyph in ligatures:
@@ -385,7 +388,7 @@
return output_dict
-def parse_standardized_variants(file_path):
+def parse_emoji_variants(file_path):
emoji_set = set()
text_set = set()
with open(file_path) as datafile:
@@ -420,8 +423,8 @@
_chars_by_age = parse_unicode_datafile(
path.join(ucd_path, 'DerivedAge.txt'), reverse=True)
- sequences = parse_standardized_variants(
- path.join(ucd_path, 'StandardizedVariants.txt'))
+ sequences = parse_emoji_variants(
+ path.join(ucd_path, 'emoji-variation-sequences.txt'))
_text_variation_sequences, _emoji_variation_sequences = sequences
_emoji_sequences = parse_unicode_datafile(
path.join(ucd_path, 'emoji-sequences.txt'))
@@ -442,8 +445,7 @@
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('UN'), flag_sequence('WF'), flag_sequence('XK'),
- flag_sequence('YT'),
+ flag_sequence('WF'), flag_sequence('XK'), flag_sequence('YT'),
})
EQUIVALENT_FLAGS = {
@@ -489,6 +491,55 @@
(0x1F468, 0x200D, 0x1F469, 0x200D, 0x1F466): 0x1F46A,
}
+ZWJ = 0x200D
+FEMALE_SIGN = 0x2640
+MALE_SIGN = 0x2642
+
+GENDER_DEFAULTS = [
+ (0x26F9, MALE_SIGN), # PERSON WITH BALL
+ (0x1F3C3, MALE_SIGN), # RUNNER
+ (0x1F3C4, MALE_SIGN), # SURFER
+ (0x1F3CA, MALE_SIGN), # SWIMMER
+ (0x1F3CB, MALE_SIGN), # WEIGHT LIFTER
+ (0x1F3CC, MALE_SIGN), # GOLFER
+ (0x1F46E, MALE_SIGN), # POLICE OFFICER
+ (0x1F46F, FEMALE_SIGN), # WOMAN WITH BUNNY EARS
+ (0x1F471, MALE_SIGN), # PERSON WITH BLOND HAIR
+ (0x1F473, MALE_SIGN), # MAN WITH TURBAN
+ (0x1F477, MALE_SIGN), # CONSTRUCTION WORKER
+ (0x1F481, FEMALE_SIGN), # INFORMATION DESK PERSON
+ (0x1F482, MALE_SIGN), # GUARDSMAN
+ (0x1F486, FEMALE_SIGN), # FACE MASSAGE
+ (0x1F487, FEMALE_SIGN), # HAIRCUT
+ (0x1F575, MALE_SIGN), # SLEUTH OR SPY
+ (0x1F645, FEMALE_SIGN), # FACE WITH NO GOOD GESTURE
+ (0x1F646, FEMALE_SIGN), # FACE WITH OK GESTURE
+ (0x1F647, MALE_SIGN), # PERSON BOWING DEEPLY
+ (0x1F64B, FEMALE_SIGN), # HAPPY PERSON RAISING ONE HAND
+ (0x1F64D, FEMALE_SIGN), # PERSON FROWNING
+ (0x1F64E, FEMALE_SIGN), # PERSON WITH POUTING FACE
+ (0x1F6A3, MALE_SIGN), # ROWBOAT
+ (0x1F6B4, MALE_SIGN), # BICYCLIST
+ (0x1F6B5, MALE_SIGN), # MOUNTAIN BICYCLIST
+ (0x1F6B6, MALE_SIGN), # PEDESTRIAN
+ (0x1F926, FEMALE_SIGN), # FACE PALM
+ (0x1F937, FEMALE_SIGN), # SHRUG
+ (0x1F938, MALE_SIGN), # PERSON DOING CARTWHEEL
+ (0x1F939, MALE_SIGN), # JUGGLING
+ (0x1F93C, MALE_SIGN), # WRESTLERS
+ (0x1F93D, MALE_SIGN), # WATER POLO
+ (0x1F93E, MALE_SIGN), # HANDBALL
+ (0x1F9D6, FEMALE_SIGN), # PERSON IN STEAMY ROOM
+ (0x1F9D7, FEMALE_SIGN), # PERSON CLIMBING
+ (0x1F9D8, FEMALE_SIGN), # PERSON IN LOTUS POSITION
+ (0x1F9D9, FEMALE_SIGN), # MAGE
+ (0x1F9DA, FEMALE_SIGN), # FAIRY
+ (0x1F9DB, FEMALE_SIGN), # VAMPIRE
+ (0x1F9DC, FEMALE_SIGN), # MERPERSON
+ (0x1F9DD, FEMALE_SIGN), # ELF
+ (0x1F9DE, FEMALE_SIGN), # GENIE
+ (0x1F9DF, FEMALE_SIGN), # ZOMBIE
+]
def is_fitzpatrick_modifier(cp):
return 0x1F3FB <= cp <= 0x1F3FF
@@ -514,10 +565,20 @@
adjusted_emoji_zwj_sequences = dict(_emoji_zwj_sequences)
adjusted_emoji_zwj_sequences.update(_emoji_zwj_sequences)
+ # Add empty flag tag sequence that is supported as fallback
+ _emoji_sequences[(0x1F3F4, 0xE007F)] = 'Emoji_Tag_Sequence'
+
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)
+ if _emoji_sequences.get(sequence, None) == 'Emoji_Tag_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.
+ # TODO: test if these are actually needed by Minikin/HarfBuzz.
+ reversed_seq = reverse_emoji(sequence)
+ all_sequences.add(reversed_seq)
+ equivalent_emoji[reversed_seq] = sequence
for sequence in adjusted_emoji_zwj_sequences.keys():
sequence = tuple(ch for ch in sequence if ch != EMOJI_VS)
@@ -529,13 +590,12 @@
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()))
+ # Remove unsupported flags
+ all_sequences.difference_update(UNSUPPORTED_FLAGS)
+
+ # Add all tag characters used in flags
+ sequence_pieces.update(range(0xE0030, 0xE0039 + 1))
+ sequence_pieces.update(range(0xE0061, 0xE007A + 1))
all_emoji = (
_emoji_properties['Emoji'] |
@@ -547,13 +607,17 @@
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 ch, gender in GENDER_DEFAULTS:
+ equivalent_emoji[(ch, ZWJ, gender)] = ch
+ for skin_tone in range(0x1F3FB, 0x1F3FF+1):
+ skin_toned = (ch, skin_tone, ZWJ, gender)
+ if skin_toned in all_emoji:
+ equivalent_emoji[skin_toned] = (ch, skin_tone)
+
for seq in _emoji_variation_sequences:
equivalent_emoji[seq] = seq[0]
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index f87f6c5..29c933a 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -36,20 +36,18 @@
built_ext_dep := $(call java-lib-deps,ext)
built_ext_classes := $(call java-lib-files,ext)
-built_ext_data := $(call intermediates-dir-for, \
- JAVA_LIBRARIES,ext,,COMMON)/javalib.jar
+
built_icudata_dep := $(call java-lib-deps,icu4j-icudata-host-jarjar,HOST)
built_icutzdata_dep := $(call java-lib-deps,icu4j-icutzdata-host-jarjar,HOST)
-built_layoutlib_create_jar := $(call intermediates-dir-for, \
- JAVA_LIBRARIES,layoutlib_create,HOST)/javalib.jar
+built_layoutlib_create_jar := $(call java-lib-files,layoutlib_create,HOST)
# This is mostly a copy of config/host_java_library.mk
LOCAL_MODULE := temp_layoutlib
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_MODULE_SUFFIX := $(COMMON_JAVA_PACKAGE_SUFFIX)
LOCAL_IS_HOST_MODULE := true
-LOCAL_BUILT_MODULE_STEM := javalib.jar
+LOCAL_BUILT_MODULE_STEM := classes.jar
#######################################
include $(BUILD_SYSTEM)/base_rules.mk
@@ -59,7 +57,6 @@
$(built_core_dep) \
$(built_framework_dep) \
$(built_ext_dep) \
- $(built_ext_data) \
$(built_icudata_dep) \
$(built_icutzdata_dep) \
$(built_layoutlib_create_jar)
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index a21fe68..78b6f71 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -45,7 +45,7 @@
import java.util.Scanner;
import java.util.Set;
-import static android.graphics.Typeface.Builder.RESOLVE_BY_FONT_TABLE;
+import static android.graphics.Typeface.RESOLVE_BY_FONT_TABLE;
import static android.graphics.Typeface_Delegate.SYSTEM_FONTS;
/**