diff options
1156 files changed, 17651 insertions, 11037 deletions
diff --git a/Android.mk b/Android.mk index b8b85baa95ee..991d18513be8 100644 --- a/Android.mk +++ b/Android.mk @@ -309,6 +309,7 @@ LOCAL_SRC_FILES += \ 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 \ @@ -569,11 +570,11 @@ LOCAL_JAVA_LIBRARIES := core-oj core-libart conscrypt okhttp bouncycastle ext 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 fada9aad6c05..da601e1519a8 100644 --- a/api/current.txt +++ b/api/current.txt @@ -210,6 +210,8 @@ package android { 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 __removed3 = 16844116; // 0x1010554 field public static final int absListViewStyle = 16842858; // 0x101006a field public static final int accessibilityEventTypes = 16843648; // 0x1010380 field public static final int accessibilityFeedbackType = 16843650; // 0x1010382 @@ -312,7 +314,6 @@ package android { field public static final int autoUrlDetect = 16843404; // 0x101028c field public static final int autoVerify = 16844014; // 0x10104ee field public static final int autofillHints = 16844121; // 0x1010559 - field public static final int autofillMode = 16844116; // 0x1010554 field public static final int background = 16842964; // 0x10100d4 field public static final int backgroundDimAmount = 16842802; // 0x1010032 field public static final int backgroundDimEnabled = 16843295; // 0x101021f @@ -471,6 +472,7 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android.accounts { 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"; @@ -3610,6 +3615,7 @@ package android.app { method public android.net.Uri getReferrer(); method public int getRequestedOrientation(); method public final android.view.SearchEvent getSearchEvent(); + method public long getStartInitiatedTime(); method public int getTaskId(); method public final java.lang.CharSequence getTitle(); method public final int getTitleColor(); @@ -3936,7 +3942,8 @@ package android.app { field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64 field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d field public static final int IMPORTANCE_GONE = 1000; // 0x3e8 - field public static final int IMPORTANCE_PERCEPTIBLE = 130; // 0x82 + field public static final int IMPORTANCE_PERCEPTIBLE = 230; // 0xe6 + field public static final deprecated int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130; // 0x82 field public static final int IMPORTANCE_SERVICE = 300; // 0x12c field public static final int IMPORTANCE_TOP_SLEEPING = 150; // 0x96 field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8 @@ -4695,7 +4702,7 @@ package android.app { 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 +4753,7 @@ package android.app { 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(); @@ -6085,6 +6092,17 @@ package android.app { method public void onDetached(); } + public final class WallpaperColors implements android.os.Parcelable { + ctor public WallpaperColors(android.os.Parcel); + ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>); + ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean); + method public int describeContents(); + method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors(); + method public boolean supportsDarkText(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR; + } + public final class WallpaperInfo implements android.os.Parcelable { ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public int describeContents(); @@ -6107,6 +6125,8 @@ package android.app { } public class WallpaperManager { + method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener); + method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler); method public void clear() throws java.io.IOException; method public void clear(int) throws java.io.IOException; method public void clearWallpaperOffsets(android.os.IBinder); @@ -6121,6 +6141,7 @@ package android.app { method public android.graphics.drawable.Drawable getDrawable(); method public android.graphics.drawable.Drawable getFastDrawable(); method public static android.app.WallpaperManager getInstance(android.content.Context); + method public android.app.WallpaperColors getWallpaperColors(int); method public android.os.ParcelFileDescriptor getWallpaperFile(int); method public int getWallpaperId(int); method public android.app.WallpaperInfo getWallpaperInfo(); @@ -6129,6 +6150,7 @@ package android.app { method public boolean isWallpaperSupported(); method public android.graphics.drawable.Drawable peekDrawable(); method public android.graphics.drawable.Drawable peekFastDrawable(); + method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener); method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle); method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException; method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException; @@ -6153,6 +6175,10 @@ package android.app { field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview"; } + public static abstract interface WallpaperManager.OnColorsChangedListener { + method public abstract void onColorsChanged(android.app.WallpaperColors, int); + } + } package android.app.admin { @@ -6788,6 +6814,7 @@ package android.app.job { 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 +6853,8 @@ package android.app.job { } 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 +6872,7 @@ package android.app.job { 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 +6889,23 @@ package android.app.job { field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE"; } + public abstract class JobServiceEngine { + ctor public JobServiceEngine(android.content.Context); + method public final android.os.IBinder getBinder(); + method public final void jobFinished(android.app.job.JobParameters, boolean); + method public abstract boolean onStartJob(android.app.job.JobParameters); + method public abstract boolean onStopJob(android.app.job.JobParameters); + } + + 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 +7638,11 @@ package android.bluetooth { 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 +8060,6 @@ package android.bluetooth.le { 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 @@ -8051,7 +8097,12 @@ package android.bluetooth.le { method public void flushPendingScanResults(android.bluetooth.le.ScanCallback); method public void startScan(android.bluetooth.le.ScanCallback); method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback); + method public int startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.app.PendingIntent); method public void stopScan(android.bluetooth.le.ScanCallback); + method public void stopScan(android.app.PendingIntent); + field public static final java.lang.String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE"; + field public static final java.lang.String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE"; + field public static final java.lang.String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT"; } public final class PeriodicAdvertisingParameters implements android.os.Parcelable { @@ -8142,9 +8193,6 @@ package android.bluetooth.le { 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 } @@ -8167,9 +8215,7 @@ package android.bluetooth.le { 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 @@ -8231,7 +8277,8 @@ package android.companion { method public android.companion.BluetoothLEDeviceFilter build(); method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern); method public android.companion.BluetoothLEDeviceFilter.Builder setRawDataFilter(byte[], byte[]); - method public android.companion.BluetoothLEDeviceFilter.Builder setRename(java.lang.String, java.lang.String, int, int, boolean); + method public android.companion.BluetoothLEDeviceFilter.Builder setRenameFromBytes(java.lang.String, java.lang.String, int, int, boolean); + method public android.companion.BluetoothLEDeviceFilter.Builder setRenameFromName(java.lang.String, java.lang.String, int, int); method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter); } @@ -8239,6 +8286,8 @@ package android.companion { method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler); method public void disassociate(java.lang.String); method public java.util.List<java.lang.String> getAssociations(); + method public boolean hasNotificationAccess(android.content.ComponentName); + method public void requestNotificationAccess(android.content.ComponentName); field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE"; } @@ -9333,6 +9382,7 @@ package android.content { 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"; @@ -9449,6 +9499,7 @@ package android.content { 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"; @@ -10346,12 +10397,10 @@ package android.content.pm { 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 @@ -10619,6 +10668,7 @@ package android.content.pm { 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"; @@ -10904,9 +10954,6 @@ package android.content.pm { 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(); @@ -10919,7 +10966,6 @@ package android.content.pm { 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(); @@ -10932,11 +10978,9 @@ package android.content.pm { 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); @@ -12525,6 +12569,7 @@ package android.graphics { field public boolean inJustDecodeBounds; field public boolean inMutable; field public deprecated boolean inPreferQualityOverSpeed; + field public android.graphics.ColorSpace inPreferredColorSpace; field public android.graphics.Bitmap.Config inPreferredConfig; field public boolean inPremultiplied; field public deprecated boolean inPurgeable; @@ -13746,7 +13791,7 @@ package android.graphics { } 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); @@ -13768,26 +13813,20 @@ package android.graphics { } 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 @@ -13819,7 +13858,7 @@ package android.graphics.drawable { 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(); @@ -14384,15 +14423,12 @@ package android.graphics.fonts { 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 { @@ -14858,15 +14894,16 @@ package android.hardware { 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 { @@ -14900,7 +14937,6 @@ package android.hardware { 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); @@ -15749,7 +15785,6 @@ package android.hardware.display { 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 @@ -20577,7 +20612,7 @@ package android.location { 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(); @@ -20593,7 +20628,7 @@ package android.location { 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(); @@ -20687,7 +20722,7 @@ package android.location { 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 @@ -21805,24 +21840,19 @@ package android.media { 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 { @@ -21834,6 +21864,13 @@ package android.media { 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 { } @@ -21869,7 +21906,7 @@ package android.media { method public deprecated java.nio.ByteBuffer[] getInputBuffers(); method public final android.media.MediaFormat getInputFormat(); method public android.media.Image getInputImage(int); - method public android.media.MediaMetricsSet getMetrics(); + method public android.os.PersistableBundle getMetrics(); method public final java.lang.String getName(); method public java.nio.ByteBuffer getOutputBuffer(int); method public deprecated java.nio.ByteBuffer[] getOutputBuffers(); @@ -21967,6 +22004,19 @@ package android.media { method public void set(int, int); } + public static final class MediaCodec.MetricsConstants { + field public static final java.lang.String CODEC = "android.media.mediacodec.codec"; + field public static final java.lang.String ENCODER = "android.media.mediacodec.encoder"; + field public static final java.lang.String HEIGHT = "android.media.mediacodec.height"; + field public static final java.lang.String MIME_TYPE = "android.media.mediacodec.mime"; + field public static final java.lang.String MODE = "android.media.mediacodec.mode"; + field public static final java.lang.String MODE_AUDIO = "audio"; + field public static final java.lang.String MODE_VIDEO = "video"; + field public static final java.lang.String ROTATION = "android.media.mediacodec.rotation"; + field public static final java.lang.String SECURE = "android.media.mediacodec.secure"; + field public static final java.lang.String WIDTH = "android.media.mediacodec.width"; + } + public static abstract interface MediaCodec.OnFrameRenderedListener { method public abstract void onFrameRendered(android.media.MediaCodec, long, long); } @@ -22277,12 +22327,12 @@ package android.media { 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 { @@ -22346,7 +22396,7 @@ package android.media { 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 @@ -22420,8 +22470,9 @@ package android.media { 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 android.os.PersistableBundle getMetrics(); method public java.util.Map<java.util.UUID, byte[]> getPsshInfo(); method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo); method public int getSampleFlags(); @@ -22451,6 +22502,17 @@ package android.media { 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 static final class MediaExtractor.MetricsConstants { + field public static final java.lang.String FORMAT = "android.media.mediaextractor.fmt"; + field public static final java.lang.String MIME_TYPE = "android.media.mediaextractor.mime"; + field public static final java.lang.String TRACKS = "android.media.mediaextractor.ntrk"; + } + public final class MediaFormat { ctor public MediaFormat(); method public final boolean containsKey(java.lang.String); @@ -22676,69 +22738,6 @@ package android.media { field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0 } - public final class MediaMetricsSet { - method public double getDouble(java.lang.String, double); - method public int getInt(java.lang.String, int); - method public long getLong(java.lang.String, long); - method public java.lang.String getString(java.lang.String, java.lang.String); - method public boolean isEmpty(); - method public java.util.Set<java.lang.String> keySet(); - method public int size(); - } - - public static final class MediaMetricsSet.MediaCodec { - field public static final java.lang.String KEY_CODEC = "android.media.mediacodec.codec"; - field public static final java.lang.String KEY_ENCODER = "android.media.mediacodec.encoder"; - field public static final java.lang.String KEY_HEIGHT = "android.media.mediacodec.height"; - field public static final java.lang.String KEY_MIME = "android.media.mediacodec.mime"; - field public static final java.lang.String KEY_MODE = "android.media.mediacodec.mode"; - field public static final java.lang.String KEY_ROTATION = "android.media.mediacodec.rotation"; - field public static final java.lang.String KEY_SECURE = "android.media.mediacodec.secure"; - field public static final java.lang.String KEY_WIDTH = "android.media.mediacodec.width"; - field public static final java.lang.String MODE_AUDIO = "audio"; - field public static final java.lang.String MODE_VIDEO = "video"; - } - - public static final class MediaMetricsSet.MediaExtractor { - field public static final java.lang.String KEY_FORMAT = "android.media.mediaextractor.fmt"; - field public static final java.lang.String KEY_MIME = "android.media.mediaextractor.mime"; - field public static final java.lang.String KEY_TRACKS = "android.media.mediaextractor.ntrk"; - } - - public static final class MediaMetricsSet.MediaPlayer { - field public static final java.lang.String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec"; - field public static final java.lang.String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec"; - field public static final java.lang.String KEY_DURATION = "android.media.mediaplayer.durationMs"; - field public static final java.lang.String KEY_ERRORS = "android.media.mediaplayer.err"; - field public static final java.lang.String KEY_ERROR_CODE = "android.media.mediaplayer.errcode"; - field public static final java.lang.String KEY_FRAMES = "android.media.mediaplayer.frames"; - field public static final java.lang.String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped"; - field public static final java.lang.String KEY_HEIGHT = "android.media.mediaplayer.height"; - field public static final java.lang.String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime"; - field public static final java.lang.String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime"; - field public static final java.lang.String KEY_PLAYING = "android.media.mediaplayer.playingMs"; - field public static final java.lang.String KEY_WIDTH = "android.media.mediaplayer.width"; - } - - public static final class MediaMetricsSet.MediaRecorder { - field public static final java.lang.String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate"; - field public static final java.lang.String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels"; - field public static final java.lang.String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate"; - field public static final java.lang.String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale"; - field public static final java.lang.String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps"; - field public static final java.lang.String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable"; - field public static final java.lang.String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate"; - field public static final java.lang.String KEY_HEIGHT = "android.media.mediarecorder.height"; - field public static final java.lang.String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale"; - field public static final java.lang.String KEY_ROTATION = "android.media.mediarecorder.rotation"; - field public static final java.lang.String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate"; - field public static final java.lang.String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval"; - field public static final java.lang.String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level"; - field public static final java.lang.String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile"; - field public static final java.lang.String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale"; - field public static final java.lang.String KEY_WIDTH = "android.media.mediarecorder.width"; - } - public final class MediaMuxer { ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException; ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException; @@ -22777,7 +22776,7 @@ package android.media { method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException; method public int getDuration(); method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException; - method public android.media.MediaMetricsSet getMetrics(); + method public android.os.PersistableBundle getMetrics(); method public android.media.PlaybackParams getPlaybackParams(); method public int getSelectedTrack(int) throws java.lang.IllegalStateException; method public android.media.SyncParams getSyncParams(); @@ -22872,6 +22871,21 @@ package android.media { method public java.util.UUID[] getSupportedSchemes(); } + public static final class MediaPlayer.MetricsConstants { + field public static final java.lang.String CODEC_AUDIO = "android.media.mediaplayer.audio.codec"; + field public static final java.lang.String CODEC_VIDEO = "android.media.mediaplayer.video.codec"; + field public static final java.lang.String DURATION = "android.media.mediaplayer.durationMs"; + field public static final java.lang.String ERRORS = "android.media.mediaplayer.err"; + field public static final java.lang.String ERROR_CODE = "android.media.mediaplayer.errcode"; + field public static final java.lang.String FRAMES = "android.media.mediaplayer.frames"; + field public static final java.lang.String FRAMES_DROPPED = "android.media.mediaplayer.dropped"; + field public static final java.lang.String HEIGHT = "android.media.mediaplayer.height"; + field public static final java.lang.String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime"; + field public static final java.lang.String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime"; + field public static final java.lang.String PLAYING = "android.media.mediaplayer.playingMs"; + field public static final java.lang.String WIDTH = "android.media.mediaplayer.width"; + } + public static final class MediaPlayer.NoDrmSchemeException extends android.media.MediaDrmException { ctor public MediaPlayer.NoDrmSchemeException(java.lang.String); } @@ -22946,7 +22960,7 @@ package android.media { ctor public MediaRecorder(); method public static final int getAudioSourceMax(); method public int getMaxAmplitude() throws java.lang.IllegalStateException; - method public android.media.MediaMetricsSet getMetrics(); + method public android.os.PersistableBundle getMetrics(); method public android.view.Surface getSurface(); method public void pause() throws java.lang.IllegalStateException; method public void prepare() throws java.io.IOException, java.lang.IllegalStateException; @@ -22965,11 +22979,12 @@ package android.media { method public void setMaxDuration(int) throws java.lang.IllegalArgumentException; method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException; method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalStateException; - method public void setNextOutputFile(java.lang.String) throws java.io.IOException, java.lang.IllegalStateException; + method public void setNextOutputFile(java.io.File) throws java.io.IOException, java.lang.IllegalStateException; method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener); method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener); method public void setOrientationHint(int); method public void setOutputFile(java.io.FileDescriptor) throws java.lang.IllegalStateException; + method public void setOutputFile(java.io.File); method public void setOutputFile(java.lang.String) throws java.lang.IllegalStateException; method public void setOutputFormat(int) throws java.lang.IllegalStateException; method public void setPreviewDisplay(android.view.Surface); @@ -23014,6 +23029,25 @@ package android.media { field public static final int VOICE_UPLINK = 2; // 0x2 } + public static final class MediaRecorder.MetricsConstants { + field public static final java.lang.String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate"; + field public static final java.lang.String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels"; + field public static final java.lang.String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate"; + field public static final java.lang.String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale"; + field public static final java.lang.String CAPTURE_FPS = "android.media.mediarecorder.capture-fps"; + field public static final java.lang.String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable"; + field public static final java.lang.String FRAMERATE = "android.media.mediarecorder.frame-rate"; + field public static final java.lang.String HEIGHT = "android.media.mediarecorder.height"; + field public static final java.lang.String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale"; + field public static final java.lang.String ROTATION = "android.media.mediarecorder.rotation"; + field public static final java.lang.String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate"; + field public static final java.lang.String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval"; + field public static final java.lang.String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level"; + field public static final java.lang.String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile"; + field public static final java.lang.String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale"; + field public static final java.lang.String WIDTH = "android.media.mediarecorder.width"; + } + public static abstract interface MediaRecorder.OnErrorListener { method public abstract void onError(android.media.MediaRecorder, int, int); } @@ -23619,7 +23653,7 @@ package android.media { 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(); @@ -23645,7 +23679,7 @@ package android.media { 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); } @@ -24507,14 +24541,14 @@ package android.media.tv { 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"; } @@ -24607,9 +24641,10 @@ package android.media.tv { 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 @@ -24704,6 +24739,8 @@ package android.media.tv { 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"; @@ -24718,6 +24755,9 @@ package android.media.tv { 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 { @@ -24764,6 +24804,8 @@ package android.media.tv { 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"; @@ -24777,14 +24819,18 @@ package android.media.tv { 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 @@ -25503,22 +25549,25 @@ package android.net { 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 } @@ -25758,6 +25807,10 @@ package android.net { method public android.net.NetworkRequest.Builder removeCapability(int); method public android.net.NetworkRequest.Builder removeTransportType(int); method public android.net.NetworkRequest.Builder setNetworkSpecifier(java.lang.String); + method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier); + } + + public abstract class NetworkSpecifier { } public class ParseException extends java.lang.RuntimeException { @@ -31903,7 +31956,7 @@ package android.os.health { 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 @@ -34478,10 +34531,15 @@ package android.provider { } 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 @@ -34493,6 +34551,35 @@ package android.provider { 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"; @@ -34877,8 +34964,8 @@ package android.provider { 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"; @@ -36977,8 +37064,10 @@ package android.service.autofill { method public final android.os.IBinder onBind(android.content.Intent); method public void onConnected(); method public void onDisconnected(); - method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback); - method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback); + method public void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback); + method public abstract deprecated void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback); + method public void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback); + method public abstract deprecated void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback); field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService"; field public static final java.lang.String SERVICE_META_DATA = "android.autofill"; } @@ -37003,6 +37092,25 @@ package android.service.autofill { method public void onSuccess(android.service.autofill.FillResponse); } + public final class FillContext implements android.os.Parcelable { + method public int describeContents(); + method public int getRequestId(); + method public android.app.assist.AssistStructure getStructure(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR; + } + + public final class FillRequest implements android.os.Parcelable { + method public int describeContents(); + method public android.os.Bundle getClientState(); + method public int getFlags(); + method public int getId(); + method public android.app.assist.AssistStructure getStructure(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR; + field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1 + } + public final class FillResponse implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); @@ -37014,7 +37122,8 @@ package android.service.autofill { method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset); method public android.service.autofill.FillResponse build(); method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews); - method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle); + method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle); + method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle); method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo); } @@ -37043,6 +37152,14 @@ package android.service.autofill { method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]); } + public final class SaveRequest implements android.os.Parcelable { + method public int describeContents(); + method public android.os.Bundle getClientState(); + method public java.util.List<android.service.autofill.FillContext> getFillContexts(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR; + } + } package android.service.carrier { @@ -37162,7 +37279,7 @@ package android.service.dreams { 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(); @@ -37304,12 +37421,16 @@ package android.service.notification { 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); @@ -37322,6 +37443,7 @@ package android.service.notification { 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 @@ -37330,6 +37452,9 @@ package android.service.notification { 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 @@ -37668,10 +37793,12 @@ package android.service.wallpaper { method public int getDesiredMinimumHeight(); method public int getDesiredMinimumWidth(); method public android.view.SurfaceHolder getSurfaceHolder(); + method public void invalidateColors(); method public boolean isPreview(); method public boolean isVisible(); method public void onApplyWindowInsets(android.view.WindowInsets); method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean); + method public android.app.WallpaperColors onComputeWallpaperColors(); method public void onCreate(android.view.SurfaceHolder); method public void onDesiredSizeChanged(int, int); method public void onDestroy(); @@ -39346,6 +39473,8 @@ package android.telecom { field public static final java.lang.String ACTION_CONFIGURE_PHONE_ACCOUNT = "android.telecom.action.CONFIGURE_PHONE_ACCOUNT"; field public static final java.lang.String ACTION_DEFAULT_DIALER_CHANGED = "android.telecom.action.DEFAULT_DIALER_CHANGED"; field public static final deprecated java.lang.String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL"; + field public static final java.lang.String ACTION_PHONE_ACCOUNT_REGISTERED = "android.telecom.action.PHONE_ACCOUNT_REGISTERED"; + field public static final java.lang.String ACTION_PHONE_ACCOUNT_UNREGISTERED = "android.telecom.action.PHONE_ACCOUNT_UNREGISTERED"; field public static final java.lang.String ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS = "android.telecom.action.SHOW_CALL_ACCESSIBILITY_SETTINGS"; field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS"; field public static final java.lang.String ACTION_SHOW_MISSED_CALLS_NOTIFICATION = "android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION"; @@ -40097,7 +40226,8 @@ package android.telephony { 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(); @@ -42608,7 +42738,7 @@ package android.text.util { 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; @@ -43821,7 +43951,6 @@ package android.view { 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 @@ -45302,7 +45431,6 @@ package android.view { method public android.view.animation.Animation getAnimation(); method public android.os.IBinder getApplicationWindowToken(); method public java.lang.String[] getAutofillHints(); - method public int getAutofillMode(); method public int getAutofillType(); method public android.view.autofill.AutofillValue getAutofillValue(); method public android.graphics.drawable.Drawable getBackground(); @@ -45319,6 +45447,7 @@ package android.view { 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(); @@ -45390,7 +45519,6 @@ package android.view { method public float getPivotX(); method public float getPivotY(); method public android.view.PointerIcon getPointerIcon(); - method public int getResolvedAutofillMode(); method public android.content.res.Resources getResources(); method public final boolean getRevealOnFocusHint(); method public final int getRight(); @@ -45623,7 +45751,6 @@ package android.view { method public void setAlpha(float); method public void setAnimation(android.view.animation.Animation); method public void setAutofillHints(java.lang.String...); - method public void setAutofillMode(int); method public void setBackground(android.graphics.drawable.Drawable); method public void setBackgroundColor(int); method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable); @@ -45637,6 +45764,7 @@ package android.view { 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); @@ -45778,9 +45906,6 @@ package android.view { field public static final java.lang.String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress"; field public static final java.lang.String AUTOFILL_HINT_POSTAL_CODE = "postalCode"; field public static final java.lang.String AUTOFILL_HINT_USERNAME = "username"; - field public static final int AUTOFILL_MODE_AUTO = 1; // 0x1 - field public static final int AUTOFILL_MODE_INHERIT = 0; // 0x0 - field public static final int AUTOFILL_MODE_MANUAL = 2; // 0x2 field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4 field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3 field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0 @@ -46348,7 +46473,6 @@ package android.view { method public abstract int getLayoutDirection(); method public abstract android.view.ViewParent getParent(); method public abstract android.view.ViewParent getParentForAccessibility(); - method public default int getResolvedAutofillMode(); method public abstract int getTextAlignment(); method public abstract int getTextDirection(); method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect); @@ -47735,7 +47859,7 @@ package android.view.autofill { field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE"; field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT"; field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS"; - field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1 + field public static final deprecated int FLAG_MANUAL_REQUEST = 1; // 0x1 } public static abstract class AutofillManager.AutofillCallback { @@ -48878,7 +49002,7 @@ package android.webkit { 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 d20c08cf7a8f..1e8370e97dc5 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -5,10 +5,6 @@ package android.app { method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent); } - public static class Notification.Builder { - method public deprecated android.app.Notification.Builder chooseBadgeIcon(int); - } - public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable { method public deprecated void showAsNotification(android.content.Context); } @@ -100,6 +96,18 @@ package android.graphics { } +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 23dc949a961d..21fce319ebe9 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -142,12 +142,14 @@ package android { 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 @@ package android { 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,8 @@ package android { 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 __removed3 = 16844116; // 0x1010554 field public static final int absListViewStyle = 16842858; // 0x101006a field public static final int accessibilityEventTypes = 16843648; // 0x1010380 field public static final int accessibilityFeedbackType = 16843650; // 0x1010382 @@ -427,7 +432,6 @@ package android { field public static final int autoUrlDetect = 16843404; // 0x101028c field public static final int autoVerify = 16844014; // 0x10104ee field public static final int autofillHints = 16844121; // 0x1010559 - field public static final int autofillMode = 16844116; // 0x1010554 field public static final int background = 16842964; // 0x10100d4 field public static final int backgroundDimAmount = 16842802; // 0x1010032 field public static final int backgroundDimEnabled = 16843295; // 0x101021f @@ -586,6 +590,7 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android.accounts { 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"; @@ -3735,6 +3743,7 @@ package android.app { method public android.net.Uri getReferrer(); method public int getRequestedOrientation(); method public final android.view.SearchEvent getSearchEvent(); + method public long getStartInitiatedTime(); method public int getTaskId(); method public final java.lang.CharSequence getTitle(); method public final int getTitleColor(); @@ -3980,6 +3989,7 @@ package android.app { 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(); @@ -4078,7 +4088,8 @@ package android.app { field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64 field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d field public static final int IMPORTANCE_GONE = 1000; // 0x3e8 - field public static final int IMPORTANCE_PERCEPTIBLE = 130; // 0x82 + field public static final int IMPORTANCE_PERCEPTIBLE = 230; // 0xe6 + field public static final deprecated int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130; // 0x82 field public static final int IMPORTANCE_SERVICE = 300; // 0x12c field public static final int IMPORTANCE_TOP_SLEEPING = 150; // 0x96 field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8 @@ -4856,7 +4867,7 @@ package android.app { 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 +4918,7 @@ package android.app { 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(); @@ -6285,6 +6296,17 @@ package android.app { method public void setPersistentVrModeEnabled(boolean); } + public final class WallpaperColors implements android.os.Parcelable { + ctor public WallpaperColors(android.os.Parcel); + ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>); + ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean); + method public int describeContents(); + method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors(); + method public boolean supportsDarkText(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR; + } + public final class WallpaperInfo implements android.os.Parcelable { ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public int describeContents(); @@ -6307,6 +6329,8 @@ package android.app { } public class WallpaperManager { + method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener); + method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler); method public void clear() throws java.io.IOException; method public void clear(int) throws java.io.IOException; method public void clearWallpaper(); @@ -6323,6 +6347,7 @@ package android.app { method public android.graphics.drawable.Drawable getDrawable(); method public android.graphics.drawable.Drawable getFastDrawable(); method public static android.app.WallpaperManager getInstance(android.content.Context); + method public android.app.WallpaperColors getWallpaperColors(int); method public android.os.ParcelFileDescriptor getWallpaperFile(int); method public int getWallpaperId(int); method public android.app.WallpaperInfo getWallpaperInfo(); @@ -6331,6 +6356,7 @@ package android.app { method public boolean isWallpaperSupported(); method public android.graphics.drawable.Drawable peekDrawable(); method public android.graphics.drawable.Drawable peekFastDrawable(); + method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener); method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle); method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException; method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException; @@ -6358,6 +6384,10 @@ package android.app { field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview"; } + public static abstract interface WallpaperManager.OnColorsChangedListener { + method public abstract void onColorsChanged(android.app.WallpaperColors, int); + } + } package android.app.admin { @@ -7217,6 +7247,7 @@ package android.app.job { 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 +7286,8 @@ package android.app.job { } 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 +7305,7 @@ package android.app.job { 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 +7323,23 @@ package android.app.job { field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE"; } + public abstract class JobServiceEngine { + ctor public JobServiceEngine(android.content.Context); + method public final android.os.IBinder getBinder(); + method public final void jobFinished(android.app.job.JobParameters, boolean); + method public abstract boolean onStartJob(android.app.job.JobParameters); + method public abstract boolean onStopJob(android.app.job.JobParameters); + } + + 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 +8110,11 @@ package android.bluetooth { 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 +8532,6 @@ package android.bluetooth.le { 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 @@ -8519,10 +8569,15 @@ package android.bluetooth.le { method public void flushPendingScanResults(android.bluetooth.le.ScanCallback); method public void startScan(android.bluetooth.le.ScanCallback); method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback); + method public int startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.app.PendingIntent); method public void startScanFromSource(android.os.WorkSource, android.bluetooth.le.ScanCallback); method public void startScanFromSource(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.os.WorkSource, android.bluetooth.le.ScanCallback); method public void startTruncatedScan(java.util.List<android.bluetooth.le.TruncatedFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback); method public void stopScan(android.bluetooth.le.ScanCallback); + method public void stopScan(android.app.PendingIntent); + field public static final java.lang.String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE"; + field public static final java.lang.String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE"; + field public static final java.lang.String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT"; } public final class PeriodicAdvertisingParameters implements android.os.Parcelable { @@ -8623,9 +8678,6 @@ package android.bluetooth.le { 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 } @@ -8648,9 +8700,7 @@ package android.bluetooth.le { 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 @@ -8721,7 +8771,8 @@ package android.companion { method public android.companion.BluetoothLEDeviceFilter build(); method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern); method public android.companion.BluetoothLEDeviceFilter.Builder setRawDataFilter(byte[], byte[]); - method public android.companion.BluetoothLEDeviceFilter.Builder setRename(java.lang.String, java.lang.String, int, int, boolean); + method public android.companion.BluetoothLEDeviceFilter.Builder setRenameFromBytes(java.lang.String, java.lang.String, int, int, boolean); + method public android.companion.BluetoothLEDeviceFilter.Builder setRenameFromName(java.lang.String, java.lang.String, int, int); method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter); } @@ -8729,6 +8780,8 @@ package android.companion { method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler); method public void disassociate(java.lang.String); method public java.util.List<java.lang.String> getAssociations(); + method public boolean hasNotificationAccess(android.content.ComponentName); + method public void requestNotificationAccess(android.content.ComponentName); field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE"; } @@ -9418,6 +9471,7 @@ package android.content { 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"; @@ -9795,6 +9849,7 @@ package android.content { 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"; @@ -9833,6 +9888,7 @@ package android.content { 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"; @@ -9856,6 +9912,7 @@ package android.content { 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"; @@ -9902,6 +9959,7 @@ package android.content { 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"; @@ -9993,6 +10051,7 @@ package android.content { 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"; @@ -11001,12 +11060,10 @@ package android.content.pm { 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 @@ -11217,6 +11274,7 @@ package android.content.pm { method public abstract byte[] getInstantAppCookie(); method public abstract int getInstantAppCookieMaxSize(); method public abstract android.graphics.drawable.Drawable getInstantAppIcon(java.lang.String); + method public abstract android.content.ComponentName getInstantAppInstallerComponent(); method public abstract android.content.ComponentName getInstantAppResolverSettingsComponent(); method public abstract java.util.List<android.content.pm.InstantAppInfo> getInstantApps(); method public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException; @@ -11303,6 +11361,7 @@ package android.content.pm { 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"; @@ -11653,9 +11712,6 @@ package android.content.pm { 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(); @@ -11668,7 +11724,6 @@ package android.content.pm { 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(); @@ -11681,11 +11736,9 @@ package android.content.pm { 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); @@ -13288,6 +13341,7 @@ package android.graphics { field public boolean inJustDecodeBounds; field public boolean inMutable; field public deprecated boolean inPreferQualityOverSpeed; + field public android.graphics.ColorSpace inPreferredColorSpace; field public android.graphics.Bitmap.Config inPreferredConfig; field public boolean inPremultiplied; field public deprecated boolean inPurgeable; @@ -14509,7 +14563,7 @@ package android.graphics { } 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); @@ -14531,26 +14585,20 @@ package android.graphics { } 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 @@ -14582,7 +14630,7 @@ package android.graphics.drawable { 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(); @@ -15147,15 +15195,12 @@ package android.graphics.fonts { 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 { @@ -15627,15 +15672,16 @@ package android.hardware { 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 { @@ -15669,7 +15715,6 @@ package android.hardware { 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); @@ -16531,7 +16576,6 @@ package android.hardware.display { 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 @@ -22073,7 +22117,7 @@ package android.location { 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(); @@ -22089,7 +22133,7 @@ package android.location { 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(); @@ -22183,7 +22227,7 @@ package android.location { 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 @@ -23630,24 +23674,19 @@ package android.media { 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 { @@ -23659,6 +23698,13 @@ package android.media { 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 { } @@ -23694,7 +23740,7 @@ package android.media { method public deprecated java.nio.ByteBuffer[] getInputBuffers(); method public final android.media.MediaFormat getInputFormat(); method public android.media.Image getInputImage(int); - method public android.media.MediaMetricsSet getMetrics(); + method public android.os.PersistableBundle getMetrics(); method public final java.lang.String getName(); method public java.nio.ByteBuffer getOutputBuffer(int); method public deprecated java.nio.ByteBuffer[] getOutputBuffers(); @@ -23792,6 +23838,19 @@ package android.media { method public void set(int, int); } + public static final class MediaCodec.MetricsConstants { + field public static final java.lang.String CODEC = "android.media.mediacodec.codec"; + field public static final java.lang.String ENCODER = "android.media.mediacodec.encoder"; + field public static final java.lang.String HEIGHT = "android.media.mediacodec.height"; + field public static final java.lang.String MIME_TYPE = "android.media.mediacodec.mime"; + field public static final java.lang.String MODE = "android.media.mediacodec.mode"; + field public static final java.lang.String MODE_AUDIO = "audio"; + field public static final java.lang.String MODE_VIDEO = "video"; + field public static final java.lang.String ROTATION = "android.media.mediacodec.rotation"; + field public static final java.lang.String SECURE = "android.media.mediacodec.secure"; + field public static final java.lang.String WIDTH = "android.media.mediacodec.width"; + } + public static abstract interface MediaCodec.OnFrameRenderedListener { method public abstract void onFrameRendered(android.media.MediaCodec, long, long); } @@ -24102,12 +24161,12 @@ package android.media { 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 { @@ -24171,7 +24230,7 @@ package android.media { 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 @@ -24245,8 +24304,9 @@ package android.media { 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 android.os.PersistableBundle getMetrics(); method public java.util.Map<java.util.UUID, byte[]> getPsshInfo(); method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo); method public int getSampleFlags(); @@ -24276,6 +24336,17 @@ package android.media { 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 static final class MediaExtractor.MetricsConstants { + field public static final java.lang.String FORMAT = "android.media.mediaextractor.fmt"; + field public static final java.lang.String MIME_TYPE = "android.media.mediaextractor.mime"; + field public static final java.lang.String TRACKS = "android.media.mediaextractor.ntrk"; + } + public final class MediaFormat { ctor public MediaFormat(); method public final boolean containsKey(java.lang.String); @@ -24501,69 +24572,6 @@ package android.media { field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0 } - public final class MediaMetricsSet { - method public double getDouble(java.lang.String, double); - method public int getInt(java.lang.String, int); - method public long getLong(java.lang.String, long); - method public java.lang.String getString(java.lang.String, java.lang.String); - method public boolean isEmpty(); - method public java.util.Set<java.lang.String> keySet(); - method public int size(); - } - - public static final class MediaMetricsSet.MediaCodec { - field public static final java.lang.String KEY_CODEC = "android.media.mediacodec.codec"; - field public static final java.lang.String KEY_ENCODER = "android.media.mediacodec.encoder"; - field public static final java.lang.String KEY_HEIGHT = "android.media.mediacodec.height"; - field public static final java.lang.String KEY_MIME = "android.media.mediacodec.mime"; - field public static final java.lang.String KEY_MODE = "android.media.mediacodec.mode"; - field public static final java.lang.String KEY_ROTATION = "android.media.mediacodec.rotation"; - field public static final java.lang.String KEY_SECURE = "android.media.mediacodec.secure"; - field public static final java.lang.String KEY_WIDTH = "android.media.mediacodec.width"; - field public static final java.lang.String MODE_AUDIO = "audio"; - field public static final java.lang.String MODE_VIDEO = "video"; - } - - public static final class MediaMetricsSet.MediaExtractor { - field public static final java.lang.String KEY_FORMAT = "android.media.mediaextractor.fmt"; - field public static final java.lang.String KEY_MIME = "android.media.mediaextractor.mime"; - field public static final java.lang.String KEY_TRACKS = "android.media.mediaextractor.ntrk"; - } - - public static final class MediaMetricsSet.MediaPlayer { - field public static final java.lang.String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec"; - field public static final java.lang.String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec"; - field public static final java.lang.String KEY_DURATION = "android.media.mediaplayer.durationMs"; - field public static final java.lang.String KEY_ERRORS = "android.media.mediaplayer.err"; - field public static final java.lang.String KEY_ERROR_CODE = "android.media.mediaplayer.errcode"; - field public static final java.lang.String KEY_FRAMES = "android.media.mediaplayer.frames"; - field public static final java.lang.String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped"; - field public static final java.lang.String KEY_HEIGHT = "android.media.mediaplayer.height"; - field public static final java.lang.String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime"; - field public static final java.lang.String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime"; - field public static final java.lang.String KEY_PLAYING = "android.media.mediaplayer.playingMs"; - field public static final java.lang.String KEY_WIDTH = "android.media.mediaplayer.width"; - } - - public static final class MediaMetricsSet.MediaRecorder { - field public static final java.lang.String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate"; - field public static final java.lang.String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels"; - field public static final java.lang.String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate"; - field public static final java.lang.String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale"; - field public static final java.lang.String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps"; - field public static final java.lang.String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable"; - field public static final java.lang.String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate"; - field public static final java.lang.String KEY_HEIGHT = "android.media.mediarecorder.height"; - field public static final java.lang.String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale"; - field public static final java.lang.String KEY_ROTATION = "android.media.mediarecorder.rotation"; - field public static final java.lang.String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate"; - field public static final java.lang.String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval"; - field public static final java.lang.String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level"; - field public static final java.lang.String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile"; - field public static final java.lang.String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale"; - field public static final java.lang.String KEY_WIDTH = "android.media.mediarecorder.width"; - } - public final class MediaMuxer { ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException; ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException; @@ -24602,7 +24610,7 @@ package android.media { method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException; method public int getDuration(); method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException; - method public android.media.MediaMetricsSet getMetrics(); + method public android.os.PersistableBundle getMetrics(); method public android.media.PlaybackParams getPlaybackParams(); method public int getSelectedTrack(int) throws java.lang.IllegalStateException; method public android.media.SyncParams getSyncParams(); @@ -24697,6 +24705,21 @@ package android.media { method public java.util.UUID[] getSupportedSchemes(); } + public static final class MediaPlayer.MetricsConstants { + field public static final java.lang.String CODEC_AUDIO = "android.media.mediaplayer.audio.codec"; + field public static final java.lang.String CODEC_VIDEO = "android.media.mediaplayer.video.codec"; + field public static final java.lang.String DURATION = "android.media.mediaplayer.durationMs"; + field public static final java.lang.String ERRORS = "android.media.mediaplayer.err"; + field public static final java.lang.String ERROR_CODE = "android.media.mediaplayer.errcode"; + field public static final java.lang.String FRAMES = "android.media.mediaplayer.frames"; + field public static final java.lang.String FRAMES_DROPPED = "android.media.mediaplayer.dropped"; + field public static final java.lang.String HEIGHT = "android.media.mediaplayer.height"; + field public static final java.lang.String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime"; + field public static final java.lang.String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime"; + field public static final java.lang.String PLAYING = "android.media.mediaplayer.playingMs"; + field public static final java.lang.String WIDTH = "android.media.mediaplayer.width"; + } + public static final class MediaPlayer.NoDrmSchemeException extends android.media.MediaDrmException { ctor public MediaPlayer.NoDrmSchemeException(java.lang.String); } @@ -24771,7 +24794,7 @@ package android.media { ctor public MediaRecorder(); method public static final int getAudioSourceMax(); method public int getMaxAmplitude() throws java.lang.IllegalStateException; - method public android.media.MediaMetricsSet getMetrics(); + method public android.os.PersistableBundle getMetrics(); method public android.view.Surface getSurface(); method public void pause() throws java.lang.IllegalStateException; method public void prepare() throws java.io.IOException, java.lang.IllegalStateException; @@ -24790,11 +24813,12 @@ package android.media { method public void setMaxDuration(int) throws java.lang.IllegalArgumentException; method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException; method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalStateException; - method public void setNextOutputFile(java.lang.String) throws java.io.IOException, java.lang.IllegalStateException; + method public void setNextOutputFile(java.io.File) throws java.io.IOException, java.lang.IllegalStateException; method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener); method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener); method public void setOrientationHint(int); method public void setOutputFile(java.io.FileDescriptor) throws java.lang.IllegalStateException; + method public void setOutputFile(java.io.File); method public void setOutputFile(java.lang.String) throws java.lang.IllegalStateException; method public void setOutputFormat(int) throws java.lang.IllegalStateException; method public void setPreviewDisplay(android.view.Surface); @@ -24841,6 +24865,25 @@ package android.media { field public static final int VOICE_UPLINK = 2; // 0x2 } + public static final class MediaRecorder.MetricsConstants { + field public static final java.lang.String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate"; + field public static final java.lang.String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels"; + field public static final java.lang.String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate"; + field public static final java.lang.String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale"; + field public static final java.lang.String CAPTURE_FPS = "android.media.mediarecorder.capture-fps"; + field public static final java.lang.String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable"; + field public static final java.lang.String FRAMERATE = "android.media.mediarecorder.frame-rate"; + field public static final java.lang.String HEIGHT = "android.media.mediarecorder.height"; + field public static final java.lang.String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale"; + field public static final java.lang.String ROTATION = "android.media.mediarecorder.rotation"; + field public static final java.lang.String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate"; + field public static final java.lang.String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval"; + field public static final java.lang.String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level"; + field public static final java.lang.String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile"; + field public static final java.lang.String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale"; + field public static final java.lang.String WIDTH = "android.media.mediarecorder.width"; + } + public static abstract interface MediaRecorder.OnErrorListener { method public abstract void onError(android.media.MediaRecorder, int, int); } @@ -25455,7 +25498,7 @@ package android.media { 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(); @@ -25481,7 +25524,7 @@ package android.media { 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); } @@ -26477,12 +26520,15 @@ package android.media.tv { 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"; @@ -26490,9 +26536,16 @@ package android.media.tv { 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 { @@ -26523,7 +26576,6 @@ package android.media.tv { 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"; @@ -26584,9 +26636,10 @@ package android.media.tv { 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 @@ -26681,6 +26734,8 @@ package android.media.tv { 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"; @@ -26695,6 +26750,9 @@ package android.media.tv { 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 { @@ -26741,6 +26799,8 @@ package android.media.tv { 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"; @@ -26754,14 +26814,18 @@ package android.media.tv { 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 @@ -26969,6 +27033,9 @@ package android.media.tv { 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); @@ -27669,22 +27736,25 @@ package android.net { 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 } @@ -27961,6 +28031,7 @@ package android.net { method public android.net.NetworkRequest.Builder removeCapability(int); method public android.net.NetworkRequest.Builder removeTransportType(int); method public android.net.NetworkRequest.Builder setNetworkSpecifier(java.lang.String); + method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier); } public class NetworkScoreManager { @@ -27979,6 +28050,9 @@ package android.net { field public static final java.lang.String EXTRA_PACKAGE_NAME = "packageName"; } + public abstract class NetworkSpecifier { + } + public class ParseException extends java.lang.RuntimeException { field public java.lang.String response; } @@ -28101,10 +28175,6 @@ package android.net { field public static final java.lang.String ATTRIBUTES_KEY_BADGING_CURVE = "android.net.attributes.key.BADGING_CURVE"; field public static final java.lang.String ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL = "android.net.attributes.key.HAS_CAPTIVE_PORTAL"; field public static final java.lang.String ATTRIBUTES_KEY_RANKING_SCORE_OFFSET = "android.net.attributes.key.RANKING_SCORE_OFFSET"; - field public static final deprecated int BADGING_4K = 30; // 0x1e - field public static final deprecated int BADGING_HD = 20; // 0x14 - field public static final deprecated int BADGING_NONE = 0; // 0x0 - field public static final deprecated int BADGING_SD = 10; // 0xa field public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR; field public final android.os.Bundle attributes; field public final boolean meteredHint; @@ -28112,9 +28182,6 @@ package android.net { field public final android.net.RssiCurve rssiCurve; } - public static abstract deprecated class ScoredNetwork.Badging implements java.lang.annotation.Annotation { - } - public class TrafficStats { ctor public TrafficStats(); method public static void clearThreadStatsTag(); @@ -34629,7 +34696,7 @@ package android.os { 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"; @@ -34781,7 +34848,7 @@ package android.os.health { 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 @@ -37448,10 +37515,15 @@ package android.provider { } 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 @@ -37463,6 +37535,35 @@ package android.provider { 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"; @@ -37950,8 +38051,8 @@ package android.provider { 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"; @@ -38111,6 +38212,7 @@ package android.provider { 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 @@ -40073,8 +40175,10 @@ package android.service.autofill { method public final android.os.IBinder onBind(android.content.Intent); method public void onConnected(); method public void onDisconnected(); - method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback); - method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback); + method public void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback); + method public abstract deprecated void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback); + method public void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback); + method public abstract deprecated void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback); field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService"; field public static final java.lang.String SERVICE_META_DATA = "android.autofill"; } @@ -40099,6 +40203,25 @@ package android.service.autofill { method public void onSuccess(android.service.autofill.FillResponse); } + public final class FillContext implements android.os.Parcelable { + method public int describeContents(); + method public int getRequestId(); + method public android.app.assist.AssistStructure getStructure(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR; + } + + public final class FillRequest implements android.os.Parcelable { + method public int describeContents(); + method public android.os.Bundle getClientState(); + method public int getFlags(); + method public int getId(); + method public android.app.assist.AssistStructure getStructure(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR; + field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1 + } + public final class FillResponse implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); @@ -40110,7 +40233,8 @@ package android.service.autofill { method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset); method public android.service.autofill.FillResponse build(); method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews); - method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle); + method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle); + method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle); method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo); } @@ -40139,6 +40263,14 @@ package android.service.autofill { method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]); } + public final class SaveRequest implements android.os.Parcelable { + method public int describeContents(); + method public android.os.Bundle getClientState(); + method public java.util.List<android.service.autofill.FillContext> getFillContexts(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR; + } + } package android.service.carrier { @@ -40258,7 +40390,7 @@ package android.service.dreams { 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(); @@ -40428,12 +40560,16 @@ package android.service.notification { 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); @@ -40450,6 +40586,7 @@ package android.service.notification { 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 @@ -40458,6 +40595,9 @@ package android.service.notification { 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 @@ -40544,15 +40684,26 @@ package android.service.notification { } +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 @@ -40895,10 +41046,12 @@ package android.service.wallpaper { method public int getDesiredMinimumHeight(); method public int getDesiredMinimumWidth(); method public android.view.SurfaceHolder getSurfaceHolder(); + method public void invalidateColors(); method public boolean isPreview(); method public boolean isVisible(); method public void onApplyWindowInsets(android.view.WindowInsets); method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean); + method public android.app.WallpaperColors onComputeWallpaperColors(); method public void onCreate(android.view.SurfaceHolder); method public void onDesiredSizeChanged(int, int); method public void onDestroy(); @@ -43589,7 +43742,8 @@ package android.telephony { 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(); @@ -43604,7 +43758,7 @@ package android.telephony { 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(); @@ -43621,7 +43775,7 @@ package android.telephony { 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); @@ -44422,6 +44576,7 @@ package android.test.mock { method public byte[] getInstantAppCookie(); method public int getInstantAppCookieMaxSize(); method public android.graphics.drawable.Drawable getInstantAppIcon(java.lang.String); + method public android.content.ComponentName getInstantAppInstallerComponent(); method public android.content.ComponentName getInstantAppResolverSettingsComponent(); method public java.util.List<android.content.pm.InstantAppInfo> getInstantApps(); method public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException; @@ -46156,7 +46311,7 @@ package android.text.util { 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; @@ -47370,7 +47525,6 @@ package android.view { 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 @@ -48851,7 +49005,6 @@ package android.view { method public android.view.animation.Animation getAnimation(); method public android.os.IBinder getApplicationWindowToken(); method public java.lang.String[] getAutofillHints(); - method public int getAutofillMode(); method public int getAutofillType(); method public android.view.autofill.AutofillValue getAutofillValue(); method public android.graphics.drawable.Drawable getBackground(); @@ -48868,6 +49021,7 @@ package android.view { 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(); @@ -48939,7 +49093,6 @@ package android.view { method public float getPivotX(); method public float getPivotY(); method public android.view.PointerIcon getPointerIcon(); - method public int getResolvedAutofillMode(); method public android.content.res.Resources getResources(); method public final boolean getRevealOnFocusHint(); method public final int getRight(); @@ -49172,7 +49325,6 @@ package android.view { method public void setAlpha(float); method public void setAnimation(android.view.animation.Animation); method public void setAutofillHints(java.lang.String...); - method public void setAutofillMode(int); method public void setBackground(android.graphics.drawable.Drawable); method public void setBackgroundColor(int); method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable); @@ -49186,6 +49338,7 @@ package android.view { 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); @@ -49327,9 +49480,6 @@ package android.view { field public static final java.lang.String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress"; field public static final java.lang.String AUTOFILL_HINT_POSTAL_CODE = "postalCode"; field public static final java.lang.String AUTOFILL_HINT_USERNAME = "username"; - field public static final int AUTOFILL_MODE_AUTO = 1; // 0x1 - field public static final int AUTOFILL_MODE_INHERIT = 0; // 0x0 - field public static final int AUTOFILL_MODE_MANUAL = 2; // 0x2 field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4 field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3 field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0 @@ -49897,7 +50047,6 @@ package android.view { method public abstract int getLayoutDirection(); method public abstract android.view.ViewParent getParent(); method public abstract android.view.ViewParent getParentForAccessibility(); - method public default int getResolvedAutofillMode(); method public abstract int getTextAlignment(); method public abstract int getTextDirection(); method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect); @@ -51287,7 +51436,7 @@ package android.view.autofill { field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE"; field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT"; field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS"; - field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1 + field public static final deprecated int FLAG_MANUAL_REQUEST = 1; // 0x1 } public static abstract class AutofillManager.AutofillCallback { @@ -52523,7 +52672,7 @@ package android.webkit { 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 1effe9cead69..7bdb9571bad0 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -5,10 +5,6 @@ package android.app { method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent); } - public static class Notification.Builder { - method public deprecated android.app.Notification.Builder chooseBadgeIcon(int); - } - public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable { method public deprecated void showAsNotification(android.content.Context); } @@ -98,6 +94,18 @@ package android.graphics { } +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 5c8edac69edb..bd2fed09c9d6 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -210,6 +210,8 @@ package android { 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 __removed3 = 16844116; // 0x1010554 field public static final int absListViewStyle = 16842858; // 0x101006a field public static final int accessibilityEventTypes = 16843648; // 0x1010380 field public static final int accessibilityFeedbackType = 16843650; // 0x1010382 @@ -312,7 +314,6 @@ package android { field public static final int autoUrlDetect = 16843404; // 0x101028c field public static final int autoVerify = 16844014; // 0x10104ee field public static final int autofillHints = 16844121; // 0x1010559 - field public static final int autofillMode = 16844116; // 0x1010554 field public static final int background = 16842964; // 0x10100d4 field public static final int backgroundDimAmount = 16842802; // 0x1010032 field public static final int backgroundDimEnabled = 16843295; // 0x101021f @@ -471,6 +472,7 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android.accounts { 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"; @@ -3612,6 +3617,7 @@ package android.app { method public android.net.Uri getReferrer(); method public int getRequestedOrientation(); method public final android.view.SearchEvent getSearchEvent(); + method public long getStartInitiatedTime(); method public int getTaskId(); method public final java.lang.CharSequence getTitle(); method public final int getTitleColor(); @@ -3848,6 +3854,7 @@ package android.app { 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(); @@ -3945,7 +3952,8 @@ package android.app { field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64 field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d field public static final int IMPORTANCE_GONE = 1000; // 0x3e8 - field public static final int IMPORTANCE_PERCEPTIBLE = 130; // 0x82 + field public static final int IMPORTANCE_PERCEPTIBLE = 230; // 0xe6 + field public static final deprecated int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130; // 0x82 field public static final int IMPORTANCE_SERVICE = 300; // 0x12c field public static final int IMPORTANCE_TOP_SLEEPING = 150; // 0x96 field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8 @@ -4707,7 +4715,7 @@ package android.app { 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 +4766,7 @@ package android.app { 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(); @@ -6104,6 +6112,17 @@ package android.app { method public void onDetached(); } + public final class WallpaperColors implements android.os.Parcelable { + ctor public WallpaperColors(android.os.Parcel); + ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>); + ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean); + method public int describeContents(); + method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors(); + method public boolean supportsDarkText(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR; + } + public final class WallpaperInfo implements android.os.Parcelable { ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public int describeContents(); @@ -6126,6 +6145,8 @@ package android.app { } public class WallpaperManager { + method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener); + method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler); method public void clear() throws java.io.IOException; method public void clear(int) throws java.io.IOException; method public void clearWallpaperOffsets(android.os.IBinder); @@ -6140,6 +6161,7 @@ package android.app { method public android.graphics.drawable.Drawable getDrawable(); method public android.graphics.drawable.Drawable getFastDrawable(); method public static android.app.WallpaperManager getInstance(android.content.Context); + method public android.app.WallpaperColors getWallpaperColors(int); method public android.os.ParcelFileDescriptor getWallpaperFile(int); method public int getWallpaperId(int); method public android.app.WallpaperInfo getWallpaperInfo(); @@ -6148,6 +6170,7 @@ package android.app { method public boolean isWallpaperSupported(); method public android.graphics.drawable.Drawable peekDrawable(); method public android.graphics.drawable.Drawable peekFastDrawable(); + method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener); method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle); method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException; method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException; @@ -6172,6 +6195,10 @@ package android.app { field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview"; } + public static abstract interface WallpaperManager.OnColorsChangedListener { + method public abstract void onColorsChanged(android.app.WallpaperColors, int); + } + } package android.app.admin { @@ -6817,6 +6844,7 @@ package android.app.job { 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 +6883,8 @@ package android.app.job { } 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 +6902,7 @@ package android.app.job { 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 +6919,23 @@ package android.app.job { field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE"; } + public abstract class JobServiceEngine { + ctor public JobServiceEngine(android.content.Context); + method public final android.os.IBinder getBinder(); + method public final void jobFinished(android.app.job.JobParameters, boolean); + method public abstract boolean onStartJob(android.app.job.JobParameters); + method public abstract boolean onStopJob(android.app.job.JobParameters); + } + + 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 +7669,11 @@ package android.bluetooth { 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 +8091,6 @@ package android.bluetooth.le { 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 @@ -8081,7 +8128,12 @@ package android.bluetooth.le { method public void flushPendingScanResults(android.bluetooth.le.ScanCallback); method public void startScan(android.bluetooth.le.ScanCallback); method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback); + method public int startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.app.PendingIntent); method public void stopScan(android.bluetooth.le.ScanCallback); + method public void stopScan(android.app.PendingIntent); + field public static final java.lang.String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE"; + field public static final java.lang.String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE"; + field public static final java.lang.String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT"; } public final class PeriodicAdvertisingParameters implements android.os.Parcelable { @@ -8172,9 +8224,6 @@ package android.bluetooth.le { 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 } @@ -8197,9 +8246,7 @@ package android.bluetooth.le { 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 @@ -8261,7 +8308,8 @@ package android.companion { method public android.companion.BluetoothLEDeviceFilter build(); method public android.companion.BluetoothLEDeviceFilter.Builder setNamePattern(java.util.regex.Pattern); method public android.companion.BluetoothLEDeviceFilter.Builder setRawDataFilter(byte[], byte[]); - method public android.companion.BluetoothLEDeviceFilter.Builder setRename(java.lang.String, java.lang.String, int, int, boolean); + method public android.companion.BluetoothLEDeviceFilter.Builder setRenameFromBytes(java.lang.String, java.lang.String, int, int, boolean); + method public android.companion.BluetoothLEDeviceFilter.Builder setRenameFromName(java.lang.String, java.lang.String, int, int); method public android.companion.BluetoothLEDeviceFilter.Builder setScanFilter(android.bluetooth.le.ScanFilter); } @@ -8269,6 +8317,8 @@ package android.companion { method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler); method public void disassociate(java.lang.String); method public java.util.List<java.lang.String> getAssociations(); + method public boolean hasNotificationAccess(android.content.ComponentName); + method public void requestNotificationAccess(android.content.ComponentName); field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE"; } @@ -9366,6 +9416,7 @@ package android.content { 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"; @@ -9482,6 +9533,7 @@ package android.content { 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"; @@ -10382,12 +10434,10 @@ package android.content.pm { 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 @@ -10658,6 +10708,7 @@ package android.content.pm { 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"; @@ -10944,9 +10995,6 @@ package android.content.pm { 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(); @@ -10959,7 +11007,6 @@ package android.content.pm { 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(); @@ -10972,11 +11019,9 @@ package android.content.pm { 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); @@ -11764,15 +11809,6 @@ package android.database { 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); @@ -12575,6 +12611,7 @@ package android.graphics { field public boolean inJustDecodeBounds; field public boolean inMutable; field public deprecated boolean inPreferQualityOverSpeed; + field public android.graphics.ColorSpace inPreferredColorSpace; field public android.graphics.Bitmap.Config inPreferredConfig; field public boolean inPremultiplied; field public deprecated boolean inPurgeable; @@ -13796,7 +13833,7 @@ package android.graphics { } 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); @@ -13818,26 +13855,20 @@ package android.graphics { } 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 @@ -13869,7 +13900,7 @@ package android.graphics.drawable { 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(); @@ -14021,6 +14052,7 @@ package android.graphics.drawable { 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(); @@ -14349,6 +14381,7 @@ package android.graphics.drawable { 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 { @@ -14435,15 +14468,12 @@ package android.graphics.fonts { 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 { @@ -14909,15 +14939,16 @@ package android.hardware { 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 { @@ -14951,7 +14982,6 @@ package android.hardware { 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); @@ -15804,7 +15834,6 @@ package android.hardware.display { 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 @@ -20652,7 +20681,7 @@ package android.location { 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(); @@ -20668,7 +20697,7 @@ package android.location { 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(); @@ -20799,7 +20828,7 @@ package android.location { 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 @@ -21918,24 +21947,19 @@ package android.media { 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 { @@ -21947,6 +21971,13 @@ package android.media { 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 { } @@ -21982,7 +22013,7 @@ package android.media { method public deprecated java.nio.ByteBuffer[] getInputBuffers(); method public final android.media.MediaFormat getInputFormat(); method public android.media.Image getInputImage(int); - method public android.media.MediaMetricsSet getMetrics(); + method public android.os.PersistableBundle getMetrics(); method public final java.lang.String getName(); method public java.nio.ByteBuffer getOutputBuffer(int); method public deprecated java.nio.ByteBuffer[] getOutputBuffers(); @@ -22080,6 +22111,19 @@ package android.media { method public void set(int, int); } + public static final class MediaCodec.MetricsConstants { + field public static final java.lang.String CODEC = "android.media.mediacodec.codec"; + field public static final java.lang.String ENCODER = "android.media.mediacodec.encoder"; + field public static final java.lang.String HEIGHT = "android.media.mediacodec.height"; + field public static final java.lang.String MIME_TYPE = "android.media.mediacodec.mime"; + field public static final java.lang.String MODE = "android.media.mediacodec.mode"; + field public static final java.lang.String MODE_AUDIO = "audio"; + field public static final java.lang.String MODE_VIDEO = "video"; + field public static final java.lang.String ROTATION = "android.media.mediacodec.rotation"; + field public static final java.lang.String SECURE = "android.media.mediacodec.secure"; + field public static final java.lang.String WIDTH = "android.media.mediacodec.width"; + } + public static abstract interface MediaCodec.OnFrameRenderedListener { method public abstract void onFrameRendered(android.media.MediaCodec, long, long); } @@ -22390,12 +22434,12 @@ package android.media { 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 { @@ -22459,7 +22503,7 @@ package android.media { 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 @@ -22533,8 +22577,9 @@ package android.media { 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 android.os.PersistableBundle getMetrics(); method public java.util.Map<java.util.UUID, byte[]> getPsshInfo(); method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo); method public int getSampleFlags(); @@ -22564,6 +22609,17 @@ package android.media { 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 static final class MediaExtractor.MetricsConstants { + field public static final java.lang.String FORMAT = "android.media.mediaextractor.fmt"; + field public static final java.lang.String MIME_TYPE = "android.media.mediaextractor.mime"; + field public static final java.lang.String TRACKS = "android.media.mediaextractor.ntrk"; + } + public final class MediaFormat { ctor public MediaFormat(); method public final boolean containsKey(java.lang.String); @@ -22789,69 +22845,6 @@ package android.media { field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0 } - public final class MediaMetricsSet { - method public double getDouble(java.lang.String, double); - method public int getInt(java.lang.String, int); - method public long getLong(java.lang.String, long); - method public java.lang.String getString(java.lang.String, java.lang.String); - method public boolean isEmpty(); - method public java.util.Set<java.lang.String> keySet(); - method public int size(); - } - - public static final class MediaMetricsSet.MediaCodec { - field public static final java.lang.String KEY_CODEC = "android.media.mediacodec.codec"; - field public static final java.lang.String KEY_ENCODER = "android.media.mediacodec.encoder"; - field public static final java.lang.String KEY_HEIGHT = "android.media.mediacodec.height"; - field public static final java.lang.String KEY_MIME = "android.media.mediacodec.mime"; - field public static final java.lang.String KEY_MODE = "android.media.mediacodec.mode"; - field public static final java.lang.String KEY_ROTATION = "android.media.mediacodec.rotation"; - field public static final java.lang.String KEY_SECURE = "android.media.mediacodec.secure"; - field public static final java.lang.String KEY_WIDTH = "android.media.mediacodec.width"; - field public static final java.lang.String MODE_AUDIO = "audio"; - field public static final java.lang.String MODE_VIDEO = "video"; - } - - public static final class MediaMetricsSet.MediaExtractor { - field public static final java.lang.String KEY_FORMAT = "android.media.mediaextractor.fmt"; - field public static final java.lang.String KEY_MIME = "android.media.mediaextractor.mime"; - field public static final java.lang.String KEY_TRACKS = "android.media.mediaextractor.ntrk"; - } - - public static final class MediaMetricsSet.MediaPlayer { - field public static final java.lang.String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec"; - field public static final java.lang.String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec"; - field public static final java.lang.String KEY_DURATION = "android.media.mediaplayer.durationMs"; - field public static final java.lang.String KEY_ERRORS = "android.media.mediaplayer.err"; - field public static final java.lang.String KEY_ERROR_CODE = "android.media.mediaplayer.errcode"; - field public static final java.lang.String KEY_FRAMES = "android.media.mediaplayer.frames"; - field public static final java.lang.String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped"; - field public static final java.lang.String KEY_HEIGHT = "android.media.mediaplayer.height"; - field public static final java.lang.String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime"; - field public static final java.lang.String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime"; - field public static final java.lang.String KEY_PLAYING = "android.media.mediaplayer.playingMs"; - field public static final java.lang.String KEY_WIDTH = "android.media.mediaplayer.width"; - } - - public static final class MediaMetricsSet.MediaRecorder { - field public static final java.lang.String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate"; - field public static final java.lang.String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels"; - field public static final java.lang.String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate"; - field public static final java.lang.String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale"; - field public static final java.lang.String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps"; - field public static final java.lang.String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable"; - field public static final java.lang.String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate"; - field public static final java.lang.String KEY_HEIGHT = "android.media.mediarecorder.height"; - field public static final java.lang.String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale"; - field public static final java.lang.String KEY_ROTATION = "android.media.mediarecorder.rotation"; - field public static final java.lang.String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate"; - field public static final java.lang.String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval"; - field public static final java.lang.String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level"; - field public static final java.lang.String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile"; - field public static final java.lang.String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale"; - field public static final java.lang.String KEY_WIDTH = "android.media.mediarecorder.width"; - } - public final class MediaMuxer { ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException; ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException; @@ -22890,7 +22883,7 @@ package android.media { method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException; method public int getDuration(); method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException; - method public android.media.MediaMetricsSet getMetrics(); + method public android.os.PersistableBundle getMetrics(); method public android.media.PlaybackParams getPlaybackParams(); method public int getSelectedTrack(int) throws java.lang.IllegalStateException; method public android.media.SyncParams getSyncParams(); @@ -22985,6 +22978,21 @@ package android.media { method public java.util.UUID[] getSupportedSchemes(); } + public static final class MediaPlayer.MetricsConstants { + field public static final java.lang.String CODEC_AUDIO = "android.media.mediaplayer.audio.codec"; + field public static final java.lang.String CODEC_VIDEO = "android.media.mediaplayer.video.codec"; + field public static final java.lang.String DURATION = "android.media.mediaplayer.durationMs"; + field public static final java.lang.String ERRORS = "android.media.mediaplayer.err"; + field public static final java.lang.String ERROR_CODE = "android.media.mediaplayer.errcode"; + field public static final java.lang.String FRAMES = "android.media.mediaplayer.frames"; + field public static final java.lang.String FRAMES_DROPPED = "android.media.mediaplayer.dropped"; + field public static final java.lang.String HEIGHT = "android.media.mediaplayer.height"; + field public static final java.lang.String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime"; + field public static final java.lang.String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime"; + field public static final java.lang.String PLAYING = "android.media.mediaplayer.playingMs"; + field public static final java.lang.String WIDTH = "android.media.mediaplayer.width"; + } + public static final class MediaPlayer.NoDrmSchemeException extends android.media.MediaDrmException { ctor public MediaPlayer.NoDrmSchemeException(java.lang.String); } @@ -23059,7 +23067,7 @@ package android.media { ctor public MediaRecorder(); method public static final int getAudioSourceMax(); method public int getMaxAmplitude() throws java.lang.IllegalStateException; - method public android.media.MediaMetricsSet getMetrics(); + method public android.os.PersistableBundle getMetrics(); method public android.view.Surface getSurface(); method public void pause() throws java.lang.IllegalStateException; method public void prepare() throws java.io.IOException, java.lang.IllegalStateException; @@ -23078,11 +23086,12 @@ package android.media { method public void setMaxDuration(int) throws java.lang.IllegalArgumentException; method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException; method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalStateException; - method public void setNextOutputFile(java.lang.String) throws java.io.IOException, java.lang.IllegalStateException; + method public void setNextOutputFile(java.io.File) throws java.io.IOException, java.lang.IllegalStateException; method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener); method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener); method public void setOrientationHint(int); method public void setOutputFile(java.io.FileDescriptor) throws java.lang.IllegalStateException; + method public void setOutputFile(java.io.File); method public void setOutputFile(java.lang.String) throws java.lang.IllegalStateException; method public void setOutputFormat(int) throws java.lang.IllegalStateException; method public void setPreviewDisplay(android.view.Surface); @@ -23127,6 +23136,25 @@ package android.media { field public static final int VOICE_UPLINK = 2; // 0x2 } + public static final class MediaRecorder.MetricsConstants { + field public static final java.lang.String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate"; + field public static final java.lang.String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels"; + field public static final java.lang.String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate"; + field public static final java.lang.String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale"; + field public static final java.lang.String CAPTURE_FPS = "android.media.mediarecorder.capture-fps"; + field public static final java.lang.String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable"; + field public static final java.lang.String FRAMERATE = "android.media.mediarecorder.frame-rate"; + field public static final java.lang.String HEIGHT = "android.media.mediarecorder.height"; + field public static final java.lang.String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale"; + field public static final java.lang.String ROTATION = "android.media.mediarecorder.rotation"; + field public static final java.lang.String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate"; + field public static final java.lang.String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval"; + field public static final java.lang.String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level"; + field public static final java.lang.String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile"; + field public static final java.lang.String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale"; + field public static final java.lang.String WIDTH = "android.media.mediarecorder.width"; + } + public static abstract interface MediaRecorder.OnErrorListener { method public abstract void onError(android.media.MediaRecorder, int, int); } @@ -23732,7 +23760,7 @@ package android.media { 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(); @@ -23758,7 +23786,7 @@ package android.media { 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); } @@ -24620,14 +24648,14 @@ package android.media.tv { 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"; } @@ -24720,9 +24748,10 @@ package android.media.tv { 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 @@ -24817,6 +24846,8 @@ package android.media.tv { 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"; @@ -24831,6 +24862,9 @@ package android.media.tv { 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 { @@ -24877,6 +24911,8 @@ package android.media.tv { 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"; @@ -24890,14 +24926,18 @@ package android.media.tv { 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 @@ -25616,22 +25656,25 @@ package android.net { 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 } @@ -25871,6 +25914,10 @@ package android.net { method public android.net.NetworkRequest.Builder removeCapability(int); method public android.net.NetworkRequest.Builder removeTransportType(int); method public android.net.NetworkRequest.Builder setNetworkSpecifier(java.lang.String); + method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier); + } + + public abstract class NetworkSpecifier { } public class ParseException extends java.lang.RuntimeException { @@ -32041,7 +32088,7 @@ package android.os.health { 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 @@ -34619,10 +34666,15 @@ package android.provider { } 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 @@ -34634,6 +34686,35 @@ package android.provider { 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"; @@ -35019,8 +35100,8 @@ package android.provider { 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"; @@ -37136,8 +37217,10 @@ package android.service.autofill { method public final android.os.IBinder onBind(android.content.Intent); method public void onConnected(); method public void onDisconnected(); - method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback); - method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback); + method public void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback); + method public abstract deprecated void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback); + method public void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback); + method public abstract deprecated void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback); field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService"; field public static final java.lang.String SERVICE_META_DATA = "android.autofill"; } @@ -37162,6 +37245,25 @@ package android.service.autofill { method public void onSuccess(android.service.autofill.FillResponse); } + public final class FillContext implements android.os.Parcelable { + method public int describeContents(); + method public int getRequestId(); + method public android.app.assist.AssistStructure getStructure(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR; + } + + public final class FillRequest implements android.os.Parcelable { + method public int describeContents(); + method public android.os.Bundle getClientState(); + method public int getFlags(); + method public int getId(); + method public android.app.assist.AssistStructure getStructure(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR; + field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1 + } + public final class FillResponse implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); @@ -37173,7 +37275,8 @@ package android.service.autofill { method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset); method public android.service.autofill.FillResponse build(); method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews); - method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle); + method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle); + method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle); method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo); } @@ -37202,6 +37305,14 @@ package android.service.autofill { method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]); } + public final class SaveRequest implements android.os.Parcelable { + method public int describeContents(); + method public android.os.Bundle getClientState(); + method public java.util.List<android.service.autofill.FillContext> getFillContexts(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR; + } + } package android.service.carrier { @@ -37321,7 +37432,7 @@ package android.service.dreams { 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(); @@ -37489,12 +37600,16 @@ package android.service.notification { 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); @@ -37508,6 +37623,7 @@ package android.service.notification { 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 @@ -37516,6 +37632,9 @@ package android.service.notification { 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 @@ -37868,10 +37987,12 @@ package android.service.wallpaper { method public int getDesiredMinimumHeight(); method public int getDesiredMinimumWidth(); method public android.view.SurfaceHolder getSurfaceHolder(); + method public void invalidateColors(); method public boolean isPreview(); method public boolean isVisible(); method public void onApplyWindowInsets(android.view.WindowInsets); method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean); + method public android.app.WallpaperColors onComputeWallpaperColors(); method public void onCreate(android.view.SurfaceHolder); method public void onDesiredSizeChanged(int, int); method public void onDestroy(); @@ -39546,6 +39667,8 @@ package android.telecom { field public static final java.lang.String ACTION_CONFIGURE_PHONE_ACCOUNT = "android.telecom.action.CONFIGURE_PHONE_ACCOUNT"; field public static final java.lang.String ACTION_DEFAULT_DIALER_CHANGED = "android.telecom.action.DEFAULT_DIALER_CHANGED"; field public static final deprecated java.lang.String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL"; + field public static final java.lang.String ACTION_PHONE_ACCOUNT_REGISTERED = "android.telecom.action.PHONE_ACCOUNT_REGISTERED"; + field public static final java.lang.String ACTION_PHONE_ACCOUNT_UNREGISTERED = "android.telecom.action.PHONE_ACCOUNT_UNREGISTERED"; field public static final java.lang.String ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS = "android.telecom.action.SHOW_CALL_ACCESSIBILITY_SETTINGS"; field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS"; field public static final java.lang.String ACTION_SHOW_MISSED_CALLS_NOTIFICATION = "android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION"; @@ -40297,7 +40420,8 @@ package android.telephony { 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(); @@ -42812,7 +42936,7 @@ package android.text.util { 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; @@ -44190,7 +44314,6 @@ package android.view { 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 @@ -44261,6 +44384,7 @@ package android.view { 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 { @@ -45673,7 +45797,6 @@ package android.view { method public android.view.animation.Animation getAnimation(); method public android.os.IBinder getApplicationWindowToken(); method public java.lang.String[] getAutofillHints(); - method public int getAutofillMode(); method public int getAutofillType(); method public android.view.autofill.AutofillValue getAutofillValue(); method public android.graphics.drawable.Drawable getBackground(); @@ -45690,6 +45813,7 @@ package android.view { 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(); @@ -45761,7 +45885,6 @@ package android.view { method public float getPivotX(); method public float getPivotY(); method public android.view.PointerIcon getPointerIcon(); - method public int getResolvedAutofillMode(); method public android.content.res.Resources getResources(); method public final boolean getRevealOnFocusHint(); method public final int getRight(); @@ -45997,7 +46120,6 @@ package android.view { method public void setAlpha(float); method public void setAnimation(android.view.animation.Animation); method public void setAutofillHints(java.lang.String...); - method public void setAutofillMode(int); method public void setAutofilled(boolean); method public void setBackground(android.graphics.drawable.Drawable); method public void setBackgroundColor(int); @@ -46012,6 +46134,7 @@ package android.view { 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); @@ -46153,9 +46276,6 @@ package android.view { field public static final java.lang.String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress"; field public static final java.lang.String AUTOFILL_HINT_POSTAL_CODE = "postalCode"; field public static final java.lang.String AUTOFILL_HINT_USERNAME = "username"; - field public static final int AUTOFILL_MODE_AUTO = 1; // 0x1 - field public static final int AUTOFILL_MODE_INHERIT = 0; // 0x0 - field public static final int AUTOFILL_MODE_MANUAL = 2; // 0x2 field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4 field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3 field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0 @@ -46727,7 +46847,6 @@ package android.view { method public abstract int getLayoutDirection(); method public abstract android.view.ViewParent getParent(); method public abstract android.view.ViewParent getParentForAccessibility(); - method public default int getResolvedAutofillMode(); method public abstract int getTextAlignment(); method public abstract int getTextDirection(); method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect); @@ -48118,7 +48237,7 @@ package android.view.autofill { field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE"; field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT"; field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS"; - field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1 + field public static final deprecated int FLAG_MANUAL_REQUEST = 1; // 0x1 } public static abstract class AutofillManager.AutofillCallback { @@ -49261,7 +49380,7 @@ package android.webkit { 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 d20c08cf7a8f..1e8370e97dc5 100644 --- a/api/test-removed.txt +++ b/api/test-removed.txt @@ -5,10 +5,6 @@ package android.app { method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent); } - public static class Notification.Builder { - method public deprecated android.app.Notification.Builder chooseBadgeIcon(int); - } - public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable { method public deprecated void showAsNotification(android.content.Context); } @@ -100,6 +96,18 @@ package android.graphics { } +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 bfcad1bb5f96..1bcfb22fe2f2 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 @@ public final class Bmgr { } } + /** + * 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 @@ public final class Bmgr { } 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 ce114fd02475..345895b794a3 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 @@ public final class Backup { } else if (arg.equals("restore")) { doRestore(OsConstants.STDIN_FILENO); } else { - Log.e(TAG, "Invalid operation '" + arg + "'"); + showUsage(); } } @@ -158,6 +158,21 @@ public final class Backup { } } + 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/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 80522886c78f..b320d5d83cc7 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -335,6 +335,7 @@ public class AccountManager { * 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 @@ public class AccountManager { "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 16a45ba6d5fe..9f2c39bbc4ce 100644 --- a/core/java/android/accounts/ChooseAccountActivity.java +++ b/core/java/android/accounts/ChooseAccountActivity.java @@ -77,7 +77,7 @@ public class ChooseAccountActivity extends Activity { 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 a3222d849367..e3352bc85668 100644 --- a/core/java/android/accounts/ChooseAccountTypeActivity.java +++ b/core/java/android/accounts/ChooseAccountTypeActivity.java @@ -99,7 +99,7 @@ public class ChooseAccountTypeActivity extends Activity { 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 844258515561..6680ce6acb04 100644 --- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java +++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java @@ -248,7 +248,7 @@ public class ChooseTypeAndAccountActivity extends Activity 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 @@ public class ChooseTypeAndAccountActivity extends Activity * 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 @@ public class ChooseTypeAndAccountActivity extends Activity * 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 38eab2905022..af74b036a796 100644 --- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java +++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java @@ -84,7 +84,7 @@ public class GrantCredentialsPermissionActivity extends Activity implements View 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 @@ public class GrantCredentialsPermissionActivity extends Activity implements View 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 06291abb69d4..b36a1600bae5 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -18,6 +18,7 @@ package android.app; import android.metrics.LogMaker; import android.graphics.Rect; +import android.os.SystemClock; import android.view.ViewRootImpl.ActivityConfigCallback; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; @@ -4521,12 +4522,20 @@ public class Activity extends ContextThemeWrapper */ 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( @@ -4563,7 +4572,7 @@ public class Activity extends ContextThemeWrapper 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( @@ -5092,6 +5101,15 @@ public class Activity extends ContextThemeWrapper /** * @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) { @@ -5924,7 +5942,7 @@ public class Activity extends ContextThemeWrapper */ 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); @@ -7416,6 +7434,25 @@ public class Activity extends ContextThemeWrapper } } + /** + * Return the timestamp at which this activity start was last initiated by the system in the + * {@link SystemClock#uptimeMillis()} time base. + * + * This can be used to understand how much time is taken for an activity to be started and + * displayed to the user. + * + * @return timestamp at which this activity start was initiated by the system + * or {@code 0} if for any reason the timestamp could not be retrieved. + */ + public long getStartInitiatedTime() { + try { + return ActivityManager.getService().getActivityStartInitiatedTime(mToken); + } catch (RemoteException e) { + Log.e(TAG, "Failed to call getActivityStartTime", e); + return 0; + } + } + class HostCallbacks extends FragmentHostCallback<Activity> { public HostCallbacks() { super(Activity.this /*activity*/); @@ -7463,6 +7500,14 @@ public class Activity extends ContextThemeWrapper } @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 { @@ -7501,7 +7546,7 @@ public class Activity extends ContextThemeWrapper @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 aede1bb67f80..66167a3c986a 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -30,6 +30,8 @@ import android.graphics.GraphicBuffer; import android.graphics.Matrix; import android.graphics.Point; import android.os.BatteryStats; +import android.os.Build; +import android.os.Build.VERSION_CODES; import android.os.IBinder; import android.os.ParcelFileDescriptor; @@ -138,14 +140,17 @@ public class ActivityManager { static final class UidObserver extends IUidObserver.Stub { final OnUidImportanceListener mListener; + final Context mContext; - UidObserver(OnUidImportanceListener listener) { + UidObserver(OnUidImportanceListener listener, Context clientContext) { mListener = listener; + mContext = clientContext; } @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) { - mListener.onUidImportance(uid, RunningAppProcessInfo.procStateToImportance(procState)); + mListener.onUidImportance(uid, RunningAppProcessInfo.procStateToImportanceForClient( + procState, mContext)); } @Override @@ -1222,6 +1227,27 @@ public class ActivityManager { 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) { readFromParcel(source); } @@ -3081,10 +3107,32 @@ public class ActivityManager { public static final int IMPORTANCE_VISIBLE = 200; /** + * Constant for {@link #importance}: {@link #IMPORTANCE_PERCEPTIBLE} had this wrong value + * before {@link Build.VERSION_CODES#O}. Since the {@link Build.VERSION_CODES#O} SDK, + * the value of {@link #IMPORTANCE_PERCEPTIBLE} has been fixed. + * + * @deprecated Use {@link #IMPORTANCE_PERCEPTIBLE} instead. + */ + @Deprecated + public static final int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130; + + /** * Constant for {@link #importance}: This process is not something the user - * is directly aware of, but is otherwise perceptable to them to some degree. + * is directly aware of, but is otherwise perceptible to them to some degree. + */ + public static final int IMPORTANCE_PERCEPTIBLE = 230; + + /** + * Constant for {@link #importance}: {@link #IMPORTANCE_CANT_SAVE_STATE} had + * this wrong value + * before {@link Build.VERSION_CODES#O}. Since the {@link Build.VERSION_CODES#O} SDK, + * the value of {@link #IMPORTANCE_CANT_SAVE_STATE} has been fixed. + * + * @deprecated Use {@link #IMPORTANCE_CANT_SAVE_STATE} instead. + * @hide */ - public static final int IMPORTANCE_PERCEPTIBLE = 130; + @Deprecated + public static final int IMPORTANCE_CANT_SAVE_STATE_DEPRECATED = 170; /** * Constant for {@link #importance}: This process is running an @@ -3092,7 +3140,7 @@ public class ActivityManager { * while in the background. * @hide */ - public static final int IMPORTANCE_CANT_SAVE_STATE = 170; + public static final int IMPORTANCE_CANT_SAVE_STATE= 270; /** * Constant for {@link #importance}: This process is contains services @@ -3128,7 +3176,11 @@ public class ActivityManager { */ public static final int IMPORTANCE_GONE = 1000; - /** @hide */ + /** + * Convert a proc state to the correspondent IMPORTANCE_* constant. If the return value + * will be passed to a client, use {@link #procStateToImportanceForClient}. + * @hide + */ public static int procStateToImportance(int procState) { if (procState == PROCESS_STATE_NONEXISTENT) { return IMPORTANCE_GONE; @@ -3151,6 +3203,28 @@ public class ActivityManager { } } + /** + * Convert a proc state to the correspondent IMPORTANCE_* constant for a client represented + * by a given {@link Context}, with converting {@link #IMPORTANCE_PERCEPTIBLE} + * and {@link #IMPORTANCE_CANT_SAVE_STATE} to the corresponding "wrong" value if the + * client's target SDK < {@link VERSION_CODES#O}. + * @hide + */ + public static int procStateToImportanceForClient(int procState, Context clientContext) { + final int importance = procStateToImportance(procState); + + // For pre O apps, convert to the old, wrong values. + if (clientContext.getApplicationInfo().targetSdkVersion < VERSION_CODES.O) { + switch (importance) { + case IMPORTANCE_PERCEPTIBLE: + return IMPORTANCE_PERCEPTIBLE_DEPRECATED; + case IMPORTANCE_CANT_SAVE_STATE: + return IMPORTANCE_CANT_SAVE_STATE_DEPRECATED; + } + } + return importance; + } + /** @hide */ public static int importanceToProcState(int importance) { if (importance == IMPORTANCE_GONE) { @@ -3380,7 +3454,27 @@ public class ActivityManager { try { int procState = getService().getPackageProcessState(packageName, mContext.getOpPackageName()); - return RunningAppProcessInfo.procStateToImportance(procState); + return RunningAppProcessInfo.procStateToImportanceForClient(procState, mContext); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * 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.procStateToImportanceForClient(procState, mContext); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3430,7 +3524,7 @@ public class ActivityManager { throw new IllegalArgumentException("Listener already registered: " + listener); } // TODO: implement the cut point in the system process to avoid IPCs. - UidObserver observer = new UidObserver(listener); + UidObserver observer = new UidObserver(listener, mContext); try { getService().registerUidObserver(observer, UID_OBSERVER_PROCSTATE | UID_OBSERVER_GONE, diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java index 9928512de09f..7d81c4c029de 100644 --- a/core/java/android/app/AlertDialog.java +++ b/core/java/android/app/AlertDialog.java @@ -48,7 +48,7 @@ import com.android.internal.R; * 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/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index a6838f8bbf0a..e07b7e4a03a1 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -2639,4 +2639,13 @@ public class ApplicationPackageManager extends PackageManager { throw e.rethrowAsRuntimeException(); } } + + @Override + public ComponentName getInstantAppInstallerComponent() { + try { + return mPM.getInstantAppInstallerComponent(); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } } diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index a3c123f74cc4..c7bcc54b51b6 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -34,6 +34,7 @@ import android.os.Bundle; 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 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene } /** + * @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 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene 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 6ed54dcdbc85..77c9c312ce24 100644 --- a/core/java/android/app/FragmentContainer.java +++ b/core/java/android/app/FragmentContainer.java @@ -31,7 +31,7 @@ public abstract class FragmentContainer { * 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 41a885eeb7f0..5ef23e630573 100644 --- a/core/java/android/app/FragmentHostCallback.java +++ b/core/java/android/app/FragmentHostCallback.java @@ -23,6 +23,7 @@ import android.content.Intent; 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 @@ public abstract class FragmentHostCallback<E> extends FragmentContainer { } /** + * @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 @@ public abstract class FragmentHostCallback<E> extends FragmentContainer { @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 75d62956671e..91578a2da9c7 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -1243,7 +1243,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate + 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 780a9227cecc..9a920d7a87b4 100644 --- a/core/java/android/app/FragmentTransition.java +++ b/core/java/android/app/FragmentTransition.java @@ -193,7 +193,7 @@ class FragmentTransition { 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 @@ class FragmentTransition { 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 079bbcdd4951..4210d2e7d3ec 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -190,6 +190,8 @@ interface IActivityManager { 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 @@ interface IActivityManager { * 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 @@ interface IActivityManager { * @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); @@ -640,6 +632,8 @@ interface IActivityManager { */ void backgroundWhitelistUid(int uid); + long getActivityStartInitiatedTime(IBinder token); + // WARNING: when these transactions are updated, check if they are any callers on the native // side. If so, make sure they are using the correct transaction ids and arguments. // If a transaction which will also be used on the native side is being inserted, add it diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 61dacefd3f51..f4e8f3f5687e 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -101,6 +101,10 @@ interface INotificationManager 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 d546f2771df8..9377d35ecabd 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -1779,7 +1779,7 @@ public class Instrumentation { * {@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 @@ public class Instrumentation { 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 e30b96fd692a..4ac44f79a4ec 100644 --- a/core/java/android/app/JobSchedulerImpl.java +++ b/core/java/android/app/JobSchedulerImpl.java @@ -20,6 +20,8 @@ package android.app; 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 @@ public class JobSchedulerImpl extends JobScheduler { } @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/Notification.java b/core/java/android/app/Notification.java index 7f26f4fd7050..8ed52a1bba59 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -2339,7 +2339,9 @@ public class Notification implements Parcelable @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("Notification(pri="); + sb.append("Notification(channel="); + sb.append(getChannel()); + sb.append(" pri="); sb.append(priority); sb.append(" contentView="); if (contentView != null) { @@ -2729,21 +2731,6 @@ public class Notification implements Parcelable } /** - * @removed - * Sets which icon to display as a badge for this notification. - * - * Must be one of {@link #BADGE_ICON_NONE}, {@link #BADGE_ICON_SMALL}, - * {@link #BADGE_ICON_LARGE}. - * - * Note: This value might be ignored, for launchers that don't support badge icons. - */ - @Deprecated - public Builder chooseBadgeIcon(int icon) { - mN.mBadgeIcon = icon; - return this; - } - - /** * Sets which icon to display as a badge for this notification. * * Must be one of {@link #BADGE_ICON_NONE}, {@link #BADGE_ICON_SMALL}, @@ -3259,9 +3246,10 @@ public class Notification implements Parcelable * This should only be used for high priority ongoing tasks like navigation, an ongoing * call, or other similarly high-priority events for the user. * <p> - * For most styles, the coloring will only be applied if the notification is ongoing. + * For most styles, the coloring will only be applied if the notification is for a + * foreground service notification. * However, for {@link MediaStyle} and {@link DecoratedMediaCustomViewStyle} notifications - * that have a media session attached there is no requirement for it to be ongoing. + * that have a media session attached there is no such requirement. * * @see Builder#setOngoing(boolean) * @see Builder#setColor(int) @@ -4759,12 +4747,10 @@ public class Notification implements Parcelable } /** - * @return whether this notification is ongoing and can't be dismissed by the user. + * @return whether this notification is a foreground service notification */ - private boolean isOngoing() { - final int ongoingFlags = Notification.FLAG_FOREGROUND_SERVICE - | Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR; - return (flags & ongoingFlags) != 0; + private boolean isForegroundService() { + return (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0; } /** @@ -4789,8 +4775,7 @@ public class Notification implements Parcelable } /** - * @return true if this notification is colorized. This also factors in whether the - * notification is ongoing. + * @return true if this notification is colorized. * * @hide */ @@ -4806,7 +4791,7 @@ public class Notification implements Parcelable return true; } } - return extras.getBoolean(EXTRA_COLORIZED) && isOngoing(); + return extras.getBoolean(EXTRA_COLORIZED) && isForegroundService(); } private boolean hasLargeIcon() { diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java index 92216d15ec95..e50bc136bc5a 100644 --- a/core/java/android/app/NotificationChannel.java +++ b/core/java/android/app/NotificationChannel.java @@ -26,6 +26,7 @@ import android.media.AudioAttributes; 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 @@ public final class NotificationChannel implements Parcelable { 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 @@ public final class NotificationChannel implements Parcelable { /** * 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 @@ public final class NotificationChannel implements Parcelable { } /** - * 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/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 3191eec03ffa..6f326de76150 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -112,13 +112,6 @@ public class ResourcesManager { private final ArrayMap<Pair<Integer, DisplayAdjustments>, WeakReference<Display>> mAdjustedDisplays = new ArrayMap<>(); - /** - * A cache of DisplayId, Resources to Display. These display adjustments associated with these - * {@link Display}s will change as the resources change. - */ - private final ArrayMap<Pair<Integer, ResourcesKey>, WeakReference<Display>> mResourceDisplays = - new ArrayMap<>(); - public static ResourcesManager getInstance() { synchronized (ResourcesManager.class) { if (sResourcesManager == null) { @@ -251,51 +244,16 @@ public class ResourcesManager { */ public Display getAdjustedDisplay(final int displayId, Resources resources) { synchronized (this) { - // Note that the ResourcesKey might be {@code null} in the case that the - // {@link Resources} is actually from {@link Resources#getSystem}. In this case, it is - // not managed by {@link ResourcesManager}, but we still want to cache the display - // object. - final Pair<Integer, ResourcesKey> key = Pair.create(displayId, - findKeyForResourceImplLocked(resources.getImpl())); - - WeakReference<Display> wd = mResourceDisplays.get(key); - if (wd != null) { - final Display display = wd.get(); - if (display != null) { - return display; - } - } final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance(); if (dm == null) { // may be null early in system startup return null; } - final Display display = dm.getCompatibleDisplay(displayId, resources); - if (display != null) { - mResourceDisplays.put(key, new WeakReference<>(display)); - } - return display; + return dm.getCompatibleDisplay(displayId, resources); } } private void cleanupResourceImpl(ResourcesKey removedKey) { - // Remove any resource to display mapping based on this key. - final Iterator<Map.Entry<Pair<Integer, ResourcesKey>, WeakReference<Display>>> iter = - mResourceDisplays.entrySet().iterator(); - while (iter.hasNext()) { - final Map.Entry<Pair<Integer, ResourcesKey>, WeakReference<Display>> entry = - iter.next(); - final ResourcesKey key = entry.getKey().second; - - // Do not touch system resource displays (indicated by a {@code null} key) or - // non-matching keys. - if (key == null || !key.equals(removedKey)) { - continue; - } - - iter.remove(); - } - // Remove resource key to resource impl mapping and flush cache final ResourcesImpl res = mResourceImpls.remove(removedKey).get(); @@ -887,7 +845,6 @@ public class ResourcesManager { int changes = mResConfiguration.updateFrom(config); // Things might have changed in display manager, so clear the cached displays. mAdjustedDisplays.clear(); - mResourceDisplays.clear(); DisplayMetrics defaultDisplayMetrics = getDisplayMetrics(); diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index 9c18df8c6c2a..4abca9a13c4b 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -165,7 +165,7 @@ public class SearchDialog extends Dialog { 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 @@ public class SearchDialog extends Dialog { 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 4572578ea608..40fe6af9627d 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -120,6 +120,8 @@ import android.print.IPrintManager; 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 @@ final class SystemServiceRegistry { 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 @@ final class SystemServiceRegistry { @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 @@ final class SystemServiceRegistry { } }}); + 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 @@ final class SystemServiceRegistry { 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 637c8c19aef5..ad8b0dbe23f7 100644 --- a/core/java/android/app/TabActivity.java +++ b/core/java/android/app/TabActivity.java @@ -108,7 +108,7 @@ public class TabActivity extends ActivityGroup { @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/WallpaperColors.java b/core/java/android/app/WallpaperColors.java new file mode 100644 index 000000000000..5ed66cac5f8f --- /dev/null +++ b/core/java/android/app/WallpaperColors.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; + +import android.graphics.Color; +import android.os.Parcel; +import android.os.Parcelable; + +import android.util.Pair; + +import java.util.List; + +/** + * A class containing information about the colors of a wallpaper. + */ +public final class WallpaperColors implements Parcelable { + + public WallpaperColors(Parcel parcel) { + } + + /** + * Wallpaper color details containing a list of colors and their weights, + * as if it were an histogram. + * This list can be extracted from a bitmap by the Palette API. + * + * Dark text support will be calculated internally based on the histogram. + * + * @param colors list of pairs where each pair contains a color + * and number of occurrences/influence. + */ + public WallpaperColors(List<Pair<Color, Integer>> colors) { + } + + /** + * Wallpaper color details containing a list of colors and their weights, + * as if it were an histogram. + * Explicit dark text support. + * + * @param colors list of pairs where each pair contains a color + * and number of occurrences/influence. + * @param supportsDarkText can have dark text on top or not + */ + public WallpaperColors(List<Pair<Color, Integer>> colors, boolean supportsDarkText) { + } + + public static final Creator<WallpaperColors> CREATOR = new Creator<WallpaperColors>() { + @Override + public WallpaperColors createFromParcel(Parcel in) { + return new WallpaperColors(in); + } + + @Override + public WallpaperColors[] newArray(int size) { + return new WallpaperColors[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + } + + /** + * List of colors with their occurrences. The bigger the int, the more relevant the color. + * @return list of colors paired with their weights. + */ + public List<Pair<Color, Integer>> getColors() { + return null; + } + + /** + * Whether or not dark text is legible on top of this wallpaper. + * + * @return true if dark text is supported + */ + public boolean supportsDarkText() { + return false; + } +} diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index aa0eaaebf975..0676bca0e796 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -17,6 +17,8 @@ package android.app; import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RawRes; import android.annotation.SystemApi; import android.content.ComponentName; @@ -741,6 +743,43 @@ public class WallpaperManager { return getWallpaperFile(which, mContext.getUserId()); } + + /** + * Registers a listener to get notified when the wallpaper colors change. + * Callback might be called from an arbitrary background thread. + * + * @param listener A listener to register + */ + public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener) { + } + + /** + * Registers a listener to get notified when the wallpaper colors change + * @param listener A listener to register + * @param handler Where to call it from. Might be called from a background thread + * if null. + */ + public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener, + @Nullable Handler handler) { + } + + /** + * Stop listening to color updates. + * @param callback A callback to unsubscribe + */ + public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener callback) { + } + + /** + * Get the primary colors of a wallpaper + * @param which wallpaper type. Must be either {@link #FLAG_SYSTEM} or + * {@link #FLAG_LOCK} + * @return a list of colors ordered by priority + */ + public @Nullable WallpaperColors getWallpaperColors(int which) { + return null; + } + /** * Version of {@link #getWallpaperFile(int)} that can access the wallpaper data * for a given user. The caller must hold the INTERACT_ACROSS_USERS_FULL @@ -1732,4 +1771,19 @@ public class WallpaperManager { mLatch.countDown(); } } + + /** + * Interface definition for a callback to be invoked when colors change on a wallpaper. + */ + public interface OnColorsChangedListener { + /** + * Called when colors change. + * A {@link android.app.WallpaperColors} object containing a simplified + * color histogram will be given. + * + * @param colors Wallpaper color info + * @param which A combination of {@link #FLAG_LOCK} and {@link #FLAG_SYSTEM} + */ + void onColorsChanged(WallpaperColors colors, int which); + } } diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java index 790a95203511..2b590e0d4301 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.Retention; 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 2d3948f6e85d..e7695e2e747f 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 @@ interface IJobCallback { */ 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 b6eec27c5412..e94da0c69f9c 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 @@ import android.app.job.JobInfo; */ 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 8220ff94361f..23baa17d947f 100644 --- a/core/java/android/app/job/JobInfo.java +++ b/core/java/android/app/job/JobInfo.java @@ -23,6 +23,7 @@ import android.annotation.Nullable; 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 class JobInfo implements Parcelable { 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 @@ public class JobInfo implements Parcelable { } /** - * 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 @@ public class JobInfo implements Parcelable { 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 8d52d3b96941..016a0fa8b92b 100644 --- a/core/java/android/app/job/JobParameters.java +++ b/core/java/android/app/job/JobParameters.java @@ -24,6 +24,7 @@ import android.os.IBinder; 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 @@ public class JobParameters implements Parcelable { 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 1b640d08dde2..e0afe039478e 100644 --- a/core/java/android/app/job/JobScheduler.java +++ b/core/java/android/app/job/JobScheduler.java @@ -19,6 +19,10 @@ package android.app.job; 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 abstract class JobScheduler { 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 class JobScheduler { 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/app/job/JobService.java b/core/java/android/app/job/JobService.java index f4019ce446f7..9096b47b8d4d 100644 --- a/core/java/android/app/job/JobService.java +++ b/core/java/android/app/job/JobService.java @@ -60,161 +60,24 @@ public abstract class JobService extends Service { public static final String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE"; - /** - * Identifier for a message that will result in a call to - * {@link #onStartJob(android.app.job.JobParameters)}. - */ - private static final int MSG_EXECUTE_JOB = 0; - /** - * Message that will result in a call to {@link #onStopJob(android.app.job.JobParameters)}. - */ - private static final int MSG_STOP_JOB = 1; - /** - * Message that the client has completed execution of this job. - */ - private static final int MSG_JOB_FINISHED = 2; - - /** Lock object for {@link #mHandler}. */ - private final Object mHandlerLock = new Object(); - - /** - * Handler we post jobs to. Responsible for calling into the client logic, and handling the - * callback to the system. - */ - @GuardedBy("mHandlerLock") - JobHandler mHandler; - - static final class JobInterface extends IJobService.Stub { - final WeakReference<JobService> mService; - - JobInterface(JobService service) { - mService = new WeakReference<>(service); - } - - @Override - public void startJob(JobParameters jobParams) throws RemoteException { - JobService service = mService.get(); - if (service != null) { - service.ensureHandler(); - Message m = Message.obtain(service.mHandler, MSG_EXECUTE_JOB, jobParams); - m.sendToTarget(); - } - } - - @Override - public void stopJob(JobParameters jobParams) throws RemoteException { - JobService service = mService.get(); - if (service != null) { - service.ensureHandler(); - Message m = Message.obtain(service.mHandler, MSG_STOP_JOB, jobParams); - m.sendToTarget(); - } - - } - } - - IJobService mBinder; + private JobServiceEngine mEngine; /** @hide */ - void ensureHandler() { - synchronized (mHandlerLock) { - if (mHandler == null) { - mHandler = new JobHandler(getMainLooper()); - } - } - } - - /** - * Runs on application's main thread - callbacks are meant to offboard work to some other - * (app-specified) mechanism. - * @hide - */ - class JobHandler extends Handler { - JobHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - final JobParameters params = (JobParameters) msg.obj; - switch (msg.what) { - case MSG_EXECUTE_JOB: - try { - boolean workOngoing = JobService.this.onStartJob(params); - ackStartMessage(params, workOngoing); - } catch (Exception e) { - Log.e(TAG, "Error while executing job: " + params.getJobId()); - throw new RuntimeException(e); - } - break; - case MSG_STOP_JOB: - try { - boolean ret = JobService.this.onStopJob(params); - ackStopMessage(params, ret); - } catch (Exception e) { - Log.e(TAG, "Application unable to handle onStopJob.", e); - throw new RuntimeException(e); - } - break; - case MSG_JOB_FINISHED: - final boolean needsReschedule = (msg.arg2 == 1); - IJobCallback callback = params.getCallback(); - if (callback != null) { - try { - callback.jobFinished(params.getJobId(), needsReschedule); - } catch (RemoteException e) { - Log.e(TAG, "Error reporting job finish to system: binder has gone" + - "away."); - } - } else { - Log.e(TAG, "finishJob() called for a nonexistent job id."); - } - break; - default: - Log.e(TAG, "Unrecognised message received."); - break; - } - } - - private void ackStartMessage(JobParameters params, boolean workOngoing) { - final IJobCallback callback = params.getCallback(); - final int jobId = params.getJobId(); - if (callback != null) { - try { - callback.acknowledgeStartMessage(jobId, workOngoing); - } catch(RemoteException e) { - Log.e(TAG, "System unreachable for starting job."); - } - } else { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Attempting to ack a job that has already been processed."); + public final IBinder onBind(Intent intent) { + if (mEngine == null) { + mEngine = new JobServiceEngine(this) { + @Override + public boolean onStartJob(JobParameters params) { + return JobService.this.onStartJob(params); } - } - } - private void ackStopMessage(JobParameters params, boolean reschedule) { - final IJobCallback callback = params.getCallback(); - final int jobId = params.getJobId(); - if (callback != null) { - try { - callback.acknowledgeStopMessage(jobId, reschedule); - } catch(RemoteException e) { - Log.e(TAG, "System unreachable for stopping job."); + @Override + public boolean onStopJob(JobParameters params) { + return JobService.this.onStopJob(params); } - } else { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Attempting to ack a job that has already been processed."); - } - } - } - } - - /** @hide */ - public final IBinder onBind(Intent intent) { - if (mBinder == null) { - mBinder = new JobInterface(this); + }; } - return mBinder.asBinder(); + return mEngine.getBinder(); } /** @@ -269,9 +132,6 @@ public abstract class JobService extends Service { * criteria specified at schedule-time. False otherwise. */ public final void jobFinished(JobParameters params, boolean needsReschedule) { - ensureHandler(); - Message m = Message.obtain(mHandler, MSG_JOB_FINISHED, params); - m.arg2 = needsReschedule ? 1 : 0; - m.sendToTarget(); + mEngine.jobFinished(params, needsReschedule); } }
\ No newline at end of file diff --git a/core/java/android/app/job/JobServiceEngine.java b/core/java/android/app/job/JobServiceEngine.java new file mode 100644 index 000000000000..879212ea1fb3 --- /dev/null +++ b/core/java/android/app/job/JobServiceEngine.java @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.app.job; + +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.util.Log; + +import com.android.internal.annotations.GuardedBy; + +import java.lang.ref.WeakReference; + +/** + * Helper for implementing a {@link android.app.Service} that interacts with + * {@link JobScheduler}. + */ +public abstract class JobServiceEngine { + private static final String TAG = "JobServiceEngine"; + + /** + * Identifier for a message that will result in a call to + * {@link #onStartJob(android.app.job.JobParameters)}. + */ + private static final int MSG_EXECUTE_JOB = 0; + /** + * Message that will result in a call to {@link #onStopJob(android.app.job.JobParameters)}. + */ + private static final int MSG_STOP_JOB = 1; + /** + * Message that the client has completed execution of this job. + */ + private static final int MSG_JOB_FINISHED = 2; + + /** + * Context we are running in. + */ + private final Context mContext; + + private final IJobService mBinder; + + /** Lock object for {@link #mHandler}. */ + private final Object mHandlerLock = new Object(); + + /** + * Handler we post jobs to. Responsible for calling into the client logic, and handling the + * callback to the system. + */ + @GuardedBy("mHandlerLock") + JobHandler mHandler; + + static final class JobInterface extends IJobService.Stub { + final WeakReference<JobServiceEngine> mService; + + JobInterface(JobServiceEngine service) { + mService = new WeakReference<>(service); + } + + @Override + public void startJob(JobParameters jobParams) throws RemoteException { + JobServiceEngine service = mService.get(); + if (service != null) { + Message m = Message.obtain(service.mHandler, MSG_EXECUTE_JOB, jobParams); + m.sendToTarget(); + } + } + + @Override + public void stopJob(JobParameters jobParams) throws RemoteException { + JobServiceEngine service = mService.get(); + if (service != null) { + Message m = Message.obtain(service.mHandler, MSG_STOP_JOB, jobParams); + m.sendToTarget(); + } + } + } + + /** + * Runs on application's main thread - callbacks are meant to offboard work to some other + * (app-specified) mechanism. + * @hide + */ + class JobHandler extends Handler { + JobHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + final JobParameters params = (JobParameters) msg.obj; + switch (msg.what) { + case MSG_EXECUTE_JOB: + try { + boolean workOngoing = JobServiceEngine.this.onStartJob(params); + ackStartMessage(params, workOngoing); + } catch (Exception e) { + Log.e(TAG, "Error while executing job: " + params.getJobId()); + throw new RuntimeException(e); + } + break; + case MSG_STOP_JOB: + try { + boolean ret = JobServiceEngine.this.onStopJob(params); + ackStopMessage(params, ret); + } catch (Exception e) { + Log.e(TAG, "Application unable to handle onStopJob.", e); + throw new RuntimeException(e); + } + break; + case MSG_JOB_FINISHED: + final boolean needsReschedule = (msg.arg2 == 1); + IJobCallback callback = params.getCallback(); + if (callback != null) { + try { + callback.jobFinished(params.getJobId(), needsReschedule); + } catch (RemoteException e) { + Log.e(TAG, "Error reporting job finish to system: binder has gone" + + "away."); + } + } else { + Log.e(TAG, "finishJob() called for a nonexistent job id."); + } + break; + default: + Log.e(TAG, "Unrecognised message received."); + break; + } + } + + private void ackStartMessage(JobParameters params, boolean workOngoing) { + final IJobCallback callback = params.getCallback(); + final int jobId = params.getJobId(); + if (callback != null) { + try { + callback.acknowledgeStartMessage(jobId, workOngoing); + } catch(RemoteException e) { + Log.e(TAG, "System unreachable for starting job."); + } + } else { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Attempting to ack a job that has already been processed."); + } + } + } + + private void ackStopMessage(JobParameters params, boolean reschedule) { + final IJobCallback callback = params.getCallback(); + final int jobId = params.getJobId(); + if (callback != null) { + try { + callback.acknowledgeStopMessage(jobId, reschedule); + } catch(RemoteException e) { + Log.e(TAG, "System unreachable for stopping job."); + } + } else { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Attempting to ack a job that has already been processed."); + } + } + } + } + + /** + * Create a new engine, ready for use. + * + * @param context The {@link Service} that is creating this engine. + */ + public JobServiceEngine(Context context) { + mContext = context; + mBinder = new JobInterface(this); + mHandler = new JobHandler(mContext.getMainLooper()); + } + + /** + * Retrieve the engine's IPC interface that should be returned by + * {@link Service#onBind(Intent)}. + */ + public final IBinder getBinder() { + return mBinder.asBinder(); + } + + /** + * Engine's report that a job has started. See + * {@link JobService#onStartJob(JobParameters) JobService.onStartJob} for more information. + */ + public abstract boolean onStartJob(JobParameters params); + + /** + * Engine's report that a job has stopped. See + * {@link JobService#onStopJob(JobParameters) JobService.onStopJob} for more information. + */ + public abstract boolean onStopJob(JobParameters params); + + /** + * Call in to engine to report that a job has finished executing. See + * {@link JobService#jobFinished(JobParameters, boolean)} JobService.jobFinished} for more + * information. + */ + public final void jobFinished(JobParameters params, boolean needsReschedule) { + Message m = Message.obtain(mHandler, MSG_JOB_FINISHED, params); + m.arg2 = needsReschedule ? 1 : 0; + m.sendToTarget(); + } +}
\ No newline at end of file diff --git a/core/java/android/app/job/JobWorkItem.aidl b/core/java/android/app/job/JobWorkItem.aidl new file mode 100644 index 000000000000..e8fe47d07865 --- /dev/null +++ b/core/java/android/app/job/JobWorkItem.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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; + +/** @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 000000000000..4bb057e689b2 --- /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 cb6fa052ddac..e6cebc0819f5 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -593,24 +593,34 @@ public final class BluetoothDevice implements Parcelable { 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 final class BluetoothDevice implements Parcelable { */ 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 @@ public final class BluetoothDevice implements Parcelable { * {@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 5d1e8ec58ceb..4aaf6bd3eb17 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java @@ -785,11 +785,11 @@ public final class BluetoothGatt implements BluetoothProfile { * 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 2df2ed8ff86f..eddc278851f4 100644 --- a/core/java/android/bluetooth/BluetoothGattServer.java +++ b/core/java/android/bluetooth/BluetoothGattServer.java @@ -558,11 +558,11 @@ public final class BluetoothGattServer implements BluetoothProfile { * * @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 28421ebc4cca..8519dbaadadc 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -1011,6 +1011,18 @@ public final class BluetoothHeadset implements BluetoothProfile { } /** + * 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/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl index 334e88b69fde..582709c3ba47 100644 --- a/core/java/android/bluetooth/IBluetoothGatt.aidl +++ b/core/java/android/bluetooth/IBluetoothGatt.aidl @@ -16,6 +16,7 @@ package android.bluetooth; +import android.app.PendingIntent; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGattService; import android.bluetooth.le.AdvertiseSettings; @@ -47,6 +48,9 @@ interface IBluetoothGatt { void unregisterScanner(in int scannerId); void startScan(in int scannerId, in ScanSettings settings, in List<ScanFilter> filters, in WorkSource workSource, in List scanStorages, in String callingPackage); + void startScanForIntent(in PendingIntent intent, in ScanSettings settings, in List<ScanFilter> filters, + in String callingPackage); + void stopScanForIntent(in PendingIntent intent, in String callingPackage); void stopScan(in int scannerId); void flushPendingBatchResults(in int scannerId); diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java index 4e9fac3ee22b..31d8f482090d 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 @@ import android.os.Parcelable; 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. */ @@ -246,8 +232,8 @@ public final class AdvertisingSetParameters implements Parcelable { 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; @@ -321,12 +307,13 @@ public final class AdvertisingSetParameters implements Parcelable { * 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 @@ public final class AdvertisingSetParameters implements Parcelable { * 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 73fc1339afa6..ea3031b20177 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 @@ public final class BluetoothLeAdvertiser { 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"); } diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java index b63c614711ea..b65a7ad0c017 100644 --- a/core/java/android/bluetooth/le/BluetoothLeScanner.java +++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java @@ -17,17 +17,18 @@ package android.bluetooth.le; import android.Manifest; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.app.ActivityThread; +import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothGatt; import android.bluetooth.IBluetoothGatt; import android.bluetooth.IBluetoothManager; -import android.bluetooth.le.IScannerCallback; import android.os.Handler; import android.os.Looper; -import android.os.ParcelUuid; import android.os.RemoteException; import android.os.WorkSource; import android.util.Log; @@ -36,7 +37,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.UUID; /** * This class provides methods to perform scan related operations for Bluetooth LE devices. An @@ -57,6 +57,27 @@ public final class BluetoothLeScanner { private static final boolean DBG = true; private static final boolean VDBG = false; + /** + * Extra containing a list of ScanResults. It can have one or more results if there was no + * error. In case of error, {@link #EXTRA_ERROR_CODE} will contain the error code and this + * extra will not be available. + */ + public static final String EXTRA_LIST_SCAN_RESULT + = "android.bluetooth.le.extra.LIST_SCAN_RESULT"; + + /** + * Optional extra indicating the error code, if any. The error code will be one of the + * SCAN_FAILED_* codes in {@link ScanCallback}. + */ + public static final String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE"; + + /** + * Optional extra indicating the callback type, which will be one of + * ScanSettings.CALLBACK_TYPE_*. + * @see ScanCallback#onScanResult(int, ScanResult) + */ + public static final String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE"; + private final IBluetoothManager mBluetoothManager; private final Handler mHandler; private BluetoothAdapter mBluetoothAdapter; @@ -110,7 +131,27 @@ public final class BluetoothLeScanner { @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public void startScan(List<ScanFilter> filters, ScanSettings settings, final ScanCallback callback) { - startScan(filters, settings, null, callback, null); + startScan(filters, settings, null, callback, /*callbackIntent=*/ null, null); + } + + /** + * Start Bluetooth LE scan using a {@link PendingIntent}. The scan results will be delivered via + * the PendingIntent. Use this method of scanning if your process is not always running and it + * should be started when scan results are available. + * + * @param filters Optional list of ScanFilters for finding exact BLE devices. + * @param settings Optional settings for the scan. + * @param callbackIntent The PendingIntent to deliver the result to. + * @return Returns 0 for success or an error code from {@link ScanCallback} if the scan request + * could not be sent. + * @see #stopScan(PendingIntent) + */ + @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + public int startScan(@Nullable List<ScanFilter> filters, @Nullable ScanSettings settings, + @NonNull PendingIntent callbackIntent) { + return startScan(filters, + settings != null ? settings : new ScanSettings.Builder().build(), + null, null, callbackIntent, null); } /** @@ -145,23 +186,23 @@ public final class BluetoothLeScanner { Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS }) public void startScanFromSource(List<ScanFilter> filters, ScanSettings settings, final WorkSource workSource, final ScanCallback callback) { - startScan(filters, settings, workSource, callback, null); + startScan(filters, settings, workSource, callback, null, null); } - private void startScan(List<ScanFilter> filters, ScanSettings settings, + private int startScan(List<ScanFilter> filters, ScanSettings settings, final WorkSource workSource, final ScanCallback callback, + final PendingIntent callbackIntent, List<List<ResultStorageDescriptor>> resultStorages) { BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); - if (callback == null) { + if (callback == null && callbackIntent == null) { throw new IllegalArgumentException("callback is null"); } if (settings == null) { throw new IllegalArgumentException("settings is null"); } synchronized (mLeScanClients) { - if (mLeScanClients.containsKey(callback)) { + if (callback != null && mLeScanClients.containsKey(callback)) { postCallbackError(callback, ScanCallback.SCAN_FAILED_ALREADY_STARTED); - return; } IBluetoothGatt gatt; try { @@ -170,28 +211,34 @@ public final class BluetoothLeScanner { gatt = null; } if (gatt == null) { - postCallbackError(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR); - return; + return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR); } if (!isSettingsConfigAllowedForScan(settings)) { - postCallbackError(callback, - ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); - return; + return postCallbackErrorOrReturn(callback, + ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); } if (!isHardwareResourcesAvailableForScan(settings)) { - postCallbackError(callback, - ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES); - return; + return postCallbackErrorOrReturn(callback, + ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES); } if (!isSettingsAndFilterComboAllowed(settings, filters)) { - postCallbackError(callback, + return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); - return; } - BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters, - settings, workSource, callback, resultStorages); - wrapper.startRegisteration(); + if (callback != null) { + BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters, + settings, workSource, callback, resultStorages); + wrapper.startRegistration(); + } else { + try { + gatt.startScanForIntent(callbackIntent, settings, filters, + ActivityThread.currentOpPackageName()); + } catch (RemoteException e) { + return ScanCallback.SCAN_FAILED_INTERNAL_ERROR; + } + } } + return ScanCallback.NO_ERROR; } /** @@ -215,6 +262,25 @@ public final class BluetoothLeScanner { } /** + * Stops an ongoing Bluetooth LE scan started using a PendingIntent. + * <p> + * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. + * + * @param callbackIntent The PendingIntent that was used to start the scan. + * @see #startScan(List, ScanSettings, PendingIntent) + */ + @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) + public void stopScan(PendingIntent callbackIntent) { + BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); + IBluetoothGatt gatt; + try { + gatt = mBluetoothManager.getBluetoothGatt(); + gatt.stopScanForIntent(callbackIntent, ActivityThread.currentOpPackageName()); + } catch (RemoteException e) { + } + } + + /** * Flush pending batch scan results stored in Bluetooth controller. This will return Bluetooth * LE scan results batched on bluetooth controller. Returns immediately, batch scan results data * will be delivered through the {@code callback}. @@ -252,7 +318,7 @@ public final class BluetoothLeScanner { scanFilters.add(filter.getFilter()); scanStorages.add(filter.getStorageDescriptors()); } - startScan(scanFilters, settings, null, callback, scanStorages); + startScan(scanFilters, settings, null, callback, null, scanStorages); } /** @@ -295,7 +361,7 @@ public final class BluetoothLeScanner { mResultStorages = resultStorages; } - public void startRegisteration() { + public void startRegistration() { synchronized (this) { // Scan stopped. if (mScannerId == -1) return; @@ -399,7 +465,6 @@ public final class BluetoothLeScanner { mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult); } }); - } @Override @@ -453,6 +518,15 @@ public final class BluetoothLeScanner { } } + private int postCallbackErrorOrReturn(final ScanCallback callback, final int errorCode) { + if (callback == null) { + return errorCode; + } else { + postCallbackError(callback, errorCode); + return ScanCallback.NO_ERROR; + } + } + private void postCallbackError(final ScanCallback callback, final int errorCode) { mHandler.post(new Runnable() { @Override diff --git a/core/java/android/bluetooth/le/ScanCallback.java b/core/java/android/bluetooth/le/ScanCallback.java index 61b2e787c86c..aff2e9095024 100644 --- a/core/java/android/bluetooth/le/ScanCallback.java +++ b/core/java/android/bluetooth/le/ScanCallback.java @@ -50,6 +50,8 @@ public abstract class ScanCallback { */ public static final int SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES = 5; + static final int NO_ERROR = 0; + /** * Callback when a BLE advertisement has been found. * diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java index 745cd16c78f9..5b2fa406cd3f 100644 --- a/core/java/android/bluetooth/le/ScanResult.java +++ b/core/java/android/bluetooth/le/ScanResult.java @@ -47,21 +47,6 @@ public final class ScanResult implements Parcelable { 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 @@ public final class ScanResult implements Parcelable { 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 @@ public final class ScanResult implements Parcelable { /** * 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 69c9a8cece3a..36e48e9bd0b8 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 final class ScanSettings implements Parcelable { 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 @@ public final class ScanSettings implements Parcelable { * 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/companion/BluetoothDeviceFilterUtils.java b/core/java/android/companion/BluetoothDeviceFilterUtils.java index 8a316f19af8e..3665d1b85bcb 100644 --- a/core/java/android/companion/BluetoothDeviceFilterUtils.java +++ b/core/java/android/companion/BluetoothDeviceFilterUtils.java @@ -37,7 +37,7 @@ public class BluetoothDeviceFilterUtils { private BluetoothDeviceFilterUtils() {} private static final boolean DEBUG = false; - private static final String LOG_TAG = "BluetoothDeviceFilterUtil"; + private static final String LOG_TAG = "BluetoothDeviceFilterUtils"; @Nullable static String patternToString(@Nullable Pattern p) { @@ -50,8 +50,10 @@ public class BluetoothDeviceFilterUtils { } static boolean matches(ScanFilter filter, BluetoothDevice device) { - return matchesAddress(filter.getDeviceAddress(), device) + boolean result = matchesAddress(filter.getDeviceAddress(), device) && matchesServiceUuid(filter.getServiceUuid(), filter.getServiceUuidMask(), device); + if (DEBUG) debugLogMatchResult(result, device, filter); + return result; } static boolean matchesAddress(String deviceAddress, BluetoothDevice device) { diff --git a/core/java/android/companion/BluetoothLEDeviceFilter.java b/core/java/android/companion/BluetoothLEDeviceFilter.java index 0444775871b9..76051d722368 100644 --- a/core/java/android/companion/BluetoothLEDeviceFilter.java +++ b/core/java/android/companion/BluetoothLEDeviceFilter.java @@ -21,6 +21,7 @@ import static android.companion.BluetoothDeviceFilterUtils.patternFromString; import static android.companion.BluetoothDeviceFilterUtils.patternToString; import static com.android.internal.util.Preconditions.checkArgument; +import static com.android.internal.util.Preconditions.checkState; import android.annotation.NonNull; import android.annotation.Nullable; @@ -31,6 +32,7 @@ import android.bluetooth.le.ScanResult; import android.os.Parcel; import android.provider.OneTimeUseBuilder; import android.text.TextUtils; +import android.util.Log; import com.android.internal.util.BitUtils; import com.android.internal.util.ObjectUtils; @@ -47,6 +49,9 @@ import java.util.regex.Pattern; */ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { + private static final boolean DEBUG = false; + private static final String LOG_TAG = "BluetoothLEDeviceFilter"; + private static final int RENAME_PREFIX_LENGTH_LIMIT = 10; private final Pattern mNamePattern; @@ -57,12 +62,14 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { private final String mRenameSuffix; private final int mRenameBytesFrom; private final int mRenameBytesTo; + private final int mRenameNameFrom; + private final int mRenameNameTo; private final boolean mRenameBytesReverseOrder; private BluetoothLEDeviceFilter(Pattern namePattern, ScanFilter scanFilter, byte[] rawDataFilter, byte[] rawDataFilterMask, String renamePrefix, String renameSuffix, int renameBytesFrom, int renameBytesTo, - boolean renameBytesReverseOrder) { + int renameNameFrom, int renameNameTo, boolean renameBytesReverseOrder) { mNamePattern = namePattern; mScanFilter = ObjectUtils.firstNotNull(scanFilter, ScanFilter.EMPTY); mRawDataFilter = rawDataFilter; @@ -71,6 +78,8 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { mRenameSuffix = renameSuffix; mRenameBytesFrom = renameBytesFrom; mRenameBytesTo = renameBytesTo; + mRenameNameFrom = renameNameFrom; + mRenameNameTo = renameNameTo; mRenameBytesReverseOrder = renameBytesReverseOrder; } @@ -129,15 +138,23 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { @Override @Nullable public String getDeviceDisplayName(ScanResult sr) { - if (mRenameBytesFrom < 0) return getDeviceDisplayNameInternal(sr.getDevice()); - final byte[] bytes = sr.getScanRecord().getBytes(); + if (mRenameBytesFrom < 0 && mRenameNameFrom < 0) { + return getDeviceDisplayNameInternal(sr.getDevice()); + } final StringBuilder sb = new StringBuilder(TextUtils.emptyIfNull(mRenamePrefix)); - int startInclusive = mRenameBytesFrom; - int endInclusive = mRenameBytesTo - 1; - int initial = mRenameBytesReverseOrder ? endInclusive : startInclusive; - int step = mRenameBytesReverseOrder ? -1 : 1; - for (int i = initial; startInclusive <= i && i <= endInclusive; i+=step) { - sb.append(Byte.toHexString(bytes[i], true)); + if (mRenameBytesFrom >= 0) { + final byte[] bytes = sr.getScanRecord().getBytes(); + int startInclusive = mRenameBytesFrom; + int endInclusive = mRenameBytesTo - 1; + int initial = mRenameBytesReverseOrder ? endInclusive : startInclusive; + int step = mRenameBytesReverseOrder ? -1 : 1; + for (int i = initial; startInclusive <= i && i <= endInclusive; i += step) { + sb.append(Byte.toHexString(bytes[i], true)); + } + } else { + sb.append( + getDeviceDisplayNameInternal(sr.getDevice()) + .substring(mRenameNameFrom, mRenameNameTo)); } return sb.append(TextUtils.emptyIfNull(mRenameSuffix)).toString(); } @@ -145,9 +162,13 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { /** @hide */ @Override public boolean matches(ScanResult device) { - return matches(device.getDevice()) - && BitUtils.maskedEquals(device.getScanRecord().getBytes(), - mRawDataFilter, mRawDataFilterMask); + boolean result = matches(device.getDevice()) + && (mRawDataFilter == null + || BitUtils.maskedEquals(device.getScanRecord().getBytes(), + mRawDataFilter, mRawDataFilterMask)); + if (DEBUG) Log.i(LOG_TAG, "matches(this = " + this + ", device = " + device + + ") -> " + result); + return result; } private boolean matches(BluetoothDevice device) { @@ -194,6 +215,8 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { dest.writeString(mRenameSuffix); dest.writeInt(mRenameBytesFrom); dest.writeInt(mRenameBytesTo); + dest.writeInt(mRenameNameFrom); + dest.writeInt(mRenameNameTo); dest.writeBoolean(mRenameBytesReverseOrder); } @@ -218,9 +241,16 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { String suffix = in.readString(); int bytesFrom = in.readInt(); int bytesTo = in.readInt(); + int nameFrom = in.readInt(); + int nameTo = in.readInt(); boolean bytesReverseOrder = in.readBoolean(); if (renamePrefix != null) { - builder.setRename(renamePrefix, suffix, bytesFrom, bytesTo, bytesReverseOrder); + if (bytesFrom >= 0) { + builder.setRenameFromBytes(renamePrefix, suffix, bytesFrom, bytesTo, + bytesReverseOrder); + } else { + builder.setRenameFromName(renamePrefix, suffix, nameFrom, nameTo); + } } return builder.build(); } @@ -247,6 +277,8 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { private String mRenameSuffix; private int mRenameBytesFrom = -1; private int mRenameBytesTo; + private int mRenameNameFrom = -1; + private int mRenameNameTo; private boolean mRenameBytesReverseOrder = false; /** @@ -312,17 +344,57 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { * @return self for chaining */ @NonNull - public Builder setRename(@NonNull String prefix, @NonNull String suffix, + public Builder setRenameFromBytes(@NonNull String prefix, @NonNull String suffix, int bytesFrom, int bytesTo, boolean bytesReverseOrder) { - checkNotUsed(); - checkArgument(TextUtils.length(prefix) >= getRenamePrefixLengthLimit(), - "Prefix is too short"); - mRenamePrefix = prefix; - mRenameSuffix = suffix; - checkArgument(bytesFrom < bytesTo, "Byte range must be non-empty"); + checkRenameNotSet(); + checkRangeNotEmpty(bytesFrom, bytesTo); mRenameBytesFrom = bytesFrom; mRenameBytesTo = bytesTo; mRenameBytesReverseOrder = bytesReverseOrder; + return setRename(prefix, suffix); + } + + /** + * Rename the devices shown in the list, using specific characters from the advertised name, + * as well as a custom prefix/suffix around them + * + * Note that the prefix length is limited to {@link #getRenamePrefixLengthLimit} characters + * to ensure that there's enough space to display the byte data + * + * The range of name characters to be displayed cannot be empty + * + * @param prefix to be displayed before the byte data + * @param suffix to be displayed after the byte data + * @param nameFrom the start name character index to be displayed (inclusive) + * @param nameTo the end name character index to be displayed (exclusive) + * @return self for chaining + */ + @NonNull + public Builder setRenameFromName(@NonNull String prefix, @NonNull String suffix, + int nameFrom, int nameTo) { + checkRenameNotSet(); + checkRangeNotEmpty(nameFrom, nameTo); + mRenameNameFrom = nameFrom; + mRenameNameTo = nameTo; + mRenameBytesReverseOrder = false; + return setRename(prefix, suffix); + } + + private void checkRenameNotSet() { + checkState(mRenamePrefix == null, "Renaming rule can only be set once"); + } + + private void checkRangeNotEmpty(int bytesFrom, int bytesTo) { + checkArgument(bytesFrom < bytesTo, "Range must be non-empty"); + } + + @NonNull + private Builder setRename(@NonNull String prefix, @NonNull String suffix) { + checkNotUsed(); + checkArgument(TextUtils.length(prefix) <= getRenamePrefixLengthLimit(), + "Prefix is too long"); + mRenamePrefix = prefix; + mRenameSuffix = suffix; return this; } @@ -334,7 +406,9 @@ public final class BluetoothLEDeviceFilter implements DeviceFilter<ScanResult> { return new BluetoothLEDeviceFilter(mNamePattern, mScanFilter, mRawDataFilter, mRawDataFilterMask, mRenamePrefix, mRenameSuffix, - mRenameBytesFrom, mRenameBytesTo, mRenameBytesReverseOrder); + mRenameBytesFrom, mRenameBytesTo, + mRenameNameFrom, mRenameNameTo, + mRenameBytesReverseOrder); } } } diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java index 4d788e783f34..e50b2a97c2d2 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -22,11 +22,13 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.PendingIntent; +import android.content.ComponentName; import android.content.Context; import android.content.IntentSender; import android.content.pm.PackageManager; import android.os.Handler; import android.os.RemoteException; +import android.service.notification.NotificationListenerService; import android.util.Log; import java.util.Collections; @@ -195,22 +197,47 @@ public final class CompanionDeviceManager { } } - /** @hide */ - public void requestNotificationAccess() { + /** + * Request notification access for the given component. + * + * The given component must follow the protocol specified in {@link NotificationListenerService} + * + * Only components from the same {@link ComponentName#getPackageName package} as the calling app + * are allowed. + * + * Your app must have an association with a device before calling this API + */ + public void requestNotificationAccess(ComponentName component) { if (!checkFeaturePresent()) { return; } - //TODO implement - throw new UnsupportedOperationException("Not yet implemented"); + try { + mService.requestNotificationAccess(component).send(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (PendingIntent.CanceledException e) { + throw new RuntimeException(e); + } } - /** @hide */ - public boolean haveNotificationAccess() { + /** + * Check whether the given component can access the notifications via a + * {@link NotificationListenerService} + * + * Your app must have an association with a device before calling this API + * + * @param component the name of the component + * @return whether the given component has the notification listener permission + */ + public boolean hasNotificationAccess(ComponentName component) { if (!checkFeaturePresent()) { return false; } - //TODO implement - throw new UnsupportedOperationException("Not yet implemented"); + try { + return mService.hasNotificationAccess(component); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } private boolean checkFeaturePresent() { diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl index 6bbb58da9938..5f73e551d57c 100644 --- a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl +++ b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl @@ -19,4 +19,5 @@ package android.companion; /** @hide */ interface ICompanionDeviceDiscoveryServiceCallback { oneway void onDeviceSelected(String packageName, int userId, String deviceAddress); + oneway void onDeviceSelectionCancel(); } diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl index 7798406c35e5..d3952084116c 100644 --- a/core/java/android/companion/ICompanionDeviceManager.aidl +++ b/core/java/android/companion/ICompanionDeviceManager.aidl @@ -16,8 +16,10 @@ package android.companion; +import android.app.PendingIntent; import android.companion.IFindDeviceCallback; import android.companion.AssociationRequest; +import android.content.ComponentName; /** * Interface for communication with the core companion device manager service. @@ -32,7 +34,6 @@ interface ICompanionDeviceManager { List<String> getAssociations(String callingPackage, int userId); void disassociate(String deviceMacAddress, String callingPackage); - //TODO add these -// boolean haveNotificationAccess(String packageName); -// oneway void requestNotificationAccess(String packageName); + boolean hasNotificationAccess(in ComponentName component); + PendingIntent requestNotificationAccess(in ComponentName component); } diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java index 2f87633a39d3..d428a3a857b7 100644 --- a/core/java/android/content/ContentProviderNative.java +++ b/core/java/android/content/ContentProviderNative.java @@ -24,7 +24,6 @@ import android.database.Cursor; 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 @@ abstract public class ContentProviderNative extends Binder implements IContentPr 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 88bade1691a6..18120c714793 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2745,7 +2745,8 @@ public abstract class Context { * {@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 @@ public abstract class Context { 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 @@ public abstract class Context { /** * 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 b382cef39145..5ca4fa343271 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -657,6 +657,16 @@ public class Intent implements Parcelable, Cloneable { 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 class Intent implements Parcelable, Cloneable { 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 @@ public class Intent implements Parcelable, Cloneable { * <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 @@ public class Intent implements Parcelable, Cloneable { @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 @@ public class Intent implements Parcelable, Cloneable { @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. @@ -3382,11 +3423,11 @@ public class Intent implements Parcelable, Cloneable { 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. + * @hide */ @Deprecated + @SystemApi public static final String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR"; /** diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 147df763fce2..bbc942aff372 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -632,4 +632,6 @@ interface IPackageManager { void deletePreloadsFileCache(); ComponentName getInstantAppResolverSettingsComponent(); + + ComponentName getInstantAppInstallerComponent(); } diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index 4d767555e3b3..c3bdde51af0f 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -275,10 +275,6 @@ public class LauncherApps { @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 @@ public class LauncherApps { 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/PackageManager.java b/core/java/android/content/pm/PackageManager.java index fa3e4e98b551..09906be7cd26 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1763,6 +1763,17 @@ public abstract class PackageManager { /** * 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 @@ public abstract class PackageManager { /** * 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 @@ public abstract class PackageManager { * @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(); @@ -6255,9 +6275,19 @@ public abstract class PackageManager { * Return the {@link ComponentName} of the activity providing Settings for the Instant App * resolver. * - * @see {@link android.content.intent#ACTION_INSTANT_APP_RESOLVER_SETTINGS} + * @see {@link android.content.Intent#ACTION_INSTANT_APP_RESOLVER_SETTINGS} * @hide */ @SystemApi public abstract ComponentName getInstantAppResolverSettingsComponent(); + + /** + * Return the {@link ComponentName} of the activity responsible for installing instant + * applications. + * + * @see {@link android.content.Intent#ACTION_INSTALL_INSTANT_APP_PACKAGE} + * @hide + */ + @SystemApi + public abstract ComponentName getInstantAppInstallerComponent(); } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index e64b2a56a277..430d8b15216f 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -3363,7 +3363,12 @@ public class PackageParser { 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; + } } } @@ -4268,7 +4273,7 @@ public class PackageParser { 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; } @@ -4301,7 +4306,7 @@ public class PackageParser { 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; } @@ -4629,7 +4634,7 @@ public class PackageParser { + 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 @@ -4831,7 +4836,7 @@ public class PackageParser { } 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; } @@ -5136,7 +5141,7 @@ public class PackageParser { 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; } @@ -5177,8 +5182,11 @@ public class PackageParser { 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, diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java index 3f4a09072540..2b76ae20b80b 100644 --- a/core/java/android/content/pm/ShortcutInfo.java +++ b/core/java/android/content/pm/ShortcutInfo.java @@ -1032,20 +1032,6 @@ public final class ShortcutInfo implements Parcelable { 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 @@ public final class ShortcutInfo implements Parcelable { 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 @@ public final class ShortcutInfo implements Parcelable { 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 a46db06ebdc0..faf238164a09 100644 --- a/core/java/android/content/res/ColorStateList.java +++ b/core/java/android/content/res/ColorStateList.java @@ -91,7 +91,7 @@ import java.util.Arrays; * 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 @@ public class ColorStateList extends ComplexColor implements Parcelable { } /** + * 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 c8353c9bffb9..88c1627f955b 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -127,7 +127,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration */ 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 3693bce91d70..408bee8a0223 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -1450,7 +1450,8 @@ public class Resources { * <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 @@ public class Resources { * 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 @@ public class Resources { * 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 @@ public class Resources { * @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 @@ public class Resources { * 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 4569a2765f51..000000000000 --- 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 0218cb5f3058..a895f820789c 100644 --- a/core/java/android/hardware/Sensor.java +++ b/core/java/android/hardware/Sensor.java @@ -836,16 +836,16 @@ public final class Sensor { } /** - * 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 a65d57daa12c..bd7f9cf60126 100644 --- a/core/java/android/hardware/SensorDirectChannel.java +++ b/core/java/android/hardware/SensorDirectChannel.java @@ -23,26 +23,31 @@ import dalvik.system.CloseGuard; 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 @@ public final class SensorDirectChannel implements AutoCloseable { /** * 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 @@ public final class SensorDirectChannel implements AutoCloseable { * 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 @@ public final class SensorDirectChannel implements AutoCloseable { * 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 @@ public final class SensorDirectChannel implements AutoCloseable { * 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 @@ public final class SensorDirectChannel implements AutoCloseable { * * @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 @@ public final class SensorDirectChannel implements AutoCloseable { */ @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 1dc64784c837..ed563914a46e 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -882,7 +882,12 @@ public abstract class SensorManager { /** - * 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 @@ public abstract class SensorManager { * * @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 @@ public abstract class SensorManager { } /** - * 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 @@ public abstract class SensorManager { * @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 @@ public abstract class SensorManager { /** @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 067717905518..10c4cb3df89c 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -35,6 +35,7 @@ import dalvik.system.CloseGuard; 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 @@ public class SystemSensorManager extends SensorManager { /** @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 @@ public class SystemSensorManager extends SensorManager { /** @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 @@ public class SystemSensorManager extends SensorManager { } 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 @@ public class SystemSensorManager extends SensorManager { "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 a529c2ffba3d..32671721f58b 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -247,6 +247,7 @@ public final class DisplayManager { * </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 425a89d7abcb..1e983016aef2 100644 --- a/core/java/android/hardware/usb/UsbDevice.java +++ b/core/java/android/hardware/usb/UsbDevice.java @@ -37,7 +37,7 @@ import com.android.internal.util.Preconditions; * <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 37ca4b44a1a1..af69f0f8fa74 100644 --- a/core/java/android/inputmethodservice/ExtractEditLayout.java +++ b/core/java/android/inputmethodservice/ExtractEditLayout.java @@ -41,6 +41,6 @@ public class ExtractEditLayout extends LinearLayout { @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 d8768e7276f6..5be977ae183d 100644 --- a/core/java/android/metrics/MetricsReader.java +++ b/core/java/android/metrics/MetricsReader.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.Queue; +import java.util.concurrent.TimeUnit; /** * Read platform logs. @@ -80,7 +81,7 @@ public class MetricsReader { 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 @@ public class MetricsReader { */ @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 @@ public class MetricsReader { 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 63ccaaea14cf..46bb34670611 100644 --- a/core/java/android/net/ConnectivityMetricsEvent.java +++ b/core/java/android/net/ConnectivityMetricsEvent.java @@ -18,6 +18,7 @@ package android.net; 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 final class ConnectivityMetricsEvent implements Parcelable { 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 7fea4a25cab7..ce7894fb3ba1 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -32,7 +32,7 @@ public final class IpSecAlgorithm implements Parcelable { * * <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 @@ public final class IpSecAlgorithm implements Parcelable { * * <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 @@ public final class IpSecAlgorithm implements Parcelable { * * <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 @@ public final class IpSecAlgorithm implements Parcelable { 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 6852beb06529..f8702e2e00e7 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -193,15 +193,44 @@ public final class IpSecManager { * * @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 @@ public final class IpSecManager { } /** + * 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 @@ public final class IpSecManager { 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/MatchAllNetworkSpecifier.java b/core/java/android/net/MatchAllNetworkSpecifier.java new file mode 100644 index 000000000000..7aafc93bb4a1 --- /dev/null +++ b/core/java/android/net/MatchAllNetworkSpecifier.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * MatchAllNetworkSpecifier is a marker class used by NetworkFactory classes to indicate + * that they accept (match) any network specifier in requests. + * + * The class must never be used as part of a network request (those semantics aren't specified). + * + * @hide + */ +public final class MatchAllNetworkSpecifier extends NetworkSpecifier implements Parcelable { + /** + * Utility method which verifies that the ns argument is not a MatchAllNetworkSpecifier and + * throws an IllegalArgumentException if it is. + */ + public static void checkNotMatchAllNetworkSpecifier(NetworkSpecifier ns) { + if (ns instanceof MatchAllNetworkSpecifier) { + throw new IllegalArgumentException("A MatchAllNetworkSpecifier is not permitted"); + } + } + + public boolean satisfiedBy(NetworkSpecifier other) { + /* + * The method is called by a NetworkRequest to see if it is satisfied by a proposed + * network (e.g. as offered by a network factory). Since MatchAllNetweorkSpecifier must + * not be used in network requests this method should never be called. + */ + throw new IllegalStateException( + "MatchAllNetworkSpecifier must not be used in NetworkRequests"); + } + + @Override + public boolean equals(Object o) { + return o instanceof MatchAllNetworkSpecifier; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + // Nothing to write. + } + + public static final Parcelable.Creator<MatchAllNetworkSpecifier> CREATOR = + new Parcelable.Creator<MatchAllNetworkSpecifier>() { + public MatchAllNetworkSpecifier createFromParcel(Parcel in) { + return new MatchAllNetworkSpecifier(); + } + public MatchAllNetworkSpecifier[] newArray(int size) { + return new MatchAllNetworkSpecifier[size]; + } + }; +} diff --git a/core/java/android/net/NetworkBadging.java b/core/java/android/net/NetworkBadging.java index 4409d0a4ce73..b4ef69542bd1 100644 --- a/core/java/android/net/NetworkBadging.java +++ b/core/java/android/net/NetworkBadging.java @@ -56,7 +56,7 @@ public class NetworkBadging { * * @param signalLevel The level returned by {@link WifiManager#calculateSignalLevel(int, int)} * for a network. Must be between 0 and {@link WifiManager#RSSI_LEVELS}-1. - * @param badging {@see ScoredNetwork#Badging}, retrieved from + * @param badging {@see NetworkBadging#Badging}, retrieved from * {@link ScoredNetwork#calculateBadge(int)}. * @param theme The theme for the current application, may be null. * @return Drawable for the given icon @@ -140,7 +140,7 @@ public class NetworkBadging { * <p>This badge should be displayed with the badge signal resource retrieved from * {@link #getBadgedWifiSignalResource(int)}. * - * @param badging {@see ScoredNetwork#Badging} from {@link ScoredNetwork#calculateBadge(int)}. + * @param badging {@see NetworkBadging#Badging} from {@link ScoredNetwork#calculateBadge(int)}. * @return the @DrawableRes for the icon or {@link View#NO_ID} for * {@link NetworkBadging#BADGING_NONE} * @throws IllegalArgumentException for an invalid badging value. diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 8665b9c5cf52..afca0b0e0bd3 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -18,8 +18,10 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; -import android.text.TextUtils; -import java.lang.IllegalArgumentException; + +import com.android.internal.util.BitUtils; + +import java.util.Objects; /** * This class represents the capabilities of a network. This is used both to specify @@ -33,6 +35,8 @@ import java.lang.IllegalArgumentException; * all cellular based connections are metered and all Wi-Fi based connections are not. */ public final class NetworkCapabilities implements Parcelable { + private static final String TAG = "NetworkCapabilities"; + /** * @hide */ @@ -205,19 +209,6 @@ public final class NetworkCapabilities implements Parcelable { (1 << NET_CAPABILITY_FOREGROUND); /** - * Network specifier for factories which want to match any network specifier - * (NS) in a request. Behavior: - * <li>Empty NS in request matches any network factory NS</li> - * <li>Empty NS in the network factory NS only matches a request with an - * empty NS</li> - * <li>"*" (this constant) NS in the network factory matches requests with - * any NS</li> - * - * @hide - */ - public static final String MATCH_ALL_REQUESTS_NETWORK_SPECIFIER = "*"; - - /** * Network capabilities that are not allowed in NetworkRequests. This exists because the * NetworkFactory / NetworkAgent model does not deal well with the situation where a * capability's presence cannot be known in advance. If such a capability is requested, then we @@ -289,7 +280,7 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public int[] getCapabilities() { - return enumerateBits(mNetworkCapabilities); + return BitUtils.unpackBits(mNetworkCapabilities); } /** @@ -305,19 +296,6 @@ public final class NetworkCapabilities implements Parcelable { 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 +406,15 @@ public final class NetworkCapabilities implements Parcelable { /** @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 +461,7 @@ public final class NetworkCapabilities implements Parcelable { * @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); } /** @@ -594,63 +570,56 @@ public final class NetworkCapabilities implements Parcelable { this.mLinkDownBandwidthKbps == nc.mLinkDownBandwidthKbps); } - private String mNetworkSpecifier; + private NetworkSpecifier mNetworkSpecifier = null; + /** * Sets the optional bearer specific network specifier. * This has no meaning if a single transport is also not specified, so calling * this without a single transport set will generate an exception, as will * subsequently adding or removing transports after this is set. * </p> - * The interpretation of this {@code String} is bearer specific and bearers that use - * it should document their particulars. For example, Bluetooth may use some sort of - * device id while WiFi could used SSID and/or BSSID. Cellular may use carrier SPN (name) - * or Subscription ID. * - * @param networkSpecifier An {@code String} of opaque format used to specify the bearer - * specific network specifier where the bearer has a choice of - * networks. + * @param networkSpecifier A concrete, parcelable framework class that extends + * NetworkSpecifier. * @return This NetworkCapabilities instance, to facilitate chaining. * @hide */ - public NetworkCapabilities setNetworkSpecifier(String networkSpecifier) { - if (TextUtils.isEmpty(networkSpecifier) == false && Long.bitCount(mTransportTypes) != 1) { + public NetworkCapabilities setNetworkSpecifier(NetworkSpecifier networkSpecifier) { + if (networkSpecifier != null && Long.bitCount(mTransportTypes) != 1) { throw new IllegalStateException("Must have a single transport specified to use " + "setNetworkSpecifier"); } + mNetworkSpecifier = networkSpecifier; + return this; } /** * Gets the optional bearer specific network specifier. * - * @return The optional {@code String} specifying the bearer specific network specifier. - * See {@link #setNetworkSpecifier}. + * @return The optional {@link NetworkSpecifier} specifying the bearer specific network + * specifier. See {@link #setNetworkSpecifier}. * @hide */ - public String getNetworkSpecifier() { + public NetworkSpecifier getNetworkSpecifier() { return mNetworkSpecifier; } private void combineSpecifiers(NetworkCapabilities nc) { - String otherSpecifier = nc.getNetworkSpecifier(); - if (TextUtils.isEmpty(otherSpecifier)) return; - if (TextUtils.isEmpty(mNetworkSpecifier) == false) { + if (mNetworkSpecifier != null && !mNetworkSpecifier.equals(nc.mNetworkSpecifier)) { throw new IllegalStateException("Can't combine two networkSpecifiers"); } - setNetworkSpecifier(otherSpecifier); + setNetworkSpecifier(nc.mNetworkSpecifier); } + private boolean satisfiedBySpecifier(NetworkCapabilities nc) { - return (TextUtils.isEmpty(mNetworkSpecifier) || - mNetworkSpecifier.equals(nc.mNetworkSpecifier) || - MATCH_ALL_REQUESTS_NETWORK_SPECIFIER.equals(nc.mNetworkSpecifier)); + return mNetworkSpecifier == null || mNetworkSpecifier.satisfiedBy(nc.mNetworkSpecifier) + || nc.mNetworkSpecifier instanceof MatchAllNetworkSpecifier; } + private boolean equalsSpecifier(NetworkCapabilities nc) { - if (TextUtils.isEmpty(mNetworkSpecifier)) { - return TextUtils.isEmpty(nc.mNetworkSpecifier); - } else { - return mNetworkSpecifier.equals(nc.mNetworkSpecifier); - } + return Objects.equals(mNetworkSpecifier, nc.mNetworkSpecifier); } /** @@ -812,7 +781,7 @@ public final class NetworkCapabilities implements Parcelable { ((int)(mTransportTypes >> 32) * 7) + (mLinkUpBandwidthKbps * 11) + (mLinkDownBandwidthKbps * 13) + - (TextUtils.isEmpty(mNetworkSpecifier) ? 0 : mNetworkSpecifier.hashCode() * 17) + + Objects.hashCode(mNetworkSpecifier) * 17 + (mSignalStrength * 19)); } @@ -826,7 +795,7 @@ public final class NetworkCapabilities implements Parcelable { dest.writeLong(mTransportTypes); dest.writeInt(mLinkUpBandwidthKbps); dest.writeInt(mLinkDownBandwidthKbps); - dest.writeString(mNetworkSpecifier); + dest.writeParcelable((Parcelable) mNetworkSpecifier, flags); dest.writeInt(mSignalStrength); } @@ -840,7 +809,7 @@ public final class NetworkCapabilities implements Parcelable { netCap.mTransportTypes = in.readLong(); netCap.mLinkUpBandwidthKbps = in.readInt(); netCap.mLinkDownBandwidthKbps = in.readInt(); - netCap.mNetworkSpecifier = in.readString(); + netCap.mNetworkSpecifier = in.readParcelable(null); netCap.mSignalStrength = in.readInt(); return netCap; } @@ -899,18 +868,23 @@ public final class NetworkCapabilities implements Parcelable { * @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 ""; + } + 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 transports; + return TRANSPORT_NAMES[transport]; } } diff --git a/core/java/android/net/NetworkRecommendationProvider.java b/core/java/android/net/NetworkRecommendationProvider.java index 271b0a7c7507..af0459d63718 100644 --- a/core/java/android/net/NetworkRecommendationProvider.java +++ b/core/java/android/net/NetworkRecommendationProvider.java @@ -20,6 +20,19 @@ import java.util.concurrent.atomic.AtomicBoolean; /** * 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/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index cb780090c46a..95a8bb472939 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -18,6 +18,7 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; +import android.text.TextUtils; import java.util.Objects; @@ -259,10 +260,27 @@ public class NetworkRequest implements Parcelable { * networks. */ public Builder setNetworkSpecifier(String networkSpecifier) { - if (NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER.equals(networkSpecifier)) { - throw new IllegalArgumentException("Invalid network specifier - must not be '" - + NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER + "'"); - } + /* + * A StringNetworkSpecifier does not accept null or empty ("") strings. When network + * specifiers were strings a null string and an empty string were considered equivalent. + * Hence no meaning is attached to a null or empty ("") string. + */ + return setNetworkSpecifier(TextUtils.isEmpty(networkSpecifier) ? null + : new StringNetworkSpecifier(networkSpecifier)); + } + + /** + * Sets the optional bearer specific network specifier. + * This has no meaning if a single transport is also not specified, so calling + * this without a single transport set will generate an exception, as will + * subsequently adding or removing transports after this is set. + * </p> + * + * @param networkSpecifier A concrete, parcelable framework class that extends + * NetworkSpecifier. + */ + public Builder setNetworkSpecifier(NetworkSpecifier networkSpecifier) { + MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(networkSpecifier); mNetworkCapabilities.setNetworkSpecifier(networkSpecifier); return this; } diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java new file mode 100644 index 000000000000..87a2b05a4430 --- /dev/null +++ b/core/java/android/net/NetworkSpecifier.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** + * Describes specific properties of a network for use in a {@link NetworkRequest}. + * + * Applications cannot instantiate this class by themselves, but can obtain instances of + * subclasses of this class via other APIs. + */ +public abstract class NetworkSpecifier { + /** @hide */ + public NetworkSpecifier() {} + + /** + * Returns true if a request with this {@link NetworkSpecifier} is satisfied by a network + * with the given NetworkSpecifier. + * + * @hide + */ + public abstract boolean satisfiedBy(NetworkSpecifier other); +} diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java index a664a8bf1ac1..666da0a455fa 100644 --- a/core/java/android/net/ScoredNetwork.java +++ b/core/java/android/net/ScoredNetwork.java @@ -73,29 +73,6 @@ public class ScoredNetwork implements Parcelable { /** A {@link NetworkKey} uniquely identifying this network. */ public final NetworkKey networkKey; - // TODO(b/35323372): Delete these once external references are switched. - /** @deprecated Use {@link NetworkBadging#Badging} instead. */ - @Deprecated - @IntDef({BADGING_NONE, BADGING_SD, BADGING_HD, BADGING_4K}) - @Retention(RetentionPolicy.SOURCE) - public @interface Badging {} - - /** @deprecated Use {@link NetworkBadging#BADGING_NONE} instead. */ - @Deprecated - public static final int BADGING_NONE = 0; - - /** @deprecated Use {@link NetworkBadging#BADGING_SD} instead. */ - @Deprecated - public static final int BADGING_SD = 10; - - /** @deprecated Use {@link NetworkBadging#BADGING_HD} instead. */ - @Deprecated - public static final int BADGING_HD = 20; - - /** @deprecated Use {@link NetworkBadging#BADGING_4K} instead. */ - @Deprecated - public static final int BADGING_4K = 30; - /** * The {@link RssiCurve} representing the scores for this network based on the RSSI. * diff --git a/core/java/android/net/StringNetworkSpecifier.java b/core/java/android/net/StringNetworkSpecifier.java new file mode 100644 index 000000000000..cb7f6bfce713 --- /dev/null +++ b/core/java/android/net/StringNetworkSpecifier.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import com.android.internal.util.Preconditions; + +import java.util.Objects; + +/** @hide */ +public final class StringNetworkSpecifier extends NetworkSpecifier implements Parcelable { + /** + * Arbitrary string used to pass (additional) information to the network factory. + */ + public final String specifier; + + public StringNetworkSpecifier(String specifier) { + Preconditions.checkStringNotEmpty(specifier); + this.specifier = specifier; + } + + @Override + public boolean satisfiedBy(NetworkSpecifier other) { + return equals(other); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof StringNetworkSpecifier)) return false; + return TextUtils.equals(specifier, ((StringNetworkSpecifier) o).specifier); + } + + @Override + public int hashCode() { + return Objects.hashCode(specifier); + } + + @Override + public String toString() { + return specifier; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(specifier); + } + + public static final Parcelable.Creator<StringNetworkSpecifier> CREATOR = + new Parcelable.Creator<StringNetworkSpecifier>() { + public StringNetworkSpecifier createFromParcel(Parcel in) { + return new StringNetworkSpecifier(in.readString()); + } + public StringNetworkSpecifier[] newArray(int size) { + return new StringNetworkSpecifier[size]; + } + }; +} diff --git a/core/java/android/net/metrics/ConnectStats.java b/core/java/android/net/metrics/ConnectStats.java index 214edeeb5382..30b2656227d0 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 @@ public class ConnectStats { } private void countConnect(int errno, String ipAddr) { - mConnectCount++; + connectCount++; if (!isNonBlocking(errno)) { - mConnectBlockingCount++; + connectBlockingCount++; } if (isIPv6(ipAddr)) { - mIpv6ConnectCount++; + ipv6ConnectCount++; } } @@ -91,16 +85,16 @@ public class ConnectStats { // 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 @@ public class ConnectStats { 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 89ae1c258ee6..a4970e4d0d28 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 { + + private static final int SIZE_LIMIT = 20000; - // The event type is currently only 1 or 2, so we store it as a byte. - public final byte[] eventTypes; + // 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(); - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeInt(netId); - out.writeByteArray(eventTypes); - out.writeByteArray(returnCodes); - out.writeIntArray(latenciesMs); + 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 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); - } - - public static final Parcelable.Creator<DnsEvent> CREATOR = new Parcelable.Creator<DnsEvent>() { - @Override - public DnsEvent createFromParcel(Parcel in) { - return new DnsEvent(in); + StringBuilder builder = new StringBuilder("DnsEvent(").append(netId).append(", "); + for (int t : BitUtils.unpackBits(transports)) { + builder.append(NetworkCapabilities.transportNameOf(t)).append(", "); } - - @Override - public DnsEvent[] newArray(int size) { - return new DnsEvent[size]; - } - }; + return builder.append(eventCount).append(" events)").toString(); + } } diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java index ac727ca2e4db..4e57efa4d47b 100644 --- a/core/java/android/net/metrics/IpConnectivityLog.java +++ b/core/java/android/net/metrics/IpConnectivityLog.java @@ -23,6 +23,7 @@ import android.os.RemoteException; 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 @@ public class IpConnectivityLog { * @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 6f388e27fe6e..65025fb9d337 100644 --- a/core/java/android/os/BaseBundle.java +++ b/core/java/android/os/BaseBundle.java @@ -325,6 +325,23 @@ public class BaseBundle { } /** + * @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 4c6d22ae1c51..832031e16ea6 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -182,7 +182,7 @@ public abstract class BatteryStats implements Parcelable { * 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 class BatteryStats implements Parcelable { 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 @@ public abstract class BatteryStats implements Parcelable { // 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 @@ public abstract class BatteryStats implements Parcelable { 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 @@ public abstract class BatteryStats implements Parcelable { // 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 @@ public abstract class BatteryStats implements Parcelable { 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 @@ public abstract class BatteryStats implements Parcelable { 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/Binder.java b/core/java/android/os/Binder.java index 15bd175949c4..ff0bc69ed325 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -16,9 +16,15 @@ package android.os; +import android.util.ExceptionUtils; import android.util.Log; import android.util.Slog; + import com.android.internal.util.FastPrintWriter; +import com.android.internal.util.FunctionalUtils; +import com.android.internal.util.FunctionalUtils.ThrowingRunnable; +import com.android.internal.util.FunctionalUtils.ThrowingSupplier; + import libcore.io.IoUtils; import java.io.FileDescriptor; @@ -26,7 +32,6 @@ import java.io.FileOutputStream; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.lang.reflect.Modifier; -import java.util.function.Supplier; /** * Base class for a remotable object, the core part of a lightweight @@ -251,14 +256,23 @@ public class Binder implements IBinder { * Convenience method for running the provided action enclosed in * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity} * + * Any exception thrown by the given action will be caught and rethrown after the call to + * {@link #restoreCallingIdentity} + * * @hide */ - public static final void withCleanCallingIdentity(Runnable action) { + public static final void withCleanCallingIdentity(ThrowingRunnable action) { long callingIdentity = clearCallingIdentity(); + Throwable throwableToPropagate = null; try { action.run(); + } catch (Throwable throwable) { + throwableToPropagate = throwable; } finally { restoreCallingIdentity(callingIdentity); + if (throwableToPropagate != null) { + throw ExceptionUtils.propagate(throwableToPropagate); + } } } @@ -266,14 +280,24 @@ public class Binder implements IBinder { * Convenience method for running the provided action enclosed in * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity} returning the result * + * Any exception thrown by the given action will be caught and rethrown after the call to + * {@link #restoreCallingIdentity} + * * @hide */ - public static final <T> T withCleanCallingIdentity(Supplier<T> action) { + public static final <T> T withCleanCallingIdentity(ThrowingSupplier<T> action) { long callingIdentity = clearCallingIdentity(); + Throwable throwableToPropagate = null; try { return action.get(); + } catch (Throwable throwable) { + throwableToPropagate = throwable; + return null; // overridden by throwing in finally block } finally { restoreCallingIdentity(callingIdentity); + if (throwableToPropagate != null) { + throw ExceptionUtils.propagate(throwableToPropagate); + } } } diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 76128e640e33..c3836a38c822 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -315,6 +315,7 @@ public final class Parcel { 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 @@ public final class Parcel { 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 2e9f8d9a6439..e69fb55abe8a 100644 --- a/core/java/android/os/ProxyFileDescriptorCallback.java +++ b/core/java/android/os/ProxyFileDescriptorCallback.java @@ -21,12 +21,14 @@ import android.system.OsConstants; /** * 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 @@ public abstract class ProxyFileDescriptorCallback { /** * 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 @@ public abstract class ProxyFileDescriptorCallback { /** * 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/UserManager.java b/core/java/android/os/UserManager.java index a6bf2d26abb3..6f4c9cf7d7ff 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -682,8 +682,10 @@ public class UserManager { * @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 b1f64218b7b4..c6bbf484e702 100644 --- a/core/java/android/os/Vibrator.java +++ b/core/java/android/os/Vibrator.java @@ -19,6 +19,7 @@ package android.os; 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 @@ import android.media.AudioAttributes; * {@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 @@ public abstract class Vibrator { */ @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 @@ public abstract class Vibrator { */ @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 000000000000..1ef3916a743f --- /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 a702cdb6093c..afc9d78dcbd1 100644 --- a/core/java/android/os/health/UidHealthStats.java +++ b/core/java/android/os/health/UidHealthStats.java @@ -445,7 +445,10 @@ public final class UidHealthStats { /** * 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 4deb4ab69059..e9ef770212c8 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.database.Cursor; 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 android.util.Log; 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 class FontsContract { 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 @@ public class FontsContract { * @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 @@ public class FontsContract { 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 @@ public class FontsContract { 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 @@ public class FontsContract { } 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 @@ public class FontsContract { 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 @@ public class FontsContract { 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 @@ public class FontsContract { 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 @@ public class FontsContract { /** @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 cac643fc8b5f..539559d19c82 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -302,8 +302,8 @@ public final class Settings { * 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 final class Settings { 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 @@ public final class Settings { }; /** + * @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 @@ public final class Settings { 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 @@ public final class Settings { * * @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 @@ public final class Settings { 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 final class Settings { 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 @@ public final class Settings { 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/provider/SettingsStringUtil.java b/core/java/android/provider/SettingsStringUtil.java index 3dfedea18323..a3dc9471a1d0 100644 --- a/core/java/android/provider/SettingsStringUtil.java +++ b/core/java/android/provider/SettingsStringUtil.java @@ -23,6 +23,7 @@ import android.text.TextUtils; import com.android.internal.util.ArrayUtils; +import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.function.Function; @@ -80,6 +81,12 @@ public class SettingsStringUtil { return s; } + public static String addAll(String delimitedElements, Collection<String> elements) { + final ColonDelimitedSet<String> set + = new ColonDelimitedSet.OfStrings(delimitedElements); + return set.addAll(elements) ? set.toString() : delimitedElements; + } + public static String add(String delimitedElements, String element) { final ColonDelimitedSet<String> set = new ColonDelimitedSet.OfStrings(delimitedElements); diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java index a4d3fb299734..5e49b8f0553f 100644 --- a/core/java/android/service/autofill/AutofillService.java +++ b/core/java/android/service/autofill/AutofillService.java @@ -34,6 +34,8 @@ import android.view.autofill.AutofillManager; import com.android.internal.os.SomeArgs; +import java.util.List; + //TODO(b/33197203): improve javadoc (of both class and methods); in particular, make sure the //life-cycle (and how state could be maintained on server-side) is well documented. @@ -103,24 +105,22 @@ public abstract class AutofillService extends Service { } @Override - public void onFillRequest(AssistStructure structure, Bundle extras, - IFillCallback callback, int flags) { + public void onFillRequest(FillRequest request, IFillCallback callback) { ICancellationSignal transport = CancellationSignal.createTransport(); try { callback.onCancellable(transport); } catch (RemoteException e) { e.rethrowFromSystemServer(); } - mHandlerCaller.obtainMessageIIOOOO(MSG_ON_FILL_REQUEST, flags, UNUSED_ARG, structure, - CancellationSignal.fromTransport(transport), extras, callback) + mHandlerCaller.obtainMessageOOO(MSG_ON_FILL_REQUEST, request, + CancellationSignal.fromTransport(transport), callback) .sendToTarget(); } @Override - public void onSaveRequest(AssistStructure structure, Bundle extras, - ISaveCallback callback) { - mHandlerCaller.obtainMessageOOO(MSG_ON_SAVE_REQUEST, structure, - extras, callback).sendToTarget(); + public void onSaveRequest(SaveRequest request, ISaveCallback callback) { + mHandlerCaller.obtainMessageOO(MSG_ON_SAVE_REQUEST, request, + callback).sendToTarget(); } }; @@ -131,23 +131,20 @@ public abstract class AutofillService extends Service { break; } case MSG_ON_FILL_REQUEST: { final SomeArgs args = (SomeArgs) msg.obj; - final AssistStructure structure = (AssistStructure) args.arg1; + final FillRequest request = (FillRequest) args.arg1; final CancellationSignal cancellation = (CancellationSignal) args.arg2; - final Bundle extras = (Bundle) args.arg3; - final IFillCallback callback = (IFillCallback) args.arg4; - final FillCallback fillCallback = new FillCallback(callback); - final int flags = msg.arg1; + final IFillCallback callback = (IFillCallback) args.arg3; + final FillCallback fillCallback = new FillCallback(callback, request.getId()); args.recycle(); - onFillRequest(structure, extras, flags, cancellation, fillCallback); + onFillRequest(request, cancellation, fillCallback); break; } case MSG_ON_SAVE_REQUEST: { final SomeArgs args = (SomeArgs) msg.obj; - final AssistStructure structure = (AssistStructure) args.arg1; - final Bundle extras = (Bundle) args.arg2; - final ISaveCallback callback = (ISaveCallback) args.arg3; + final SaveRequest request = (SaveRequest) args.arg1; + final ISaveCallback callback = (ISaveCallback) args.arg2; final SaveCallback saveCallback = new SaveCallback(callback); args.recycle(); - onSaveRequest(structure, extras, saveCallback); + onSaveRequest(request, saveCallback); break; } case MSG_DISCONNECT: { onDisconnected(); @@ -198,6 +195,28 @@ public abstract class AutofillService extends Service { * or {@link FillCallback#onFailure(CharSequence)}) * to notify the result of the request. * + * @param request the {@link FillRequest request} to handle. + * See {@link FillResponse} for examples of multiple-sections requests. + * @param cancellationSignal signal for observing cancellation requests. The system will use + * this to notify you that the fill result is no longer needed and you should stop + * handling this fill request in order to save resources. + * @param callback object used to notify the result of the request. + */ + public void onFillRequest(@NonNull FillRequest request, + @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback) { + onFillRequest(request.getStructure(), request.getClientState(), request.getFlags(), + cancellationSignal, callback); + } + + /** + * Called by the Android system do decide if an {@link Activity} can be autofilled by the + * service. + * + * <p>Service must call one of the {@link FillCallback} methods (like + * {@link FillCallback#onSuccess(FillResponse)} + * or {@link FillCallback#onFailure(CharSequence)}) + * to notify the result of the request. + * * @param structure {@link Activity}'s view structure. * @param data bundle containing data passed by the service in a last call to * {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your @@ -211,6 +230,7 @@ public abstract class AutofillService extends Service { * handling this fill request in order to save resources. * @param callback object used to notify the result of the request. */ + @Deprecated public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data, int flags, @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback); @@ -222,6 +242,23 @@ public abstract class AutofillService extends Service { * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)}) * to notify the result of the request. * + * @param request the {@link SaveRequest request} to handle. + * See {@link FillResponse} for examples of multiple-sections requests. + * @param callback object used to notify the result of the request. + */ + public void onSaveRequest(@NonNull SaveRequest request, @NonNull SaveCallback callback) { + List<FillContext> contexts = request.getFillContexts(); + onSaveRequest(contexts.get(contexts.size() - 1).getStructure(), + request.getClientState(), callback); + } + + /** + * Called when user requests service to save the fields of an {@link Activity}. + * + * <p>Service must call one of the {@link SaveCallback} methods (like + * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)}) + * to notify the result of the request. + * * @param structure {@link Activity}'s view structure. * @param data bundle containing data passed by the service in a last call to * {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your @@ -231,6 +268,7 @@ public abstract class AutofillService extends Service { * See {@link FillResponse} for examples of multiple-sections requests. * @param callback object used to notify the result of the request. */ + @Deprecated public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data, @NonNull SaveCallback callback); diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java index e8ad14f55261..a009be805ce7 100644 --- a/core/java/android/service/autofill/FillCallback.java +++ b/core/java/android/service/autofill/FillCallback.java @@ -27,11 +27,13 @@ import android.os.RemoteException; */ public final class FillCallback { private final IFillCallback mCallback; + private final int mRequestId; private boolean mCalled; /** @hide */ - public FillCallback(IFillCallback callback) { + public FillCallback(IFillCallback callback, int requestId) { mCallback = callback; + mRequestId = requestId; } /** @@ -47,7 +49,7 @@ public final class FillCallback { assertNotCalled(); mCalled = true; try { - mCallback.onSuccess(response); + mCallback.onSuccess(response, mRequestId); } catch (RemoteException e) { e.rethrowAsRuntimeException(); } diff --git a/core/java/android/service/autofill/FillContext.java b/core/java/android/service/autofill/FillContext.java new file mode 100644 index 000000000000..2efa08c00969 --- /dev/null +++ b/core/java/android/service/autofill/FillContext.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.autofill; + +import android.annotation.NonNull; +import android.app.assist.AssistStructure; +import android.os.Bundle; +import android.os.CancellationSignal; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * This class represents a context for each fill request made via {@link + * AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)}. + * It contains a snapshot of the UI state, the view ids that were returned by + * the {@link AutofillService autofill service} as both required to trigger a save + * and optional that can be saved, and the id of the corresponding {@link + * FillRequest}. + * <p> + * This context allows you to inspect the values for the interesting views + * in the context they appeared. Also a reference to the corresponding fill + * request is useful to store meta-data in the client state bundle passed + * to {@link FillResponse.Builder#setClientState(Bundle)} to avoid interpreting + * the UI state again while saving. + */ +public final class FillContext implements Parcelable { + private final int mRequestId; + private final @NonNull AssistStructure mStructure; + + /** @hide */ + public FillContext(int requestId, @NonNull AssistStructure structure) { + mRequestId = requestId; + mStructure = structure; + } + + private FillContext(Parcel parcel) { + this(parcel.readInt(), parcel.readParcelable(null)); + } + + /** + * Gets the id of the {@link FillRequest fill request} this context + * corresponds to. This is useful to associate your custom client + * state with every request to avoid reinterpreting the UI when saving + * user data. + * + * @return The request id. + */ + public int getRequestId() { + return mRequestId; + } + + /** + * @return The screen content. + */ + public AssistStructure getStructure() { + return mStructure; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(mRequestId); + parcel.writeParcelable(mStructure, flags); + } + + public static final Parcelable.Creator<FillContext> CREATOR = + new Parcelable.Creator<FillContext>() { + @Override + public FillContext createFromParcel(Parcel parcel) { + return new FillContext(parcel); + } + + @Override + public FillContext[] newArray(int size) { + return new FillContext[size]; + } + }; +} diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/core/java/android/service/autofill/FillRequest.aidl index 30355d47e957..2b1a8fea8a5e 100644 --- a/packages/SystemUI/res/values/dimens_tv.xml +++ b/core/java/android/service/autofill/FillRequest.aidl @@ -1,7 +1,5 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * Copyright 2016, The Android Open Source Project +/** + * Copyright (c) 2017, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ ---> -<resources> - <!-- Extra space around the PIP and its outline in PIP onboarding activity --> - <dimen name="tv_pip_bounds_space">3dp</dimen> -</resources> + +package android.service.autofill; + +parcelable FillRequest; diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java new file mode 100644 index 000000000000..aa6db4d092f2 --- /dev/null +++ b/core/java/android/service/autofill/FillRequest.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.autofill; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.assist.AssistStructure; +import android.os.Bundle; +import android.os.CancellationSignal; +import android.os.Parcel; +import android.os.Parcelable; +import com.android.internal.util.Preconditions; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * This class represents a request to an {@link AutofillService autofill provider} + * to interpret the screen and provide information to the system which views are + * interesting for saving and what are the possible ways to fill the inputs on + * the screen if applicable. + * + * @see AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback) + */ +public final class FillRequest implements Parcelable { + private static AtomicInteger sIdCounter = new AtomicInteger(); + + /** + * Indicates autofill was explicitly requested by the user. + */ + public static final int FLAG_MANUAL_REQUEST = 0x1; + + /** @hide */ + @IntDef( + flag = true, + value = {FLAG_MANUAL_REQUEST}) + @Retention(RetentionPolicy.SOURCE) + @interface RequestFlags{} + + private final int mId; + private final @RequestFlags int mFlags; + private final @NonNull AssistStructure mStructure; + private final @Nullable Bundle mClientState; + + /** @hide */ + public FillRequest(@NonNull AssistStructure structure, + @Nullable Bundle clientState, @RequestFlags int flags) { + this(sIdCounter.incrementAndGet(), structure, clientState, flags); + } + + private FillRequest(@NonNull Parcel parcel) { + mId = parcel.readInt(); + mStructure = parcel.readParcelable(null); + mClientState = parcel.readBundle(); + mFlags = parcel.readInt(); + } + + private FillRequest(int id, @NonNull AssistStructure structure, + @Nullable Bundle clientState, @RequestFlags int flags) { + mId = id; + mFlags = Preconditions.checkFlagsArgument(flags, FLAG_MANUAL_REQUEST); + mStructure = Preconditions.checkNotNull(structure, "structure"); + mClientState = clientState; + } + + /** + * @return The unique id of this request. + */ + public int getId() { + return mId; + } + + /** + * @return The flags associated with this request. + * + * @see #FLAG_MANUAL_REQUEST + */ + public @RequestFlags int getFlags() { + return mFlags; + } + + /** + * @return The structure capturing the UI state. + */ + public @NonNull AssistStructure getStructure() { + return mStructure; + } + + /** + * Gets the extra client state returned from the last {@link + * AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback) + * fill request}. + * <p> + * Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback) + * save request} is made the client state is cleared. + * + * @return The client state. + */ + public @Nullable Bundle getClientState() { + return mClientState; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(mId); + parcel.writeParcelable(mStructure, flags); + parcel.writeBundle(mClientState); + parcel.writeInt(mFlags); + } + + public static final Parcelable.Creator<FillRequest> CREATOR = + new Parcelable.Creator<FillRequest>() { + @Override + public FillRequest createFromParcel(Parcel parcel) { + return new FillRequest(parcel); + } + + @Override + public FillRequest[] newArray(int size) { + return new FillRequest[size]; + } + }; +} diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java index 3117f9842b64..8c8060a608f0 100644 --- a/core/java/android/service/autofill/FillResponse.java +++ b/core/java/android/service/autofill/FillResponse.java @@ -132,25 +132,25 @@ import java.util.ArrayList; */ public final class FillResponse implements Parcelable { - private final ArrayList<Dataset> mDatasets; - private final SaveInfo mSaveInfo; - private final Bundle mExtras; - private final RemoteViews mPresentation; - private final IntentSender mAuthentication; - private AutofillId[] mAuthenticationIds; + private final @Nullable ArrayList<Dataset> mDatasets; + private final @Nullable SaveInfo mSaveInfo; + private final @Nullable Bundle mClientState; + private final @Nullable RemoteViews mPresentation; + private final @Nullable IntentSender mAuthentication; + private final @Nullable AutofillId[] mAuthenticationIds; private FillResponse(@NonNull Builder builder) { mDatasets = builder.mDatasets; mSaveInfo = builder.mSaveInfo; - mExtras = builder.mExtras; + mClientState = builder.mCLientState; mPresentation = builder.mPresentation; mAuthentication = builder.mAuthentication; mAuthenticationIds = builder.mAuthenticationIds; } /** @hide */ - public @Nullable Bundle getExtras() { - return mExtras; + public @Nullable Bundle getClientState() { + return mClientState; } /** @hide */ @@ -185,7 +185,7 @@ public final class FillResponse implements Parcelable { public static final class Builder { private ArrayList<Dataset> mDatasets; private SaveInfo mSaveInfo; - private Bundle mExtras; + private Bundle mCLientState; private RemoteViews mPresentation; private IntentSender mAuthentication; private AutofillId[] mAuthenticationIds; @@ -289,27 +289,38 @@ public final class FillResponse implements Parcelable { return this; } + @Deprecated + public Builder setExtras(@Nullable Bundle extras) { + throwIfDestroyed(); + mCLientState = extras; + return this; + } + /** - * Sets a {@link Bundle} that will be passed to subsequent APIs that + * Sets a {@link Bundle state} that will be passed to subsequent APIs that * manipulate this response. For example, they are passed to subsequent * calls to {@link AutofillService#onFillRequest( * android.app.assist.AssistStructure, Bundle, int, * android.os.CancellationSignal, FillCallback)} and {@link AutofillService#onSaveRequest( - * android.app.assist.AssistStructure, Bundle, SaveCallback)}. + * android.app.assist.AssistStructure, Bundle, SaveCallback)}. You can use + * this to store intermediate state that is persistent across multiple + * fill requests and the subsequent save request. * * <p>If this method is called on multiple {@link FillResponse} objects for the same * activity, just the latest bundle is passed back to the service. * - * @param extras The response extras. + * <p>Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback) + * save request} is made the client state is cleared. + * + * @param clientState The custom client state. * @return This builder. */ - public Builder setExtras(Bundle extras) { + public Builder setClientState(@Nullable Bundle clientState) { throwIfDestroyed(); - mExtras = extras; + mCLientState = clientState; 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 @@ -345,7 +356,7 @@ public final class FillResponse implements Parcelable { return new StringBuilder( "FillResponse: [datasets=").append(mDatasets) .append(", saveInfo=").append(mSaveInfo) - .append(", hasExtras=").append(mExtras != null) + .append(", clientState=").append(mClientState != null) .append(", hasPresentation=").append(mPresentation != null) .append(", hasAuthentication=").append(mAuthentication != null) .append(", authenticationSize=").append(mAuthenticationIds != null @@ -366,7 +377,7 @@ public final class FillResponse implements Parcelable { public void writeToParcel(Parcel parcel, int flags) { parcel.writeTypedArrayList(mDatasets, flags); parcel.writeParcelable(mSaveInfo, flags); - parcel.writeParcelable(mExtras, flags); + parcel.writeParcelable(mClientState, flags); parcel.writeParcelableArray(mAuthenticationIds, flags); parcel.writeParcelable(mAuthentication, flags); parcel.writeParcelable(mPresentation, flags); diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl index a8d86ca1cc79..23a1a3fee47c 100644 --- a/core/java/android/service/autofill/IAutoFillService.aidl +++ b/core/java/android/service/autofill/IAutoFillService.aidl @@ -16,10 +16,10 @@ package android.service.autofill; -import android.app.assist.AssistStructure; -import android.os.Bundle; +import android.service.autofill.FillRequest; import android.service.autofill.IFillCallback; import android.service.autofill.ISaveCallback; +import android.service.autofill.SaveRequest; import com.android.internal.os.IResultReceiver; /** @@ -29,8 +29,6 @@ import com.android.internal.os.IResultReceiver; */ oneway interface IAutoFillService { 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, - in ISaveCallback callback); + void onFillRequest(in FillRequest request, in IFillCallback callback); + void onSaveRequest(in SaveRequest request, in ISaveCallback callback); } diff --git a/core/java/android/service/autofill/IFillCallback.aidl b/core/java/android/service/autofill/IFillCallback.aidl index 2bb3e9acd3e1..688ac84b9cd8 100644 --- a/core/java/android/service/autofill/IFillCallback.aidl +++ b/core/java/android/service/autofill/IFillCallback.aidl @@ -27,6 +27,6 @@ import android.service.autofill.FillResponse; */ interface IFillCallback { void onCancellable(in ICancellationSignal cancellation); - void onSuccess(in FillResponse response); + void onSuccess(in FillResponse response, int requestId); void onFailure(CharSequence message); } diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java index 4ad0f086691a..258d257813ca 100644 --- a/core/java/android/service/autofill/SaveInfo.java +++ b/core/java/android/service/autofill/SaveInfo.java @@ -140,7 +140,19 @@ public final class SaveInfo implements Parcelable { */ public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 0x10; - private final int mType; + /** @hide */ + @IntDef( + flag = true, + value = { + SAVE_DATA_TYPE_GENERIC, + SAVE_DATA_TYPE_PASSWORD, + SAVE_DATA_TYPE_ADDRESS, + SAVE_DATA_TYPE_CREDIT_CARD, + SAVE_DATA_TYPE_EMAIL_ADDRESS}) + @Retention(RetentionPolicy.SOURCE) + @interface SaveDataType{} + + private final @SaveDataType int mType; private final CharSequence mNegativeActionTitle; private final IntentSender mNegativeActionListener; private final AutofillId[] mRequiredIds; @@ -177,7 +189,7 @@ public final class SaveInfo implements Parcelable { } /** @hide */ - public int getType() { + public @SaveDataType int getType() { return mType; } @@ -191,7 +203,7 @@ public final class SaveInfo implements Parcelable { */ public static final class Builder { - private final int mType; + private final @SaveDataType int mType; private CharSequence mNegativeActionTitle; private IntentSender mNegativeActionListener; // TODO(b/33197203): make mRequiredIds final once addSavableIds() is gone @@ -215,7 +227,7 @@ public final class SaveInfo implements Parcelable { * * @throws IllegalArgumentException if {@code requiredIds} is {@code null} or empty. */ - public Builder(int type, @NonNull AutofillId[] requiredIds) { + public Builder(@SaveDataType int type, @NonNull AutofillId[] requiredIds) { if (false) {// TODO(b/33197203): re-move when clients use it Preconditions.checkArgument(requiredIds != null && requiredIds.length > 0, "must have at least one required id: " + Arrays.toString(requiredIds)); @@ -230,7 +242,7 @@ public final class SaveInfo implements Parcelable { * // TODO(b/33197203): make sure is removed when clients migrated */ @Deprecated - public Builder(int type) { + public Builder(@SaveDataType int type) { this(type, null); } diff --git a/core/java/android/service/autofill/SaveRequest.aidl b/core/java/android/service/autofill/SaveRequest.aidl new file mode 100644 index 000000000000..7789b577714b --- /dev/null +++ b/core/java/android/service/autofill/SaveRequest.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2017, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.autofill; + +parcelable SaveRequest; diff --git a/core/java/android/service/autofill/SaveRequest.java b/core/java/android/service/autofill/SaveRequest.java new file mode 100644 index 000000000000..9de931542cb9 --- /dev/null +++ b/core/java/android/service/autofill/SaveRequest.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.autofill; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Bundle; +import android.os.CancellationSignal; +import android.os.Parcel; +import android.os.Parcelable; +import com.android.internal.util.Preconditions; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class represents a request to an {@link AutofillService + * autofill provider} to save applicable data entered by the user. + * + * @see AutofillService#onSaveRequest(SaveRequest, SaveCallback) + */ +public final class SaveRequest implements Parcelable { + private final @NonNull ArrayList<FillContext> mFillContexts; + private final @Nullable Bundle mClientState; + + /** @hide */ + public SaveRequest(@NonNull ArrayList<FillContext> fillContexts, + @Nullable Bundle clientState) { + mFillContexts = Preconditions.checkNotNull(fillContexts, "fillContexts"); + mClientState = clientState; + } + + private SaveRequest(@NonNull Parcel parcel) { + this(parcel.readTypedArrayList(null), parcel.readBundle()); + } + + /** + * @return The contexts associated with each previous fill request. + */ + public @NonNull List<FillContext> getFillContexts() { + return mFillContexts; + } + + /** + * Gets the extra client state returned from the last {@link + * AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)} + * fill request}. + * + * @return The client state. + */ + public @Nullable Bundle getClientState() { + return mClientState; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeTypedArrayList(mFillContexts, flags); + parcel.writeBundle(mClientState); + } + + public static final Creator<SaveRequest> CREATOR = + new Creator<SaveRequest>() { + @Override + public SaveRequest createFromParcel(Parcel parcel) { + return new SaveRequest(parcel); + } + + @Override + public SaveRequest[] newArray(int size) { + return new SaveRequest[size]; + } + }; +} diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index 94505d37310d..6a15adeda9ab 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -462,7 +462,7 @@ public class DreamService extends Service implements Window.Callback { * @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 b26e32835aa1..dc1a70d74d7f 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 @@ oneway interface INotificationListener 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 6ec9d69583e3..d94017cdb2bf 100644 --- a/core/java/android/service/notification/NotificationAssistantService.java +++ b/core/java/android/service/notification/NotificationAssistantService.java @@ -138,7 +138,6 @@ public abstract class NotificationAssistantService extends NotificationListenerS } } - 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 f55c7cfb4ba5..4833be335c88 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 android.widget.RemoteViews; import com.android.internal.annotations.GuardedBy; import com.android.internal.os.SomeArgs; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -59,7 +66,7 @@ import java.util.List; * 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 @@ public abstract class NotificationListenerService extends Service { @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 @@ public abstract class NotificationListenerService extends Service { } /** + * 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 @@ public abstract class NotificationListenerService extends Service { } } + + /** + * 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 @@ public abstract class NotificationListenerService extends Service { // 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 abstract class NotificationListenerService extends Service { 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 @@ public abstract class NotificationListenerService extends Service { 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/oemlock/IOemLockService.aidl b/core/java/android/service/oemlock/IOemLockService.aidl new file mode 100644 index 000000000000..2c606f97ab9f --- /dev/null +++ b/core/java/android/service/oemlock/IOemLockService.aidl @@ -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.service.oemlock; + +/** + * Interface for communication with the OemLockService. + * + * @hide + */ +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 000000000000..c4fbe5ec7e1a --- /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 cb021bc03087..326796afb3ad 100644 --- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java +++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java @@ -146,6 +146,8 @@ public class PersistentDataBlockManager { /** * 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 @@ public class PersistentDataBlockManager { /** * 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/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 6bbb0ff9861b..98780a7d73d5 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -16,6 +16,8 @@ package android.service.wallpaper; +import android.annotation.Nullable; +import android.app.WallpaperColors; import android.content.res.TypedArray; import android.graphics.Canvas; import android.util.MergedConfiguration; @@ -542,6 +544,24 @@ public abstract class WallpaperService extends Service { */ public void onSurfaceDestroyed(SurfaceHolder holder) { } + + /** + * Notifies the engine that wallpaper colors changed significantly. + * This will trigger a {@link #onComputeWallpaperColors()} call. + */ + public void invalidateColors() { + } + + /** + * Notifies the system about what colors the wallpaper is using. + * You might return null if no color information is available at the moment. In that case + * you might want to call {@link #invalidateColors()} in a near future. + * + * @return List of wallpaper colors and their weights. + */ + public @Nullable WallpaperColors onComputeWallpaperColors() { + return null; + } protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) { out.print(prefix); out.print("mInitializing="); out.print(mInitializing); diff --git a/core/java/android/speech/tts/SynthesisCallback.java b/core/java/android/speech/tts/SynthesisCallback.java index e535cfab3ab6..f5e5f4d8356c 100644 --- a/core/java/android/speech/tts/SynthesisCallback.java +++ b/core/java/android/speech/tts/SynthesisCallback.java @@ -151,6 +151,9 @@ public interface SynthesisCallback { * 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 59ee8f360c12..ef81f1211364 100644 --- a/core/java/android/speech/tts/UtteranceProgressListener.java +++ b/core/java/android/speech/tts/UtteranceProgressListener.java @@ -128,6 +128,9 @@ public abstract class UtteranceProgressListener { * <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 8537d8f1ea84..ed583907123b 100644 --- a/core/java/android/text/FontConfig.java +++ b/core/java/android/text/FontConfig.java @@ -23,8 +23,6 @@ import android.annotation.NonNull; 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 @@ import java.lang.annotation.Retention; * 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 @@ public final class FontConfig implements Parcelable { } /** - * @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 @@ public final class FontConfig implements Parcelable { 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 final class FontConfig implements Parcelable { 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 final class FontConfig implements Parcelable { 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 b47fce89b0ff..a233ba118e7d 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -1030,24 +1030,17 @@ public abstract class Layout { * 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 @@ public abstract class Layout { * 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 @@ public abstract class Layout { * 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 @@ public abstract class Layout { 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 @@ public abstract class Layout { 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 @@ public abstract class Layout { 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 @@ public abstract class Layout { 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 @@ public abstract class Layout { } } - 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 @@ public abstract class Layout { } } - 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 @@ public abstract class Layout { 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 @@ public abstract class Layout { } 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 5f01f7b61bf1..d41dfdcd29fc 100644 --- a/core/java/android/text/SpannableStringBuilder.java +++ b/core/java/android/text/SpannableStringBuilder.java @@ -98,7 +98,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable 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 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable } 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 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable 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 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable 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 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable 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 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable * 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 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable } } - 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 4b02df86c82e..366ec145ffc4 100644 --- a/core/java/android/text/SpannableStringInternal.java +++ b/core/java/android/text/SpannableStringInternal.java @@ -65,7 +65,7 @@ import java.lang.reflect.Array; 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 @@ import java.lang.reflect.Array; } /* 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/util/Linkify.java b/core/java/android/text/util/Linkify.java index 7e6eb4906c20..0f8515988d1e 100644 --- a/core/java/android/text/util/Linkify.java +++ b/core/java/android/text/util/Linkify.java @@ -88,7 +88,11 @@ public class Linkify { * {@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 b6d8aa449533..546f93a2e97a 100644 --- a/core/java/android/transition/ChangeBounds.java +++ b/core/java/android/transition/ChangeBounds.java @@ -472,9 +472,9 @@ public class ChangeBounds extends Transition { 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 class ChangeBounds extends Transition { 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 class ChangeBounds extends Transition { 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 e5aa2b5b4ce7..89b9646e54b3 100644 --- a/core/java/android/util/LauncherIcons.java +++ b/core/java/android/util/LauncherIcons.java @@ -20,11 +20,8 @@ import android.content.res.Resources; 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 final class LauncherIcons { 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 @@ public final class LauncherIcons { 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 5bc6c9480025..d857bf712bfe 100644 --- a/core/java/android/util/Log.java +++ b/core/java/android/util/Log.java @@ -212,7 +212,9 @@ public final class Log { * @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 051de8a190e1..4bbc0f863603 100644 --- a/core/java/android/util/StateSet.java +++ b/core/java/android/util/StateSet.java @@ -228,6 +228,29 @@ public class StateSet { 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 4ae5a2921547..2c9bb660b149 100644 --- a/core/java/android/util/TypedValue.java +++ b/core/java/android/util/TypedValue.java @@ -187,6 +187,27 @@ public class TypedValue { /** * 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 6dedbde01995..3e9fab1aee27 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -205,6 +205,7 @@ public final class Display { * </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 f3c2421c604a..f47c35580f0f 100644 --- a/core/java/android/view/FocusFinder.java +++ b/core/java/android/view/FocusFinder.java @@ -18,15 +18,17 @@ package android.view; 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 @@ public class FocusFinder { 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 @@ public class FocusFinder { @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 @@ public class FocusFinder { 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 @@ public class FocusFinder { 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; + private Comparator<View> mTopsComparator = (first, second) -> { + if (first == second) { + return 0; + } - public void setIsLayoutRtl(boolean b) { - mIsLayoutRtl = b; - } + Rect firstRect = mRectByView.get(first); + Rect secondRect = mRectByView.get(second); - public void setRoot(ViewGroup root) { - mRoot = root; - } + int result = firstRect.top - secondRect.top; + if (result == 0) { + return firstRect.bottom - secondRect.bottom; + } + return result; + }; - public int compare(View first, View second) { + private Comparator<View> mSidesComparator = (first, second) -> { if (first == second) { return 0; } - getRect(first, mFirstRect); - getRect(second, mSecondRect); - - 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. - return 0; + 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); } - } - private void getRect(View view, Rect rect) { - view.getDrawingRect(rect); - mRoot.offsetDescendantRectToMyCoords(view, rect); + // 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) { + 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 int id = view.getId(); - if (isValidId(id)) { - mFocusables.put(id, view); - } - final int nextId = mNextIdGetter.get(view); - if (isValidId(nextId)) { - mIsConnectedTo.put(nextId, true); + 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 int nextId = mNextIdGetter.get(view); - if (isValidId(nextId) && !mIsConnectedTo.get(view.getId())) { + final View next = mNextFoci.get(view); + if (next != null && !mIsConnectedTo.contains(view)) { setHeadOfChain(view); } } - - for (int i = 0; i < focusables.size(); ++i) { - mOriginalOrdinal.put(focusables.get(i), i); - } } 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 @@ public class FocusFinder { 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 fe9197867484..20f7acebf6e5 100644 --- a/core/java/android/view/NotificationHeaderView.java +++ b/core/java/android/view/NotificationHeaderView.java @@ -94,8 +94,8 @@ public class NotificationHeaderView extends ViewGroup { 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 1cb563f0a87a..3b1545696347 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -55,6 +55,8 @@ public class SurfaceControl { 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 @@ public class SurfaceControl { 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 076b33cc9d6a..1a71679449a4 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -93,7 +93,7 @@ import java.util.concurrent.locks.ReentrantLock; * 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 @@ public class SurfaceView extends View { 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 @@ public class SurfaceView extends View { 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 @@ public class SurfaceView extends View { protected void onWindowVisibilityChanged(int visibility) { super.onWindowVisibilityChanged(visibility); mWindowVisibility = visibility == VISIBLE; - mRequestedVisible = mWindowVisibility && mViewVisibility; + updateRequestedVisibility(); updateSurface(); } @@ -254,7 +271,7 @@ public class SurfaceView extends View { 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 @@ public class SurfaceView extends View { @Override protected void onDetachedFromWindow() { + getViewRootImpl().removeWindowStoppedCallback(this); + mAttachedToWindow = false; if (mGlobalListenersAdded) { ViewTreeObserver observer = getViewTreeObserver(); @@ -299,6 +318,7 @@ public class SurfaceView extends View { mSurfaceControl = null; mHaveFrame = false; + super.onDetachedFromWindow(); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a09db9c3972d..172ad8da5381 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -109,7 +109,6 @@ import android.widget.FrameLayout; import android.widget.ScrollBarDrawable; import com.android.internal.R; -import com.android.internal.util.Preconditions; import com.android.internal.view.TooltipPopup; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.widget.ScrollBarUtils; @@ -321,7 +320,7 @@ import java.util.function.Predicate; * </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> @@ -954,41 +953,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE}; - /** @hide */ - @IntDef({ - AUTOFILL_MODE_INHERIT, - AUTOFILL_MODE_AUTO, - AUTOFILL_MODE_MANUAL - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AutofillMode {} - - /** - * This view inherits the autofill state from it's parent. If there is no parent it is - * {@link #AUTOFILL_MODE_AUTO}. - * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode"> - * {@code android:autofillMode}. - */ - public static final int AUTOFILL_MODE_INHERIT = 0; - - /** - * Allows this view to automatically trigger an autofill request when it get focus. - * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode"> - * {@code android:autofillMode}. - */ - public static final int AUTOFILL_MODE_AUTO = 1; - - /** - * Do not trigger an autofill request if this view is focused. The user can still force - * an autofill request. - * <p>This does not prevent this field from being autofilled if an autofill operation is - * triggered from a different view.</p> - * - * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">{@code - * android:autofillMode}. - */ - public static final int AUTOFILL_MODE_MANUAL = 2; - /** * This view contains an email address. * @@ -2762,7 +2726,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * 1 PFLAG3_IS_AUTOFILLED * 1 PFLAG3_FINGER_DOWN * 1 PFLAG3_FOCUSED_BY_DEFAULT - * 11 PFLAG3_AUTO_FILL_MODE_MASK + * __ unused * 11 PFLAG3_IMPORTANT_FOR_AUTOFILL * 1 PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE * 1 PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED @@ -2992,23 +2956,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000; /** - * Shift for the place where the autofill mode is stored in the pflags - * - * @see #getAutofillMode() - * @see #setAutofillMode(int) - */ - private static final int PFLAG3_AUTOFILL_MODE_SHIFT = 19; - - /** - * Mask for autofill modes - * - * @see #getAutofillMode() - * @see #setAutofillMode(int) - */ - private static final int PFLAG3_AUTOFILL_MODE_MASK = (AUTOFILL_MODE_INHERIT - | AUTOFILL_MODE_AUTO | AUTOFILL_MODE_MANUAL) << PFLAG3_AUTOFILL_MODE_SHIFT; - - /** * Shift for the bits in {@link #mPrivateFlags3} related to the * "importantForAutofill" attribute. */ @@ -3920,6 +3867,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, 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 +4057,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ 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; @@ -5041,11 +5002,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setFocusedByDefault(a.getBoolean(attr, true)); } break; - case R.styleable.View_autofillMode: - if (a.peekValue(attr) != null) { - setAutofillMode(a.getInt(attr, AUTOFILL_MODE_INHERIT)); - } - break; case R.styleable.View_autofillHints: if (a.peekValue(attr) != null) { CharSequence[] rawHints = null; @@ -5086,6 +5042,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, 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 +6761,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, 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()) { @@ -6827,8 +6791,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) { - if (isAutofillable() && isAttachedToWindow() - && getResolvedAutofillMode() == AUTOFILL_MODE_AUTO) { + if (isAutofillable() && isAttachedToWindow()) { AutofillManager afm = getAutofillManager(); if (afm != null) { if (enter && hasWindowFocus() && isFocused()) { @@ -6948,7 +6911,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, 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); + } } /** @@ -9134,21 +9100,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Set autofill mode for the view. - * - * @param autofillMode One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO}, - * or {@link #AUTOFILL_MODE_MANUAL}. - * @attr ref android.R.styleable#View_autofillMode - */ - public void setAutofillMode(@AutofillMode int autofillMode) { - Preconditions.checkArgumentInRange(autofillMode, AUTOFILL_MODE_INHERIT, - AUTOFILL_MODE_MANUAL, "autofillMode"); - - mPrivateFlags3 &= ~PFLAG3_AUTOFILL_MODE_MASK; - mPrivateFlags3 |= autofillMode << PFLAG3_AUTOFILL_MODE_SHIFT; - } - - /** * Sets the hints that helps the autofill service to select the appropriate data to fill the * view. * @@ -9785,48 +9736,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Returns the autofill mode for this view. - * - * @return One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO}, or - * {@link #AUTOFILL_MODE_MANUAL}. - * @attr ref android.R.styleable#View_autofillMode - */ - @ViewDebug.ExportedProperty(mapping = { - @ViewDebug.IntToString(from = AUTOFILL_MODE_INHERIT, to = "AUTOFILL_MODE_INHERIT"), - @ViewDebug.IntToString(from = AUTOFILL_MODE_AUTO, to = "AUTOFILL_MODE_AUTO"), - @ViewDebug.IntToString(from = AUTOFILL_MODE_MANUAL, to = "AUTOFILL_MODE_MANUAL") - }) - @AutofillMode - public int getAutofillMode() { - return (mPrivateFlags3 & PFLAG3_AUTOFILL_MODE_MASK) >> PFLAG3_AUTOFILL_MODE_SHIFT; - } - - /** - * Returns the resolved autofill mode for this view. - * - * This is the same as {@link #getAutofillMode()} but if the mode is - * {@link #AUTOFILL_MODE_INHERIT} the parents autofill mode will be returned. - * - * @return One of {@link #AUTOFILL_MODE_AUTO}, or {@link #AUTOFILL_MODE_MANUAL}. If the auto- - * fill mode can not be resolved e.g. {@link #getAutofillMode()} is - * {@link #AUTOFILL_MODE_INHERIT} and the {@link View} is detached - * {@link #AUTOFILL_MODE_AUTO} is returned. - */ - public @AutofillMode int getResolvedAutofillMode() { - @AutofillMode int autofillMode = getAutofillMode(); - - if (autofillMode == AUTOFILL_MODE_INHERIT) { - if (mParent == null) { - return AUTOFILL_MODE_AUTO; - } else { - return mParent.getResolvedAutofillMode(); - } - } else { - return autofillMode; - } - } - - /** * Find the nearest view in the specified direction that can take focus. * This does not actually give focus to that view. * @@ -9986,6 +9895,33 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * 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 +11688,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, 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 +12905,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, 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 +12977,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } mBackgroundSizeChanged = true; + mDefaultFocusHighlightSizeChanged = true; if (mForegroundInfo != null) { mForegroundInfo.mBoundsChanged = true; } @@ -13927,6 +13869,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidate(true); } mBackgroundSizeChanged = true; + mDefaultFocusHighlightSizeChanged = true; if (mForegroundInfo != null) { mForegroundInfo.mBoundsChanged = true; } @@ -13995,6 +13938,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidate(true); } mBackgroundSizeChanged = true; + mDefaultFocusHighlightSizeChanged = true; if (mForegroundInfo != null) { mForegroundInfo.mBoundsChanged = true; } @@ -14057,6 +14001,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidate(true); } mBackgroundSizeChanged = true; + mDefaultFocusHighlightSizeChanged = true; if (mForegroundInfo != null) { mForegroundInfo.mBoundsChanged = true; } @@ -14116,6 +14061,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidate(true); } mBackgroundSizeChanged = true; + mDefaultFocusHighlightSizeChanged = true; if (mForegroundInfo != null) { mForegroundInfo.mBoundsChanged = true; } @@ -18720,6 +18666,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // Step 6, draw decorations (foreground, scrollbars) onDrawForeground(canvas); + // Step 7, draw the default focus highlight + drawDefaultFocusHighlight(canvas); + if (debugDraw()) { debugDrawFocus(canvas); } @@ -19278,6 +19227,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mPrivateFlags |= drawn; mBackgroundSizeChanged = true; + mDefaultFocusHighlightSizeChanged = true; if (mForegroundInfo != null) { mForegroundInfo.mBoundsChanged = true; } @@ -19429,6 +19379,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection); } + if (mDefaultFocusHighlight != null) { + mDefaultFocusHighlight.setLayoutDirection(layoutDirection); + } mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED; onResolveDrawables(layoutDirection); } @@ -19487,7 +19440,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // 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 +19465,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, 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 +19509,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, 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 +19548,106 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * 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 +19787,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (mStateListAnimator != null) { mStateListAnimator.jumpToCurrentState(); } + if (mDefaultFocusHighlight != null) { + mDefaultFocusHighlight.jumpToCurrentState(); + } if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { mForegroundInfo.mDrawable.jumpToCurrentState(); } @@ -19869,6 +19934,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /* Remove the background */ mBackground = null; if ((mViewFlags & WILL_NOT_DRAW) != 0 + && (mDefaultFocusHighlight == null) && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) { mPrivateFlags |= PFLAG_SKIP_DRAW; } @@ -20060,7 +20126,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } // 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 +21942,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // 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 574137b30f1e..4def0d02c225 100644 --- a/core/java/android/view/ViewConfiguration.java +++ b/core/java/android/view/ViewConfiguration.java @@ -35,7 +35,7 @@ public class ViewConfiguration { * 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 @@ public class ViewConfiguration { 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 9e1ceee60cd5..f9eb25da642a 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -61,7 +61,6 @@ import android.view.animation.Transformation; 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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager 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 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager 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/ViewParent.java b/core/java/android/view/ViewParent.java index d5aab48afe32..cc11cb8205d5 100644 --- a/core/java/android/view/ViewParent.java +++ b/core/java/android/view/ViewParent.java @@ -659,17 +659,4 @@ public interface ViewParent { * @return true if the action was consumed by this ViewParent */ public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle arguments); - - /** - * Return the resolved autofill mode. - * - * @return One of {@link View#AUTOFILL_MODE_AUTO}, {@link View#AUTOFILL_MODE_MANUAL} if the - * autofill mode can be resolved. If the autofill mode cannot be resolved - * {@link View#AUTOFILL_MODE_AUTO}. - * - * @see View#getResolvedAutofillMode() - */ - default @View.AutofillMode int getResolvedAutofillMode() { - return View.AUTOFILL_MODE_AUTO; - } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 58ef0af3fe79..a7ececf6c782 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1249,6 +1249,19 @@ public final class ViewRootImpl implements ViewParent, mIsAmbientMode = ambient; } + 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) { if (mStopped != stopped) { mStopped = stopped; @@ -1264,6 +1277,10 @@ public final class ViewRootImpl implements ViewParent, renderer.destroyHardwareResources(mView); } } + + for (int i = 0; i < mWindowStoppedCallbacks.size(); i++) { + mWindowStoppedCallbacks.get(i).windowStopped(stopped); + } } } diff --git a/core/java/android/view/ViewStub.java b/core/java/android/view/ViewStub.java index 85d10f199218..e9d1b8784914 100644 --- a/core/java/android/view/ViewStub.java +++ b/core/java/android/view/ViewStub.java @@ -58,7 +58,7 @@ import java.lang.ref.WeakReference; * 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 666ccf486941..8445b37b8133 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -978,8 +978,9 @@ public interface WindowManager extends ViewManager { * 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 ba004b967260..ec6559cba39b 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -101,7 +101,10 @@ public final class AutofillManager { // Public flags start from the lowest bit /** * Indicates autofill was explicitly requested by the user. + * + * @deprecated Use {@link android.service.autofill.FillRequest#FLAG_MANUAL_REQUEST} */ + @Deprecated public static final int FLAG_MANUAL_REQUEST = 0x1; // Private flags start from the highest bit @@ -192,6 +195,9 @@ public final class AutofillManager { * {@hide} */ public void onCreate(Bundle savedInstanceState) { + if (!hasAutofillFeature()) { + return; + } synchronized (mLock) { mLastAutofilledData = savedInstanceState.getParcelable(LAST_AUTOFILLED_DATA_TAG); @@ -237,6 +243,9 @@ public final class AutofillManager { * {@hide} */ public void onAttachedToWindow(@NonNull IBinder windowToken) { + if (!hasAutofillFeature()) { + return; + } synchronized (mLock) { if (mSessionId == NO_SESSION) { return; @@ -258,6 +267,9 @@ public final class AutofillManager { * {@hide} */ public void onSaveInstanceState(Bundle outState) { + if (!hasAutofillFeature()) { + return; + } synchronized (mLock) { if (mSessionId != NO_SESSION) { outState.putInt(SESSION_ID_TAG, mSessionId); @@ -278,6 +290,9 @@ public final class AutofillManager { * @return whether autofill is enabled for the current user. */ public boolean isEnabled() { + if (!hasAutofillFeature()) { + return false; + } synchronized (mLock) { ensureServiceClientAddedIfNeededLocked(); return mEnabled; @@ -294,6 +309,9 @@ public final class AutofillManager { * @param view view requesting the new autofill context. */ public void requestAutofill(@NonNull View view) { + if (!hasAutofillFeature()) { + return; + } synchronized (mLock) { ensureServiceClientAddedIfNeededLocked(); @@ -320,6 +338,9 @@ public final class AutofillManager { * @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 +360,9 @@ public final class AutofillManager { * @param view {@link View} that was entered. */ public void notifyViewEntered(@NonNull View view) { + if (!hasAutofillFeature()) { + return; + } AutofillCallback callback = null; synchronized (mLock) { ensureServiceClientAddedIfNeededLocked(); @@ -372,6 +396,9 @@ public final class AutofillManager { * @param view {@link View} that was exited. */ public void notifyViewExited(@NonNull View view) { + if (!hasAutofillFeature()) { + return; + } synchronized (mLock) { ensureServiceClientAddedIfNeededLocked(); @@ -392,6 +419,9 @@ public final class AutofillManager { * @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 +456,9 @@ public final class AutofillManager { * @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 +477,9 @@ public final class AutofillManager { * @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 +522,6 @@ public final class AutofillManager { } } - /** * Called to indicate the value of an autofillable virtual {@link View} changed. * @@ -495,6 +530,9 @@ public final class AutofillManager { * @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 +550,9 @@ public final class AutofillManager { * 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 +569,9 @@ public final class AutofillManager { * 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; @@ -542,6 +586,9 @@ public final class AutofillManager { * will be disabled. */ public void disableOwnedAutofillServices() { + if (!hasAutofillFeature()) { + return; + } try { mService.disableOwnedAutofillServices(mContext.getUserId()); } catch (RemoteException e) { @@ -558,6 +605,9 @@ public final class AutofillManager { /** @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 @@ -672,6 +722,9 @@ public final class AutofillManager { * @param callback callback to receive events. */ public void registerCallback(@Nullable AutofillCallback callback) { + if (!hasAutofillFeature()) { + return; + } synchronized (mLock) { if (callback == null) return; @@ -694,6 +747,9 @@ public final class AutofillManager { * @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; @@ -707,8 +763,8 @@ public final class AutofillManager { } } - private void requestShowFillUi(IBinder windowToken, AutofillId id, int width, int height, - Rect anchorBounds, IAutofillWindowPresenter presenter) { + private void requestShowFillUi(int sessionId, IBinder windowToken, AutofillId id, int width, + int height, Rect anchorBounds, IAutofillWindowPresenter presenter) { final View anchor = findAchorView(windowToken, id); if (anchor == null) { return; @@ -716,9 +772,15 @@ public final class AutofillManager { AutofillCallback callback = null; synchronized (mLock) { - if (getClientLocked().autofillCallbackRequestShowFillUi(anchor, width, height, - anchorBounds, presenter) && mCallback != null) { - callback = mCallback; + if (mSessionId == sessionId) { + AutofillClient client = getClientLocked(); + + if (client != null) { + if (client.autofillCallbackRequestShowFillUi(anchor, width, height, + anchorBounds, presenter) && mCallback != null) { + callback = mCallback; + } + } } } @@ -732,6 +794,23 @@ public final class AutofillManager { } } + private void authenticate(int sessionId, IntentSender intent, Intent fillInIntent) { + synchronized (mLock) { + if (sessionId == mSessionId) { + AutofillClient client = getClientLocked(); + if (client != null) { + client.autofillCallbackAuthenticate(intent, fillInIntent); + } + } + } + } + + private void setState(boolean enabled) { + synchronized (mLock) { + mEnabled = enabled; + } + } + /** * Sets a view as autofilled if the current value is the {code targetValue}. * @@ -751,80 +830,92 @@ public final class AutofillManager { } } - private void handleAutofill(IBinder windowToken, List<AutofillId> ids, + private void autofill(int sessionId, IBinder windowToken, List<AutofillId> ids, List<AutofillValue> values) { - final View root = WindowManagerGlobal.getInstance().getWindowView(windowToken); - if (root == null) { - return; - } - - final int itemCount = ids.size(); - int numApplied = 0; - ArrayMap<View, SparseArray<AutofillValue>> virtualValues = null; + synchronized (mLock) { + if (sessionId != mSessionId) { + return; + } - for (int i = 0; i < itemCount; i++) { - final AutofillId id = ids.get(i); - final AutofillValue value = values.get(i); - final int viewId = id.getViewId(); - final View view = root.findViewByAccessibilityIdTraversal(viewId); - if (view == null) { - Log.w(TAG, "autofill(): no View with id " + viewId); - continue; + final View root = WindowManagerGlobal.getInstance().getWindowView(windowToken); + if (root == null) { + return; } - if (id.isVirtual()) { - if (virtualValues == null) { - // Most likely there will be just one view with virtual children. - virtualValues = new ArrayMap<>(1); - } - SparseArray<AutofillValue> valuesByParent = virtualValues.get(view); - if (valuesByParent == null) { - // We don't know the size yet, but usually it will be just a few fields... - valuesByParent = new SparseArray<>(5); - virtualValues.put(view, valuesByParent); + + final int itemCount = ids.size(); + int numApplied = 0; + ArrayMap<View, SparseArray<AutofillValue>> virtualValues = null; + + for (int i = 0; i < itemCount; i++) { + final AutofillId id = ids.get(i); + final AutofillValue value = values.get(i); + final int viewId = id.getViewId(); + final View view = root.findViewByAccessibilityIdTraversal(viewId); + if (view == null) { + Log.w(TAG, "autofill(): no View with id " + viewId); + continue; } - valuesByParent.put(id.getVirtualChildId(), value); - } else { - synchronized (mLock) { + if (id.isVirtual()) { + if (virtualValues == null) { + // Most likely there will be just one view with virtual children. + virtualValues = new ArrayMap<>(1); + } + SparseArray<AutofillValue> valuesByParent = virtualValues.get(view); + if (valuesByParent == null) { + // We don't know the size yet, but usually it will be just a few fields... + valuesByParent = new SparseArray<>(5); + virtualValues.put(view, valuesByParent); + } + valuesByParent.put(id.getVirtualChildId(), value); + } else { // Mark the view as to be autofilled with 'value' if (mLastAutofilledData == null) { mLastAutofilledData = new ParcelableMap(itemCount - i); } mLastAutofilledData.put(id, value); - } - view.autofill(value); + view.autofill(value); - // Set as autofilled if the values match now, e.g. when the value was updated - // synchronously. - // If autofill happens async, the view is set to autofilled in notifyValueChanged. - setAutofilledIfValuesIs(view, value); + // Set as autofilled if the values match now, e.g. when the value was updated + // synchronously. + // If autofill happens async, the view is set to autofilled in + // notifyValueChanged. + setAutofilledIfValuesIs(view, value); - numApplied++; + numApplied++; + } } - } - if (virtualValues != null) { - for (int i = 0; i < virtualValues.size(); i++) { - final View parent = virtualValues.keyAt(i); - final SparseArray<AutofillValue> childrenValues = virtualValues.valueAt(i); - parent.autofill(childrenValues); - numApplied += childrenValues.size(); + if (virtualValues != null) { + for (int i = 0; i < virtualValues.size(); i++) { + final View parent = virtualValues.keyAt(i); + final SparseArray<AutofillValue> childrenValues = virtualValues.valueAt(i); + parent.autofill(childrenValues); + numApplied += childrenValues.size(); + } } - } - final LogMaker log = new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_DATASET_APPLIED); - log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount); - log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED, numApplied); - mMetricsLogger.write(log); + final LogMaker log = new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_DATASET_APPLIED); + log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount); + log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED, + numApplied); + mMetricsLogger.write(log); + } } - private void requestHideFillUi(IBinder windowToken, AutofillId id) { + private void requestHideFillUi(int sessionId, IBinder windowToken, AutofillId id) { final View anchor = findAchorView(windowToken, id); AutofillCallback callback = null; synchronized (mLock) { - if (getClientLocked().autofillCallbackRequestHideFillUi() && mCallback != null) { - callback = mCallback; + if (mSessionId == sessionId) { + AutofillClient client = getClientLocked(); + + if (client != null) { + if (client.autofillCallbackRequestHideFillUi() && mCallback != null) { + callback = mCallback; + } + } } } @@ -838,12 +929,14 @@ public final class AutofillManager { } } - private void notifyNoFillUi(IBinder windowToken, AutofillId id) { + private void notifyNoFillUi(int sessionId, IBinder windowToken, AutofillId id) { final View anchor = findAchorView(windowToken, id); - AutofillCallback callback; + AutofillCallback callback = null; synchronized (mLock) { - callback = mCallback; + if (mSessionId == sessionId && getClientLocked() != null) { + callback = mCallback; + } } if (callback != null) { @@ -871,6 +964,10 @@ public final class AutofillManager { return view; } + private boolean hasAutofillFeature() { + return mService != null; + } + /** * Callback for auto-fill related events. * @@ -942,71 +1039,69 @@ public final class AutofillManager { public void setState(boolean enabled) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> { - synchronized (afm.mLock) { - afm.mEnabled = enabled; - } - }); + afm.mContext.getMainThreadHandler().post(() -> afm.setState(enabled)); } } @Override - public void autofill(IBinder windowToken, List<AutofillId> ids, + public void autofill(int sessionId, IBinder windowToken, List<AutofillId> ids, List<AutofillValue> values) { // TODO(b/33197203): must keep the dataset so subsequent calls pass the same // dataset.extras to service final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> - afm.handleAutofill(windowToken, ids, values)); + afm.mContext.getMainThreadHandler().post( + () -> afm.autofill(sessionId, windowToken, ids, values)); } } @Override - public void authenticate(IntentSender intent, Intent fillInIntent) { + public void authenticate(int sessionId, IntentSender intent, Intent fillInIntent) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> { - if (afm.getClientLocked() != null) { - afm.getClientLocked().autofillCallbackAuthenticate(intent, fillInIntent); - } - }); + afm.mContext.getMainThreadHandler().post( + () -> afm.authenticate(sessionId, intent, fillInIntent)); } } @Override - public void requestShowFillUi(IBinder windowToken, AutofillId id, + public void requestShowFillUi(int sessionId, IBinder windowToken, AutofillId id, int width, int height, Rect anchorBounds, IAutofillWindowPresenter presenter) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> { - if (afm.getClientLocked() != null) { - afm.requestShowFillUi(windowToken, id, width, - height, anchorBounds, presenter); - } - }); + afm.mContext.getMainThreadHandler().post( + () -> afm.requestShowFillUi(sessionId, windowToken, id, width, height, + anchorBounds, presenter)); } } @Override - public void requestHideFillUi(IBinder windowToken, AutofillId id) { + public void requestHideFillUi(int sessionId, IBinder windowToken, AutofillId id) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> { - if (afm.getClientLocked() != null) { - afm.requestHideFillUi(windowToken, id); - } - }); + afm.mContext.getMainThreadHandler().post( + () -> afm.requestHideFillUi(sessionId, windowToken, id)); } } @Override - public void notifyNoFillUi(IBinder windowToken, AutofillId id) { + public void notifyNoFillUi(int sessionId, IBinder windowToken, AutofillId id) { + final AutofillManager afm = mAfm.get(); + if (afm != null) { + afm.mContext.getMainThreadHandler().post( + () -> afm.notifyNoFillUi(sessionId, windowToken, id)); + } + } + + @Override + public void startIntentSender(IntentSender intentSender) { final AutofillManager afm = mAfm.get(); if (afm != null) { afm.mContext.getMainThreadHandler().post(() -> { - if (afm.getClientLocked() != null) { - afm.notifyNoFillUi(windowToken, id); + 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/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl index 7bea17466ac5..56f91ed6de9b 100644 --- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl +++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl @@ -40,26 +40,32 @@ oneway interface IAutoFillManagerClient { /** * Autofills the activity with the contents of a dataset. */ - void autofill(in IBinder windowToken, in List<AutofillId> ids, in List<AutofillValue> values); + void autofill(int sessionId, in IBinder windowToken, in List<AutofillId> ids, + in List<AutofillValue> values); /** * Authenticates a fill response or a data set. */ - void authenticate(in IntentSender intent, in Intent fillInIntent); + void authenticate(int sessionId, in IntentSender intent, in Intent fillInIntent); /** * Requests showing the fill UI. */ - void requestShowFillUi(in IBinder windowToken, in AutofillId id, int width, + void requestShowFillUi(int sessionId, in IBinder windowToken, in AutofillId id, int width, int height, in Rect anchorBounds, in IAutofillWindowPresenter presenter); /** * Requests hiding the fill UI. */ - void requestHideFillUi(in IBinder windowToken, in AutofillId id); + void requestHideFillUi(int sessionId, 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); + void notifyNoFillUi(int sessionId, in IBinder windowToken, in AutofillId id); + + /** + * Starts the provided intent sender + */ + void startIntentSender(in IntentSender intentSender); } diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java index 2f12e9b5be83..28d9fcf57370 100644 --- a/core/java/android/view/inputmethod/EditorInfo.java +++ b/core/java/android/view/inputmethod/EditorInfo.java @@ -155,7 +155,7 @@ public class EditorInfo implements InputType, Parcelable { public static final int IME_ACTION_PREVIOUS = 0x00000007; /** - * Flag of {@link #imeOptions}: used to request that the IME does not update any personalized + * Flag of {@link #imeOptions}: used to request that the IME should not update any personalized * data such as typing history and personalized language model based on what the user typed on * this text editing object. Typical use cases are: * <ul> diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java index 71809bdb4393..f0645b895afa 100644 --- a/core/java/android/view/inputmethod/InputMethodInfo.java +++ b/core/java/android/view/inputmethod/InputMethodInfo.java @@ -57,7 +57,6 @@ import java.util.List; * @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 @@ public final class InputMethodInfo implements Parcelable { 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 @@ public final class InputMethodInfo implements Parcelable { 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 @@ public final class InputMethodInfo implements Parcelable { 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 @@ public final class InputMethodInfo implements Parcelable { mIsDefaultResId = isDefaultResId; mIsAuxIme = isAuxIme; mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod; - mSupportsDismissingWindow = supportsDismissingWindow; } InputMethodInfo(Parcel source) { @@ -272,7 +262,6 @@ public final class InputMethodInfo implements Parcelable { 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 @@ public final class InputMethodInfo implements Parcelable { 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 @@ public final class InputMethodInfo implements Parcelable { 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 final class InputMethodInfo implements Parcelable { */ 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 @@ public final class InputMethodInfo implements Parcelable { mSubtypes = new InputMethodSubtypeArray(subtypes); mForceDefault = forceDefault; mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod; - mSupportsDismissingWindow = supportsDismissingWindow; } private static ResolveInfo buildDummyResolveInfo(String packageName, String className, @@ -458,8 +444,7 @@ public final class InputMethodInfo implements Parcelable { 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 @@ public final class InputMethodInfo implements Parcelable { } /** - * @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 @@ public final class InputMethodInfo implements Parcelable { 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 6213a63e108a..9202889ac9f2 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -1731,7 +1731,14 @@ public class WebView extends AbsoluteLayout * * @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/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java index 06d486813b1b..6df76fa2e09a 100644 --- a/core/java/android/widget/AppSecurityPermissions.java +++ b/core/java/android/widget/AppSecurityPermissions.java @@ -151,8 +151,8 @@ public class AppSecurityPermissions { 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 09e09b7c2c9c..09ba553cbf3e 100644 --- a/core/java/android/widget/Button.java +++ b/core/java/android/widget/Button.java @@ -37,7 +37,7 @@ import android.widget.RemoteViews.RemoteView; * * 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 0f0e6c30979d..be0967f162c4 100644 --- a/core/java/android/widget/DayPickerView.java +++ b/core/java/android/widget/DayPickerView.java @@ -124,13 +124,13 @@ class DayPickerView extends ViewGroup { 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 faa23106e920..4fb7b19f7bf7 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -1915,11 +1915,10 @@ public class Editor { } 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 @@ public class Editor { 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 @@ public class Editor { 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 @@ public class Editor { || !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 @@ public class Editor { 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 @@ public class Editor { } 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 2152e4338362..f348d73c1b42 100644 --- a/core/java/android/widget/MultiAutoCompleteTextView.java +++ b/core/java/android/widget/MultiAutoCompleteTextView.java @@ -43,7 +43,7 @@ import android.util.AttributeSet; * * 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 662e64099fc8..7bdd6dadf415 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -706,7 +706,7 @@ public class NumberPicker extends LinearLayout { // 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 @@ public class NumberPicker extends LinearLayout { // 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 @@ public class NumberPicker extends LinearLayout { } // 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 5505f2fef919..9245134fd266 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -1787,7 +1787,7 @@ public class RemoteViews implements Parcelable, Filter { @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 @@ public class RemoteViews implements Parcelable, Filter { 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 7e2cadfc8c45..8de17c072b59 100644 --- a/core/java/android/widget/TabHost.java +++ b/core/java/android/widget/TabHost.java @@ -136,7 +136,7 @@ mTabHost.setup(); 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 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1"); } }); - 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 0183343e96e1..11b7514d6ac8 100644 --- a/core/java/android/widget/TextInputTimePickerView.java +++ b/core/java/android/widget/TextInputTimePickerView.java @@ -76,12 +76,12 @@ public class TextInputTimePickerView extends RelativeLayout { 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 @@ public class TextInputTimePickerView extends RelativeLayout { } }); - 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 fcab7035e60f..f9f10af85b69 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.drawable.Drawable; 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 class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener == (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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } 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 class TextView extends View implements ViewTreeObserver.OnPreDrawListener public void setTextLocale(@NonNull Locale locale) { mLocalesChanged = true; mTextPaint.setTextLocale(locale); - changeListenerLocaleTo(locale); if (mLayout != null) { nullLayouts(); requestLayout(); @@ -3456,7 +3467,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * 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 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener createEditorIfNeeded(); mEditor.createInputContentTypeIfNeeded(); mEditor.mInputContentType.imeHintLocales = hintLocales; + if (mUseInternationalizedInput) { + changeListenerLocaleTo(hintLocales == null ? null : hintLocales.get(0)); + } } /** @@ -8470,7 +8518,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // 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 0445ebd50926..553b86e1f0c2 100644 --- a/core/java/android/widget/TwoLineListItem.java +++ b/core/java/android/widget/TwoLineListItem.java @@ -70,8 +70,8 @@ public class TwoLineListItem extends RelativeLayout { 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 ee5d339a19d3..032c7750c1d6 100644 --- a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java +++ b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java @@ -59,13 +59,13 @@ public class AccessibilityButtonChooserActivity extends Activity { 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 @@ public class AccessibilityButtonChooserActivity extends Activity { 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/AlertActivity.java b/core/java/com/android/internal/app/AlertActivity.java index 35ffa71de56f..999a908251dd 100644 --- a/core/java/com/android/internal/app/AlertActivity.java +++ b/core/java/com/android/internal/app/AlertActivity.java @@ -67,10 +67,15 @@ public abstract class AlertActivity extends Activity implements DialogInterface @Override public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + return dispatchPopulateAccessibilityEvent(this, event); + } + + public static boolean dispatchPopulateAccessibilityEvent(Activity act, + AccessibilityEvent event) { event.setClassName(Dialog.class.getName()); - event.setPackageName(getPackageName()); + event.setPackageName(act.getPackageName()); - ViewGroup.LayoutParams params = getWindow().getAttributes(); + ViewGroup.LayoutParams params = act.getWindow().getAttributes(); boolean isFullScreen = (params.width == ViewGroup.LayoutParams.MATCH_PARENT) && (params.height == ViewGroup.LayoutParams.MATCH_PARENT); event.setFullScreen(isFullScreen); @@ -86,8 +91,7 @@ public abstract class AlertActivity extends Activity implements DialogInterface * @see #mAlertParams */ protected void setupAlert() { - mAlertParams.apply(mAlert); - mAlert.installContent(); + mAlert.installContent(mAlertParams); } @Override diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java index 95c291a9e8fe..46cb5461b682 100644 --- a/core/java/com/android/internal/app/AlertController.java +++ b/core/java/com/android/internal/app/AlertController.java @@ -247,6 +247,11 @@ public class AlertController { return false; } + public void installContent(AlertParams params) { + params.apply(this); + installContent(); + } + public void installContent() { int contentView = selectContentView(); mWindow.setContentView(contentView); diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl index 3a31b370a417..35d4ba81bd69 100644 --- a/core/java/com/android/internal/app/IAppOpsService.aidl +++ b/core/java/com/android/internal/app/IAppOpsService.aidl @@ -38,6 +38,7 @@ interface IAppOpsService { 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 622b70843cc2..b59667815922 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -287,7 +287,7 @@ public class ResolverActivity extends Activity { 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 @@ public class ResolverActivity extends Activity { } - 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 class ResolverActivity extends Activity { 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 @@ public class ResolverActivity extends Activity { : 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 @@ public class ResolverActivity extends Activity { } } - 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 class ResolverActivity extends Activity { 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/app/SuggestedLocaleAdapter.java b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java index cb2b0191b883..46f47a31441c 100644 --- a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java +++ b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java @@ -16,6 +16,10 @@ package com.android.internal.app; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.content.res.Configuration; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; @@ -57,6 +61,10 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable { private final boolean mCountryMode; private LayoutInflater mInflater; + private Locale mDisplayLocale = null; + // used to potentially cache a modified Context that uses mDisplayLocale + private Context mContextOverride = null; + public SuggestedLocaleAdapter(Set<LocaleStore.LocaleInfo> localeOptions, boolean countryMode) { mCountryMode = countryMode; mLocaleOptions = new ArrayList<>(localeOptions.size()); @@ -126,6 +134,31 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable { return position; } + /** + * Overrides the locale used to display localized labels. Setting the locale to null will reset + * the Adapter to use the default locale for the labels. + */ + public void setDisplayLocale(@NonNull Context context, @Nullable Locale locale) { + if (locale == null) { + mDisplayLocale = null; + mContextOverride = null; + } else if (!locale.equals(mDisplayLocale)) { + mDisplayLocale = locale; + final Configuration configOverride = new Configuration(); + configOverride.setLocale(locale); + mContextOverride = context.createConfigurationContext(configOverride); + } + } + + private void setTextTo(@NonNull TextView textView, int resId) { + if (mContextOverride == null) { + textView.setText(resId); + } else { + textView.setText(mContextOverride.getText(resId)); + // If mContextOverride is not null, mDisplayLocale can't be null either. + } + } + @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null && mInflater == null) { @@ -143,15 +176,16 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable { } TextView textView = (TextView) convertView; if (itemType == TYPE_HEADER_SUGGESTED) { - textView.setText(R.string.language_picker_section_suggested); + setTextTo(textView, R.string.language_picker_section_suggested); } else { if (mCountryMode) { - textView.setText(R.string.region_picker_section_all); + setTextTo(textView, R.string.region_picker_section_all); } else { - textView.setText(R.string.language_picker_section_all); + setTextTo(textView, R.string.language_picker_section_all); } } - textView.setTextLocale(Locale.getDefault()); + textView.setTextLocale( + mDisplayLocale != null ? mDisplayLocale : Locale.getDefault()); break; default: // Covers both null, and "reusing" a wrong kind of view diff --git a/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java b/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java new file mode 100644 index 000000000000..4ce6f609ef73 --- /dev/null +++ b/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.notification; + +import android.content.ComponentName; +import android.content.Intent; + +public final class NotificationAccessConfirmationActivityContract { + private static final ComponentName COMPONENT_NAME = new ComponentName( + "com.android.settings", + "com.android.settings.notification.NotificationAccessConfirmationActivity"); + public static final String EXTRA_USER_ID = "user_id"; + public static final String EXTRA_COMPONENT_NAME = "component_name"; + public static final String EXTRA_PACKAGE_TITLE = "package_title"; + + public static Intent launcherIntent(int userId, ComponentName component, String packageTitle) { + return new Intent() + .setComponent(COMPONENT_NAME) + .putExtra(EXTRA_USER_ID, userId) + .putExtra(EXTRA_COMPONENT_NAME, component) + .putExtra(EXTRA_PACKAGE_TITLE, packageTitle); + } +} diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index fe3860507c27..7fbfb8baedc4 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -114,7 +114,7 @@ public class BatteryStatsImpl extends BatteryStats { 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; @@ -5463,7 +5463,6 @@ public class BatteryStatsImpl extends BatteryStats { LongSamplingCounter mUserCpuTime; LongSamplingCounter mSystemCpuTime; - LongSamplingCounter mCpuPower; LongSamplingCounter[][] mCpuClusterSpeed; /** @@ -5474,7 +5473,7 @@ public class BatteryStatsImpl extends BatteryStats { /** * 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. @@ -5511,17 +5510,16 @@ public class BatteryStatsImpl extends BatteryStats { 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) { @@ -6162,11 +6160,6 @@ public class BatteryStatsImpl extends BatteryStats { } @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) { @@ -6311,7 +6304,6 @@ public class BatteryStatsImpl extends BatteryStats { mUserCpuTime.reset(false); mSystemCpuTime.reset(false); - mCpuPower.reset(false); if (mCpuClusterSpeed != null) { for (LongSamplingCounter[] speeds : mCpuClusterSpeed) { @@ -6338,9 +6330,9 @@ public class BatteryStatsImpl extends BatteryStats { } } 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(); @@ -6477,7 +6469,6 @@ public class BatteryStatsImpl extends BatteryStats { mUserCpuTime.detach(); mSystemCpuTime.detach(); - mCpuPower.detach(); if (mCpuClusterSpeed != null) { for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) { @@ -6510,12 +6501,12 @@ public class BatteryStatsImpl extends BatteryStats { 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); } @@ -6677,7 +6668,6 @@ public class BatteryStatsImpl extends BatteryStats { mUserCpuTime.writeToParcel(out); mSystemCpuTime.writeToParcel(out); - mCpuPower.writeToParcel(out); if (mCpuClusterSpeed != null) { out.writeInt(1); @@ -6734,8 +6724,8 @@ public class BatteryStatsImpl extends BatteryStats { 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)); } } @@ -6913,7 +6903,6 @@ public class BatteryStatsImpl extends BatteryStats { 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(); @@ -8002,7 +7991,7 @@ public class BatteryStatsImpl extends BatteryStats { } public void readSyncSummaryFromParcelLocked(String name, Parcel in) { - StopwatchTimer timer = mSyncStats.instantiateObject(); + DualTimer timer = mSyncStats.instantiateObject(); timer.readSummaryFromParcelLocked(in); mSyncStats.add(name, timer); } @@ -8055,14 +8044,14 @@ public class BatteryStatsImpl extends BatteryStats { } 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); } @@ -9705,8 +9694,7 @@ public class BatteryStatsImpl extends BatteryStats { 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. @@ -9720,7 +9708,7 @@ public class BatteryStatsImpl extends BatteryStats { 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) { @@ -9736,13 +9724,11 @@ public class BatteryStatsImpl extends BatteryStats { 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. @@ -11036,7 +11022,6 @@ public class BatteryStatsImpl extends BatteryStats { u.mUserCpuTime.readSummaryFromParcelLocked(in); u.mSystemCpuTime.readSummaryFromParcelLocked(in); - u.mCpuPower.readSummaryFromParcelLocked(in); if (in.readInt() != 0) { final int numClusters = in.readInt(); @@ -11432,7 +11417,6 @@ public class BatteryStatsImpl extends BatteryStats { u.mUserCpuTime.writeSummaryFromParcelLocked(out); u.mSystemCpuTime.writeSummaryFromParcelLocked(out); - u.mCpuPower.writeSummaryFromParcelLocked(out); if (u.mCpuClusterSpeed != null) { out.writeInt(1); @@ -11503,7 +11487,7 @@ public class BatteryStatsImpl extends BatteryStats { } } - 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 e8919ede82b5..181e1ac9f3ec 100644 --- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java +++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java @@ -50,14 +50,12 @@ public class KernelUidCpuTimeReader { * @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 @@ public class KernelUidCpuTimeReader { 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 @@ public class KernelUidCpuTimeReader { 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 @@ public class KernelUidCpuTimeReader { 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 44fa99df7b73..142effbbf0c7 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -186,8 +186,8 @@ public class ZygoteInit { 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/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 8e6e63b0e238..baf6db93daaf 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -1688,7 +1688,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind } }; } 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; @@ -2263,8 +2263,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind @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); } } diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 7b966de86756..243916b4ade2 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -1593,7 +1593,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { 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 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { 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 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { 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 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { 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 a208ccb8f35f..e349f3d4b473 100644 --- a/core/java/com/android/internal/util/BitUtils.java +++ b/core/java/com/android/internal/util/BitUtils.java @@ -55,4 +55,25 @@ public class BitUtils { && 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/CollectionUtils.java b/core/java/com/android/internal/util/CollectionUtils.java index 287f68cf5a55..96b443d28abc 100644 --- a/core/java/com/android/internal/util/CollectionUtils.java +++ b/core/java/com/android/internal/util/CollectionUtils.java @@ -16,6 +16,8 @@ package com.android.internal.util; +import static com.android.internal.util.ArrayUtils.isEmpty; + import android.annotation.NonNull; import android.annotation.Nullable; @@ -64,7 +66,7 @@ public class CollectionUtils { */ public static @NonNull <I, O> List<O> map(@Nullable List<I> cur, Function<? super I, ? extends O> f) { - if (cur == null || cur.isEmpty()) return Collections.emptyList(); + if (isEmpty(cur)) return Collections.emptyList(); final ArrayList<O> result = new ArrayList<>(); for (int i = 0; i < cur.size(); i++) { result.add(f.apply(cur.get(i))); @@ -73,6 +75,30 @@ public class CollectionUtils { } /** + * {@link #map(List, Function)} + {@link #filter(List, java.util.function.Predicate)} + * + * Calling this is equivalent (but more memory efficient) to: + * + * {@code + * filter( + * map(cur, f), + * i -> { i != null }) + * } + */ + public static @NonNull <I, O> List<O> mapNotNull(@Nullable List<I> cur, + Function<? super I, ? extends O> f) { + if (isEmpty(cur)) return Collections.emptyList(); + final ArrayList<O> result = new ArrayList<>(); + for (int i = 0; i < cur.size(); i++) { + O transformed = f.apply(cur.get(i)); + if (transformed != null) { + result.add(transformed); + } + } + return result; + } + + /** * Returns the given list, or an immutable empty list if the provided list is null * * This can be used to guaranty null-safety without paying the price of extra allocations @@ -94,7 +120,7 @@ public class CollectionUtils { * Returns the elements of the given list that are of type {@code c} */ public static @NonNull <T> List<T> filter(@Nullable List<?> list, Class<T> c) { - if (ArrayUtils.isEmpty(list)) return Collections.emptyList(); + if (isEmpty(list)) return Collections.emptyList(); ArrayList<T> result = null; for (int i = 0; i < list.size(); i++) { final Object item = list.get(i); @@ -120,11 +146,42 @@ public class CollectionUtils { */ public static @Nullable <T> T find(@Nullable List<T> items, java.util.function.Predicate<T> predicate) { - if (ArrayUtils.isEmpty(items)) return null; + if (isEmpty(items)) return null; for (int i = 0; i < items.size(); i++) { final T item = items.get(i); if (predicate.test(item)) return item; } return null; } + + /** + * Similar to {@link List#add}, but with support for list values of {@code null} and + * {@link Collections#emptyList} + */ + public static @NonNull <T> List<T> add(@Nullable List<T> cur, T val) { + if (cur == null || cur == Collections.emptyList()) { + cur = new ArrayList<>(); + } + cur.add(val); + return cur; + } + + /** + * Similar to {@link List#remove}, but with support for list values of {@code null} and + * {@link Collections#emptyList} + */ + public static @NonNull <T> List<T> remove(@Nullable List<T> cur, T val) { + if (isEmpty(cur)) { + return emptyIfNull(cur); + } + cur.remove(val); + return cur; + } + + /** + * @return a list that will not be affected by mutations to the given original list. + */ + public static @NonNull <T> List<T> copyOf(@Nullable List<T> cur) { + return isEmpty(cur) ? Collections.emptyList() : new ArrayList<>(cur); + } } diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java index 4659d3c48a22..ce89501c970a 100644 --- a/core/java/com/android/internal/util/DumpUtils.java +++ b/core/java/com/android/internal/util/DumpUtils.java @@ -121,12 +121,15 @@ public final class DumpUtils { 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/util/FunctionalUtils.java b/core/java/com/android/internal/util/FunctionalUtils.java new file mode 100644 index 000000000000..9aeb0415b5fc --- /dev/null +++ b/core/java/com/android/internal/util/FunctionalUtils.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.util; + +import java.util.function.Supplier; + +/** + * Utilities specific to functional programming + */ +public class FunctionalUtils { + private FunctionalUtils() {} + + /** + * An equivalent of {@link Runnable} that allows throwing checked exceptions + * + * This can be used to specify a lambda argument without forcing all the checked exceptions + * to be handled within it + */ + @FunctionalInterface + public interface ThrowingRunnable { + void run() throws Exception; + } + + /** + * An equivalent of {@link Supplier} that allows throwing checked exceptions + * + * This can be used to specify a lambda argument without forcing all the checked exceptions + * to be handled within it + */ + @FunctionalInterface + public interface ThrowingSupplier<T> { + T get() throws Exception; + } +} diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java index 4e6857a72b43..e5d571672ce2 100644 --- a/core/java/com/android/internal/util/Preconditions.java +++ b/core/java/com/android/internal/util/Preconditions.java @@ -49,6 +49,23 @@ public class Preconditions { } /** + * Ensures that an expression checking an argument is true. + * + * @param expression the expression to check + * @param messageTemplate a printf-style message template to use if the check fails; will + * be converted to a string using {@link String#format(String, Object...)} + * @param messageArgs arguments for {@code messageTemplate} + * @throws IllegalArgumentException if {@code expression} is false + */ + public static void checkArgument(boolean expression, + final String messageTemplate, + final Object... messageArgs) { + if (!expression) { + throw new IllegalArgumentException(String.format(messageTemplate, messageArgs)); + } + } + + /** * Ensures that an string reference passed as a parameter to the calling * method is not empty. * diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java index 919cf991d433..83a2838be07e 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 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView 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 c3a7460e5752..65cd4fa20341 100644 --- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java +++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java @@ -569,10 +569,10 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar 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 @@ public class ActionBarOverlayLayout extends ViewGroup implements DecorContentPar 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 f63afada7e38..afb2a5efcf95 100644 --- a/core/java/com/android/internal/widget/MediaNotificationView.java +++ b/core/java/com/android/internal/widget/MediaNotificationView.java @@ -152,7 +152,7 @@ public class MediaNotificationView extends FrameLayout { @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 33fabfc4c2a5..96285cd4c17d 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -96,6 +96,7 @@ LOCAL_SRC_FILES:= \ 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 e237ce9f208f..8ca479478930 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -159,6 +159,7 @@ extern int register_android_os_HwRemoteBinder(JNIEnv *env); 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 @@ static const RegJNIRec gRegJNI[] = { 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/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index 3a03af60efce..0e67d304c66d 100755 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -44,14 +44,6 @@ static jmethodID gBitmap_constructorMethodID; static jmethodID gBitmap_reinitMethodID; static jmethodID gBitmap_getAllocationByteCountMethodID; -static jfieldID gTransferParams_aFieldID; -static jfieldID gTransferParams_bFieldID; -static jfieldID gTransferParams_cFieldID; -static jfieldID gTransferParams_dFieldID; -static jfieldID gTransferParams_eFieldID; -static jfieldID gTransferParams_fFieldID; -static jfieldID gTransferParams_gFieldID; - namespace android { class BitmapWrapper { @@ -742,28 +734,8 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors, if (colorType != kN32_SkColorType || xyzD50 == nullptr || transferParameters == nullptr) { colorSpace = GraphicsJNI::colorSpaceForType(colorType); } else { - SkColorSpaceTransferFn p; - p.fA = (float) env->GetDoubleField(transferParameters, gTransferParams_aFieldID); - p.fB = (float) env->GetDoubleField(transferParameters, gTransferParams_bFieldID); - p.fC = (float) env->GetDoubleField(transferParameters, gTransferParams_cFieldID); - p.fD = (float) env->GetDoubleField(transferParameters, gTransferParams_dFieldID); - p.fE = (float) env->GetDoubleField(transferParameters, gTransferParams_eFieldID); - p.fF = (float) env->GetDoubleField(transferParameters, gTransferParams_fFieldID); - p.fG = (float) env->GetDoubleField(transferParameters, gTransferParams_gFieldID); - - SkMatrix44 xyzMatrix(SkMatrix44::kIdentity_Constructor); - jfloat* array = env->GetFloatArrayElements(xyzD50, NULL); - xyzMatrix.setFloat(0, 0, array[0]); - xyzMatrix.setFloat(1, 0, array[1]); - xyzMatrix.setFloat(2, 0, array[2]); - xyzMatrix.setFloat(0, 1, array[3]); - xyzMatrix.setFloat(1, 1, array[4]); - xyzMatrix.setFloat(2, 1, array[5]); - xyzMatrix.setFloat(0, 2, array[6]); - xyzMatrix.setFloat(1, 2, array[7]); - xyzMatrix.setFloat(2, 2, array[8]); - env->ReleaseFloatArrayElements(xyzD50, array, 0); - + SkColorSpaceTransferFn p = GraphicsJNI::getNativeTransferParameters(env, transferParameters); + SkMatrix44 xyzMatrix = GraphicsJNI::getNativeXYZMatrix(env, xyzD50); colorSpace = SkColorSpace::MakeRGB(p, xyzMatrix); } @@ -1635,20 +1607,6 @@ static void Bitmap_copyColorSpace(JNIEnv* env, jobject, jlong srcBitmapPtr, jlon } /////////////////////////////////////////////////////////////////////////////// -static jclass make_globalref(JNIEnv* env, const char classname[]) -{ - jclass c = env->FindClass(classname); - SkASSERT(c); - return (jclass) env->NewGlobalRef(c); -} - -static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz, - const char fieldname[], const char type[]) -{ - jfieldID id = env->GetFieldID(clazz, fieldname, type); - SkASSERT(id); - return id; -} static const JNINativeMethod gBitmapMethods[] = { { "nativeCreate", "([IIIIIIZ[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/Bitmap;", @@ -1706,20 +1664,11 @@ static const JNINativeMethod gBitmapMethods[] = { int register_android_graphics_Bitmap(JNIEnv* env) { - jclass transfer_params_class = FindClassOrDie(env, "android/graphics/ColorSpace$Rgb$TransferParameters"); - gTransferParams_aFieldID = GetFieldIDOrDie(env, transfer_params_class, "a", "D"); - gTransferParams_bFieldID = GetFieldIDOrDie(env, transfer_params_class, "b", "D"); - gTransferParams_cFieldID = GetFieldIDOrDie(env, transfer_params_class, "c", "D"); - gTransferParams_dFieldID = GetFieldIDOrDie(env, transfer_params_class, "d", "D"); - gTransferParams_eFieldID = GetFieldIDOrDie(env, transfer_params_class, "e", "D"); - gTransferParams_fFieldID = GetFieldIDOrDie(env, transfer_params_class, "f", "D"); - gTransferParams_gFieldID = GetFieldIDOrDie(env, transfer_params_class, "g", "D"); - - gBitmap_class = make_globalref(env, "android/graphics/Bitmap"); - gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J"); - gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V"); - gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V"); - gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I"); + gBitmap_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Bitmap")); + gBitmap_nativePtr = GetFieldIDOrDie(env, gBitmap_class, "mNativePtr", "J"); + gBitmap_constructorMethodID = GetMethodIDOrDie(env, gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V"); + gBitmap_reinitMethodID = GetMethodIDOrDie(env, gBitmap_class, "reinit", "(IIZ)V"); + gBitmap_getAllocationByteCountMethodID = GetMethodIDOrDie(env, gBitmap_class, "getAllocationByteCount", "()I"); return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods, NELEM(gBitmapMethods)); } diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index 3dc1be6a26e3..e714671027d6 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -27,6 +27,7 @@ jfieldID gOptions_justBoundsFieldID; jfieldID gOptions_sampleSizeFieldID; jfieldID gOptions_configFieldID; +jfieldID gOptions_colorSpaceFieldID; jfieldID gOptions_premultipliedFieldID; jfieldID gOptions_mutableFieldID; jfieldID gOptions_ditherFieldID; @@ -51,20 +52,6 @@ jmethodID gInsetStruct_constructorMethodID; jclass gBitmapConfig_class; jmethodID gBitmapConfig_nativeToConfigMethodID; -jclass gColorSpace_class; -jmethodID gColorSpace_getMethodID; -jmethodID gColorSpace_matchMethodID; - -jclass gColorSpaceRGB_class; -jmethodID gColorSpaceRGB_constructorMethodID; - -jclass gColorSpace_Named_class; -jfieldID gColorSpace_Named_sRGBFieldID; -jfieldID gColorSpace_Named_LinearExtendedSRGBFieldID; - -jclass gTransferParameters_class; -jmethodID gTransferParameters_constructorMethodID; - using namespace android; jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format) { @@ -243,70 +230,6 @@ static bool needsFineScale(const SkISize fullSize, const SkISize decodedSize, needsFineScale(fullSize.height(), decodedSize.height(), sampleSize); } -static jobject getColorSpace(JNIEnv* env, - sk_sp<SkColorSpace>& decodeColorSpace, SkColorType decodeColorType) { - jobject colorSpace = nullptr; - - // No need to match, we know what the output color space will be - if (decodeColorType == kRGBA_F16_SkColorType) { - jobject linearExtendedSRGB = env->GetStaticObjectField( - gColorSpace_Named_class, gColorSpace_Named_LinearExtendedSRGBFieldID); - colorSpace = env->CallStaticObjectMethod(gColorSpace_class, - gColorSpace_getMethodID, linearExtendedSRGB); - } else { - // Same here, no need to match - if (decodeColorSpace->isSRGB()) { - jobject sRGB = env->GetStaticObjectField( - gColorSpace_Named_class, gColorSpace_Named_sRGBFieldID); - colorSpace = env->CallStaticObjectMethod(gColorSpace_class, - gColorSpace_getMethodID, sRGB); - } else if (decodeColorSpace.get() != nullptr) { - // Try to match against known RGB color spaces using the CIE XYZ D50 - // conversion matrix and numerical transfer function parameters - SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor); - LOG_ALWAYS_FATAL_IF(!decodeColorSpace->toXYZD50(&xyzMatrix)); - - SkColorSpaceTransferFn transferParams; - // We can only handle numerical transfer functions at the moment - LOG_ALWAYS_FATAL_IF(!decodeColorSpace->isNumericalTransferFn(&transferParams)); - - jobject params = env->NewObject(gTransferParameters_class, - gTransferParameters_constructorMethodID, - transferParams.fA, transferParams.fB, transferParams.fC, - transferParams.fD, transferParams.fE, transferParams.fF, - transferParams.fG); - - jfloatArray xyzArray = env->NewFloatArray(9); - jfloat xyz[9] = { - xyzMatrix.getFloat(0, 0), - xyzMatrix.getFloat(1, 0), - xyzMatrix.getFloat(2, 0), - xyzMatrix.getFloat(0, 1), - xyzMatrix.getFloat(1, 1), - xyzMatrix.getFloat(2, 1), - xyzMatrix.getFloat(0, 2), - xyzMatrix.getFloat(1, 2), - xyzMatrix.getFloat(2, 2) - }; - env->SetFloatArrayRegion(xyzArray, 0, 9, xyz); - - colorSpace = env->CallStaticObjectMethod(gColorSpace_class, - gColorSpace_matchMethodID, xyzArray, params); - - if (colorSpace == nullptr) { - // We couldn't find an exact match, let's create a new color space - // instance with the 3x3 conversion matrix and transfer function - colorSpace = env->NewObject(gColorSpaceRGB_class, - gColorSpaceRGB_constructorMethodID, - env->NewStringUTF("Unknown"), xyzArray, params); - } - - env->DeleteLocalRef(xyzArray); - } - } - return colorSpace; -} - static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding, jobject options) { // This function takes ownership of the input stream. Since the SkAndroidCodec // will take ownership of the stream, we don't necessarily need to take ownership @@ -323,6 +246,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding float scale = 1.0f; bool requireUnpremultiplied = false; jobject javaBitmap = NULL; + sk_sp<SkColorSpace> prefColorSpace = nullptr; // Update with options supplied by the client. if (options != NULL) { @@ -346,6 +270,8 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding jobject jconfig = env->GetObjectField(options, gOptions_configFieldID); prefColorType = GraphicsJNI::getNativeBitmapColorType(env, jconfig); + jobject jcolorSpace = env->GetObjectField(options, gOptions_colorSpaceFieldID); + prefColorSpace = GraphicsJNI::getNativeColorSpace(env, jcolorSpace); isHardware = GraphicsJNI::isHardwareConfig(env, jconfig); isMutable = env->GetBooleanField(options, gOptions_mutableFieldID); requireUnpremultiplied = !env->GetBooleanField(options, gOptions_premultipliedFieldID); @@ -399,7 +325,8 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding // Set the decode colorType SkColorType decodeColorType = codec->computeOutputColorType(prefColorType); - sk_sp<SkColorSpace> decodeColorSpace = codec->computeOutputColorSpace(decodeColorType); + sk_sp<SkColorSpace> decodeColorSpace = codec->computeOutputColorSpace( + decodeColorType, prefColorSpace); // Set the options and return if the client only wants the size. if (options != NULL) { @@ -427,7 +354,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding env->SetObjectField(options, gOptions_outConfigFieldID, config); env->SetObjectField(options, gOptions_outColorSpaceFieldID, - getColorSpace(env, decodeColorSpace, decodeColorType)); + GraphicsJNI::getColorSpace(env, decodeColorSpace, decodeColorType)); if (onlyDecodeSize) { return nullptr; @@ -616,7 +543,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding 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 { @@ -795,6 +722,8 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) { gOptions_sampleSizeFieldID = GetFieldIDOrDie(env, options_class, "inSampleSize", "I"); gOptions_configFieldID = GetFieldIDOrDie(env, options_class, "inPreferredConfig", "Landroid/graphics/Bitmap$Config;"); + gOptions_colorSpaceFieldID = GetFieldIDOrDie(env, options_class, "inPreferredColorSpace", + "Landroid/graphics/ColorSpace;"); gOptions_premultipliedFieldID = GetFieldIDOrDie(env, options_class, "inPremultiplied", "Z"); gOptions_mutableFieldID = GetFieldIDOrDie(env, options_class, "inMutable", "Z"); gOptions_ditherFieldID = GetFieldIDOrDie(env, options_class, "inDither", "Z"); @@ -827,29 +756,6 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) { gBitmapConfig_nativeToConfigMethodID = GetStaticMethodIDOrDie(env, gBitmapConfig_class, "nativeToConfig", "(I)Landroid/graphics/Bitmap$Config;"); - gColorSpace_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ColorSpace")); - gColorSpace_getMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class, - "get", "(Landroid/graphics/ColorSpace$Named;)Landroid/graphics/ColorSpace;"); - gColorSpace_matchMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class, "match", - "([FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/ColorSpace;"); - - gColorSpaceRGB_class = MakeGlobalRefOrDie(env, - FindClassOrDie(env, "android/graphics/ColorSpace$Rgb")); - gColorSpaceRGB_constructorMethodID = GetMethodIDOrDie(env, gColorSpaceRGB_class, - "<init>", "(Ljava/lang/String;[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)V"); - - gColorSpace_Named_class = MakeGlobalRefOrDie(env, - FindClassOrDie(env, "android/graphics/ColorSpace$Named")); - gColorSpace_Named_sRGBFieldID = GetStaticFieldIDOrDie(env, - gColorSpace_Named_class, "SRGB", "Landroid/graphics/ColorSpace$Named;"); - gColorSpace_Named_LinearExtendedSRGBFieldID = GetStaticFieldIDOrDie(env, - gColorSpace_Named_class, "LINEAR_EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;"); - - gTransferParameters_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, - "android/graphics/ColorSpace$Rgb$TransferParameters")); - gTransferParameters_constructorMethodID = GetMethodIDOrDie(env, gTransferParameters_class, - "<init>", "(DDDDDDD)V"); - return android::RegisterMethodsOrDie(env, "android/graphics/BitmapFactory", gMethods, NELEM(gMethods)); } diff --git a/core/jni/android/graphics/BitmapFactory.h b/core/jni/android/graphics/BitmapFactory.h index 76db41dca53f..1ee49fa0af77 100644 --- a/core/jni/android/graphics/BitmapFactory.h +++ b/core/jni/android/graphics/BitmapFactory.h @@ -8,6 +8,7 @@ extern jclass gOptions_class; extern jfieldID gOptions_justBoundsFieldID; extern jfieldID gOptions_sampleSizeFieldID; extern jfieldID gOptions_configFieldID; +extern jfieldID gOptions_colorSpaceFieldID; extern jfieldID gOptions_premultipliedFieldID; extern jfieldID gOptions_ditherFieldID; extern jfieldID gOptions_purgeableFieldID; @@ -17,9 +18,14 @@ extern jfieldID gOptions_preferQualityOverSpeedFieldID; extern jfieldID gOptions_widthFieldID; extern jfieldID gOptions_heightFieldID; extern jfieldID gOptions_mimeFieldID; +extern jfieldID gOptions_outConfigFieldID; +extern jfieldID gOptions_outColorSpaceFieldID; extern jfieldID gOptions_mCancelID; extern jfieldID gOptions_bitmapFieldID; +extern jclass gBitmapConfig_class; +extern jmethodID gBitmapConfig_nativeToConfigMethodID; + jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format); jobject decodeBitmap(JNIEnv* env, void* data, size_t size); diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp index 3247851a0ede..9355cfcdb0d3 100644 --- a/core/jni/android/graphics/BitmapRegionDecoder.cpp +++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp @@ -132,11 +132,14 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in bool requireUnpremul = false; jobject javaBitmap = NULL; bool isHardware = false; + sk_sp<SkColorSpace> colorSpace = nullptr; // Update the default options with any options supplied by the client. if (NULL != options) { sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID); jobject jconfig = env->GetObjectField(options, gOptions_configFieldID); colorType = GraphicsJNI::getNativeBitmapColorType(env, jconfig); + jobject jcolorSpace = env->GetObjectField(options, gOptions_colorSpaceFieldID); + colorSpace = GraphicsJNI::getNativeColorSpace(env, jcolorSpace); isHardware = GraphicsJNI::isHardwareConfig(env, jconfig); requireUnpremul = !env->GetBooleanField(options, gOptions_premultipliedFieldID); javaBitmap = env->GetObjectField(options, gOptions_bitmapFieldID); @@ -148,8 +151,16 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in env->SetIntField(options, gOptions_widthFieldID, -1); env->SetIntField(options, gOptions_heightFieldID, -1); env->SetObjectField(options, gOptions_mimeFieldID, 0); + env->SetObjectField(options, gOptions_outConfigFieldID, 0); + env->SetObjectField(options, gOptions_outColorSpaceFieldID, 0); } + SkBitmapRegionDecoder* brd = reinterpret_cast<SkBitmapRegionDecoder*>(brdHandle); + + SkColorType decodeColorType = brd->computeOutputColorType(colorType); + sk_sp<SkColorSpace> decodeColorSpace = brd->computeOutputColorSpace( + decodeColorType, colorSpace); + // Recycle a bitmap if possible. android::Bitmap* recycledBitmap = nullptr; size_t recycledBytes = 0; @@ -168,17 +179,16 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in if (javaBitmap) { allocator = &recycleAlloc; // We are required to match the color type of the recycled bitmap. - colorType = recycledBitmap->info().colorType(); + decodeColorType = recycledBitmap->info().colorType(); } else { allocator = &heapAlloc; } // Decode the region. SkIRect subset = SkIRect::MakeXYWH(inputX, inputY, inputWidth, inputHeight); - SkBitmapRegionDecoder* brd = - reinterpret_cast<SkBitmapRegionDecoder*>(brdHandle); SkBitmap bitmap; - if (!brd->decodeRegion(&bitmap, allocator, subset, sampleSize, colorType, requireUnpremul)) { + if (!brd->decodeRegion(&bitmap, allocator, subset, sampleSize, + decodeColorType, requireUnpremul, decodeColorSpace)) { return nullObjectReturn("Failed to decode region."); } @@ -186,16 +196,29 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in if (NULL != options) { env->SetIntField(options, gOptions_widthFieldID, bitmap.width()); env->SetIntField(options, gOptions_heightFieldID, bitmap.height()); + env->SetObjectField(options, gOptions_mimeFieldID, encodedFormatToString(env, (SkEncodedImageFormat)brd->getEncodedFormat())); if (env->ExceptionCheck()) { return nullObjectReturn("OOM in encodedFormatToString()"); } + + jint configID = GraphicsJNI::colorTypeToLegacyBitmapConfig(decodeColorType); + if (isHardware) { + configID = GraphicsJNI::kHardware_LegacyBitmapConfig; + } + jobject config = env->CallStaticObjectMethod(gBitmapConfig_class, + gBitmapConfig_nativeToConfigMethodID, configID); + env->SetObjectField(options, gOptions_outConfigFieldID, config); + + env->SetObjectField(options, gOptions_outColorSpaceFieldID, + GraphicsJNI::getColorSpace(env, decodeColorSpace, decodeColorType)); } // If we may have reused a bitmap, we need to indicate that the pixels have changed. if (javaBitmap) { recycleAlloc.copyIfNecessary(); + bitmap::reinitBitmap(env, javaBitmap, recycledBitmap->info(), !requireUnpremul); return javaBitmap; } diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp index 3010dc1699e1..fc90fb37ff7e 100644 --- a/core/jni/android/graphics/FontFamily.cpp +++ b/core/jni/android/graphics/FontFamily.cpp @@ -45,21 +45,24 @@ namespace android { 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 @@ static jlong FontFamily_create(jlong builderPtr) { 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 void FontFamily_addAxisValue(jlong builderPtr, jint tag, jfloat value) { 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/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp index e66587a9d8fe..b11fd4fce714 100644 --- a/core/jni/android/graphics/Graphics.cpp +++ b/core/jni/android/graphics/Graphics.cpp @@ -6,6 +6,7 @@ #include "jni.h" #include "JNIHelp.h" #include "GraphicsJNI.h" +#include "core_jni_helpers.h" #include "SkCanvas.h" #include "SkMath.h" @@ -17,6 +18,8 @@ #include <Caches.h> #include <TextureCache.h> +using namespace android; + void doThrowNPE(JNIEnv* env) { jniThrowNullPointerException(env, NULL); } @@ -178,6 +181,32 @@ static jclass gVMRuntime_class; static jmethodID gVMRuntime_newNonMovableArray; static jmethodID gVMRuntime_addressOf; +static jfieldID gTransferParams_aFieldID; +static jfieldID gTransferParams_bFieldID; +static jfieldID gTransferParams_cFieldID; +static jfieldID gTransferParams_dFieldID; +static jfieldID gTransferParams_eFieldID; +static jfieldID gTransferParams_fFieldID; +static jfieldID gTransferParams_gFieldID; + +static jclass gColorSpace_class; +static jfieldID gColorSpace_IlluminantD50FieldID; +static jmethodID gColorSpace_adaptMethodID; +static jmethodID gColorSpace_getMethodID; +static jmethodID gColorSpace_matchMethodID; + +static jclass gColorSpaceRGB_class; +static jmethodID gColorSpaceRGB_getTransferParametersMethodID; +static jmethodID gColorSpaceRGB_getTransformMethodID; +static jmethodID gColorSpaceRGB_constructorMethodID; + +static jclass gColorSpace_Named_class; +static jfieldID gColorSpace_Named_sRGBFieldID; +static jfieldID gColorSpace_Named_LinearExtendedSRGBFieldID; + +static jclass gTransferParameters_class; +static jmethodID gTransferParameters_constructorMethodID; + /////////////////////////////////////////////////////////////////////////////// void GraphicsJNI::get_jrect(JNIEnv* env, jobject obj, int* L, int* T, int* R, int* B) @@ -328,7 +357,7 @@ SkColorType GraphicsJNI::legacyBitmapConfigToColorType(jint legacyConfig) { } void GraphicsJNI::getSkBitmap(JNIEnv* env, jobject bitmap, SkBitmap* outBitmap) { - android::bitmap::toBitmap(env, bitmap).getSkBitmap(outBitmap); + bitmap::toBitmap(env, bitmap).getSkBitmap(outBitmap); } SkPixelRef* GraphicsJNI::refSkPixelRef(JNIEnv* env, jobject jbitmap) { @@ -464,6 +493,125 @@ bool GraphicsJNI::isColorSpaceSRGB(SkColorSpace* colorSpace) { return colorSpace == nullptr || colorSpace->isSRGB(); } +SkColorSpaceTransferFn GraphicsJNI::getNativeTransferParameters(JNIEnv* env, jobject transferParams) { + SkColorSpaceTransferFn p; + p.fA = (float) env->GetDoubleField(transferParams, gTransferParams_aFieldID); + p.fB = (float) env->GetDoubleField(transferParams, gTransferParams_bFieldID); + p.fC = (float) env->GetDoubleField(transferParams, gTransferParams_cFieldID); + p.fD = (float) env->GetDoubleField(transferParams, gTransferParams_dFieldID); + p.fE = (float) env->GetDoubleField(transferParams, gTransferParams_eFieldID); + p.fF = (float) env->GetDoubleField(transferParams, gTransferParams_fFieldID); + p.fG = (float) env->GetDoubleField(transferParams, gTransferParams_gFieldID); + return p; +} + +SkMatrix44 GraphicsJNI::getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50) { + SkMatrix44 xyzMatrix(SkMatrix44::kIdentity_Constructor); + jfloat* array = env->GetFloatArrayElements(xyzD50, NULL); + xyzMatrix.setFloat(0, 0, array[0]); + xyzMatrix.setFloat(1, 0, array[1]); + xyzMatrix.setFloat(2, 0, array[2]); + xyzMatrix.setFloat(0, 1, array[3]); + xyzMatrix.setFloat(1, 1, array[4]); + xyzMatrix.setFloat(2, 1, array[5]); + xyzMatrix.setFloat(0, 2, array[6]); + xyzMatrix.setFloat(1, 2, array[7]); + xyzMatrix.setFloat(2, 2, array[8]); + env->ReleaseFloatArrayElements(xyzD50, array, 0); + return xyzMatrix; +} + +sk_sp<SkColorSpace> GraphicsJNI::getNativeColorSpace(JNIEnv* env, jobject colorSpace) { + if (colorSpace == nullptr) return nullptr; + if (!env->IsInstanceOf(colorSpace, gColorSpaceRGB_class)) { + doThrowIAE(env, "The color space must be an RGB color space"); + } + + jobject transferParams = env->CallObjectMethod(colorSpace, + gColorSpaceRGB_getTransferParametersMethodID); + if (transferParams == nullptr) { + doThrowIAE(env, "The color space must use an ICC parametric transfer function"); + } + + jfloatArray illuminantD50 = (jfloatArray) env->GetStaticObjectField(gColorSpace_class, + gColorSpace_IlluminantD50FieldID); + jobject colorSpaceD50 = env->CallStaticObjectMethod(gColorSpace_class, + gColorSpace_adaptMethodID, colorSpace, illuminantD50); + + jfloatArray xyzD50 = (jfloatArray) env->CallObjectMethod(colorSpaceD50, + gColorSpaceRGB_getTransformMethodID); + + SkMatrix44 xyzMatrix = getNativeXYZMatrix(env, xyzD50); + SkColorSpaceTransferFn transferFunction = getNativeTransferParameters(env, transferParams); + + return SkColorSpace::MakeRGB(transferFunction, xyzMatrix); +} + + +jobject GraphicsJNI::getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColorSpace, + SkColorType decodeColorType) { + jobject colorSpace = nullptr; + + // No need to match, we know what the output color space will be + if (decodeColorType == kRGBA_F16_SkColorType) { + jobject linearExtendedSRGB = env->GetStaticObjectField( + gColorSpace_Named_class, gColorSpace_Named_LinearExtendedSRGBFieldID); + colorSpace = env->CallStaticObjectMethod(gColorSpace_class, + gColorSpace_getMethodID, linearExtendedSRGB); + } else { + // Same here, no need to match + if (decodeColorSpace->isSRGB()) { + jobject sRGB = env->GetStaticObjectField( + gColorSpace_Named_class, gColorSpace_Named_sRGBFieldID); + colorSpace = env->CallStaticObjectMethod(gColorSpace_class, + gColorSpace_getMethodID, sRGB); + } else if (decodeColorSpace.get() != nullptr) { + // Try to match against known RGB color spaces using the CIE XYZ D50 + // conversion matrix and numerical transfer function parameters + SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor); + LOG_ALWAYS_FATAL_IF(!decodeColorSpace->toXYZD50(&xyzMatrix)); + + SkColorSpaceTransferFn transferParams; + // We can only handle numerical transfer functions at the moment + LOG_ALWAYS_FATAL_IF(!decodeColorSpace->isNumericalTransferFn(&transferParams)); + + jobject params = env->NewObject(gTransferParameters_class, + gTransferParameters_constructorMethodID, + transferParams.fA, transferParams.fB, transferParams.fC, + transferParams.fD, transferParams.fE, transferParams.fF, + transferParams.fG); + + jfloatArray xyzArray = env->NewFloatArray(9); + jfloat xyz[9] = { + xyzMatrix.getFloat(0, 0), + xyzMatrix.getFloat(1, 0), + xyzMatrix.getFloat(2, 0), + xyzMatrix.getFloat(0, 1), + xyzMatrix.getFloat(1, 1), + xyzMatrix.getFloat(2, 1), + xyzMatrix.getFloat(0, 2), + xyzMatrix.getFloat(1, 2), + xyzMatrix.getFloat(2, 2) + }; + env->SetFloatArrayRegion(xyzArray, 0, 9, xyz); + + colorSpace = env->CallStaticObjectMethod(gColorSpace_class, + gColorSpace_matchMethodID, xyzArray, params); + + if (colorSpace == nullptr) { + // We couldn't find an exact match, let's create a new color space + // instance with the 3x3 conversion matrix and transfer function + colorSpace = env->NewObject(gColorSpaceRGB_class, + gColorSpaceRGB_constructorMethodID, + env->NewStringUTF("Unknown"), xyzArray, params); + } + + env->DeleteLocalRef(xyzArray); + } + } + return colorSpace; +} + /////////////////////////////////////////////////////////////////////////////// bool HeapAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) { mStorage = android::Bitmap::allocateHeapBitmap(bitmap, ctable); @@ -510,7 +658,11 @@ bool RecyclingClippingPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTab // mRecycledBitmap->info() for the SkImageInfo. According to the // specification for BitmapRegionDecoder, we are not allowed to change // the SkImageInfo. - mRecycledBitmap->reconfigure(mRecycledBitmap->info(), rowBytes, ctable); + // We can (must) preserve the color space since it doesn't affect the + // storage needs + mRecycledBitmap->reconfigure( + mRecycledBitmap->info().makeColorSpace(bitmap->refColorSpace()), + rowBytes, ctable); // Give the bitmap the same pixelRef as mRecycledBitmap. // skbug.com/4538: We also need to make sure that the rowBytes on the pixel ref @@ -577,74 +729,97 @@ bool AshmemPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) //////////////////////////////////////////////////////////////////////////////// -static jclass make_globalref(JNIEnv* env, const char classname[]) -{ - jclass c = env->FindClass(classname); - SkASSERT(c); - return (jclass) env->NewGlobalRef(c); -} - -static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz, - const char fieldname[], const char type[]) -{ - jfieldID id = env->GetFieldID(clazz, fieldname, type); - SkASSERT(id); - return id; -} - int register_android_graphics_Graphics(JNIEnv* env) { jmethodID m; jclass c; - gRect_class = make_globalref(env, "android/graphics/Rect"); - gRect_leftFieldID = getFieldIDCheck(env, gRect_class, "left", "I"); - gRect_topFieldID = getFieldIDCheck(env, gRect_class, "top", "I"); - gRect_rightFieldID = getFieldIDCheck(env, gRect_class, "right", "I"); - gRect_bottomFieldID = getFieldIDCheck(env, gRect_class, "bottom", "I"); + gRect_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Rect")); + gRect_leftFieldID = GetFieldIDOrDie(env, gRect_class, "left", "I"); + gRect_topFieldID = GetFieldIDOrDie(env, gRect_class, "top", "I"); + gRect_rightFieldID = GetFieldIDOrDie(env, gRect_class, "right", "I"); + gRect_bottomFieldID = GetFieldIDOrDie(env, gRect_class, "bottom", "I"); - gRectF_class = make_globalref(env, "android/graphics/RectF"); - gRectF_leftFieldID = getFieldIDCheck(env, gRectF_class, "left", "F"); - gRectF_topFieldID = getFieldIDCheck(env, gRectF_class, "top", "F"); - gRectF_rightFieldID = getFieldIDCheck(env, gRectF_class, "right", "F"); - gRectF_bottomFieldID = getFieldIDCheck(env, gRectF_class, "bottom", "F"); + gRectF_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/RectF")); + gRectF_leftFieldID = GetFieldIDOrDie(env, gRectF_class, "left", "F"); + gRectF_topFieldID = GetFieldIDOrDie(env, gRectF_class, "top", "F"); + gRectF_rightFieldID = GetFieldIDOrDie(env, gRectF_class, "right", "F"); + gRectF_bottomFieldID = GetFieldIDOrDie(env, gRectF_class, "bottom", "F"); - gPoint_class = make_globalref(env, "android/graphics/Point"); - gPoint_xFieldID = getFieldIDCheck(env, gPoint_class, "x", "I"); - gPoint_yFieldID = getFieldIDCheck(env, gPoint_class, "y", "I"); + gPoint_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Point")); + gPoint_xFieldID = GetFieldIDOrDie(env, gPoint_class, "x", "I"); + gPoint_yFieldID = GetFieldIDOrDie(env, gPoint_class, "y", "I"); - gPointF_class = make_globalref(env, "android/graphics/PointF"); - gPointF_xFieldID = getFieldIDCheck(env, gPointF_class, "x", "F"); - gPointF_yFieldID = getFieldIDCheck(env, gPointF_class, "y", "F"); + gPointF_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/PointF")); + gPointF_xFieldID = GetFieldIDOrDie(env, gPointF_class, "x", "F"); + gPointF_yFieldID = GetFieldIDOrDie(env, gPointF_class, "y", "F"); - gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder"); - gBitmapRegionDecoder_constructorMethodID = env->GetMethodID(gBitmapRegionDecoder_class, "<init>", "(J)V"); + gBitmapRegionDecoder_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/BitmapRegionDecoder")); + gBitmapRegionDecoder_constructorMethodID = GetMethodIDOrDie(env, gBitmapRegionDecoder_class, "<init>", "(J)V"); - gBitmapConfig_class = make_globalref(env, "android/graphics/Bitmap$Config"); - gBitmapConfig_nativeInstanceID = getFieldIDCheck(env, gBitmapConfig_class, - "nativeInt", "I"); + gBitmapConfig_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Bitmap$Config")); + gBitmapConfig_nativeInstanceID = GetFieldIDOrDie(env, gBitmapConfig_class, "nativeInt", "I"); - gCanvas_class = make_globalref(env, "android/graphics/Canvas"); - gCanvas_nativeInstanceID = getFieldIDCheck(env, gCanvas_class, "mNativeCanvasWrapper", "J"); + gCanvas_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Canvas")); + gCanvas_nativeInstanceID = GetFieldIDOrDie(env, gCanvas_class, "mNativeCanvasWrapper", "J"); - gPicture_class = make_globalref(env, "android/graphics/Picture"); - gPicture_nativeInstanceID = getFieldIDCheck(env, gPicture_class, "mNativePicture", "J"); + gPicture_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Picture")); + gPicture_nativeInstanceID = GetFieldIDOrDie(env, gPicture_class, "mNativePicture", "J"); - gRegion_class = make_globalref(env, "android/graphics/Region"); - gRegion_nativeInstanceID = getFieldIDCheck(env, gRegion_class, "mNativeRegion", "J"); - gRegion_constructorMethodID = env->GetMethodID(gRegion_class, "<init>", - "(JI)V"); + gRegion_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Region")); + gRegion_nativeInstanceID = GetFieldIDOrDie(env, gRegion_class, "mNativeRegion", "J"); + gRegion_constructorMethodID = GetMethodIDOrDie(env, gRegion_class, "<init>", "(JI)V"); c = env->FindClass("java/lang/Byte"); gByte_class = (jclass) env->NewGlobalRef( env->GetStaticObjectField(c, env->GetStaticFieldID(c, "TYPE", "Ljava/lang/Class;"))); - gVMRuntime_class = make_globalref(env, "dalvik/system/VMRuntime"); + gVMRuntime_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "dalvik/system/VMRuntime")); m = env->GetStaticMethodID(gVMRuntime_class, "getRuntime", "()Ldalvik/system/VMRuntime;"); gVMRuntime = env->NewGlobalRef(env->CallStaticObjectMethod(gVMRuntime_class, m)); - gVMRuntime_newNonMovableArray = env->GetMethodID(gVMRuntime_class, "newNonMovableArray", + gVMRuntime_newNonMovableArray = GetMethodIDOrDie(env, gVMRuntime_class, "newNonMovableArray", "(Ljava/lang/Class;I)Ljava/lang/Object;"); - gVMRuntime_addressOf = env->GetMethodID(gVMRuntime_class, "addressOf", "(Ljava/lang/Object;)J"); + gVMRuntime_addressOf = GetMethodIDOrDie(env, gVMRuntime_class, "addressOf", "(Ljava/lang/Object;)J"); + + jclass transfer_params_class = FindClassOrDie(env, "android/graphics/ColorSpace$Rgb$TransferParameters"); + gTransferParams_aFieldID = GetFieldIDOrDie(env, transfer_params_class, "a", "D"); + gTransferParams_bFieldID = GetFieldIDOrDie(env, transfer_params_class, "b", "D"); + gTransferParams_cFieldID = GetFieldIDOrDie(env, transfer_params_class, "c", "D"); + gTransferParams_dFieldID = GetFieldIDOrDie(env, transfer_params_class, "d", "D"); + gTransferParams_eFieldID = GetFieldIDOrDie(env, transfer_params_class, "e", "D"); + gTransferParams_fFieldID = GetFieldIDOrDie(env, transfer_params_class, "f", "D"); + gTransferParams_gFieldID = GetFieldIDOrDie(env, transfer_params_class, "g", "D"); + + gColorSpace_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ColorSpace")); + gColorSpace_IlluminantD50FieldID = GetStaticFieldIDOrDie(env, + gColorSpace_class, "ILLUMINANT_D50", "[F"); + gColorSpace_adaptMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class, "adapt", + "(Landroid/graphics/ColorSpace;[F)Landroid/graphics/ColorSpace;"); + gColorSpace_getMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class, + "get", "(Landroid/graphics/ColorSpace$Named;)Landroid/graphics/ColorSpace;"); + gColorSpace_matchMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class, "match", + "([FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/ColorSpace;"); + + gColorSpaceRGB_class = MakeGlobalRefOrDie(env, + FindClassOrDie(env, "android/graphics/ColorSpace$Rgb")); + gColorSpaceRGB_constructorMethodID = GetMethodIDOrDie(env, gColorSpaceRGB_class, + "<init>", "(Ljava/lang/String;[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)V"); + gColorSpaceRGB_getTransferParametersMethodID = GetMethodIDOrDie(env, gColorSpaceRGB_class, + "getTransferParameters", "()Landroid/graphics/ColorSpace$Rgb$TransferParameters;"); + gColorSpaceRGB_getTransformMethodID = GetMethodIDOrDie(env, gColorSpaceRGB_class, + "getTransform", "()[F"); + + gColorSpace_Named_class = MakeGlobalRefOrDie(env, + FindClassOrDie(env, "android/graphics/ColorSpace$Named")); + gColorSpace_Named_sRGBFieldID = GetStaticFieldIDOrDie(env, + gColorSpace_Named_class, "SRGB", "Landroid/graphics/ColorSpace$Named;"); + gColorSpace_Named_LinearExtendedSRGBFieldID = GetStaticFieldIDOrDie(env, + gColorSpace_Named_class, "LINEAR_EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;"); + + gTransferParameters_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, + "android/graphics/ColorSpace$Rgb$TransferParameters")); + gTransferParameters_constructorMethodID = GetMethodIDOrDie(env, gTransferParameters_class, + "<init>", "(DDDDDDD)V"); return 0; } diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h index 7d7c88159a55..7fbea2589730 100644 --- a/core/jni/android/graphics/GraphicsJNI.h +++ b/core/jni/android/graphics/GraphicsJNI.h @@ -10,6 +10,7 @@ #include "SkPoint.h" #include "SkRect.h" #include "SkColorSpace.h" +#include "SkMatrix44.h" #include <jni.h> #include <hwui/Canvas.h> #include <hwui/Bitmap.h> @@ -112,6 +113,13 @@ public: static sk_sp<SkColorSpace> linearColorSpace(); static sk_sp<SkColorSpace> colorSpaceForType(SkColorType type); static bool isColorSpaceSRGB(SkColorSpace* colorSpace); + + static SkColorSpaceTransferFn getNativeTransferParameters(JNIEnv* env, jobject transferParams); + static SkMatrix44 getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50); + static sk_sp<SkColorSpace> getNativeColorSpace(JNIEnv* env, jobject colorSpace); + + static jobject getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColorSpace, + SkColorType decodeColorType); }; class HeapAllocator : public SkBRDAllocator { diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp index d0b07d0168df..86c97a1e558c 100644 --- a/core/jni/android/graphics/Typeface.cpp +++ b/core/jni/android/graphics/Typeface.cpp @@ -42,6 +42,13 @@ static jlong Typeface_createFromTypeface(JNIEnv* env, jobject, jlong familyHandl 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 @@ static jint Typeface_getStyle(JNIEnv* env, jobject obj, jlong faceHandle) { 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 @@ static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArr 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 jobject Typeface_getSupportedAxes(JNIEnv *env, jobject, jlong faceHandle) 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_Parcel.cpp b/core/jni/android_os_Parcel.cpp index 8f7908a0e048..d740a76f8c2e 100644 --- a/core/jni/android_os_Parcel.cpp +++ b/core/jni/android_os_Parcel.cpp @@ -617,6 +617,21 @@ static jlong android_os_Parcel_unmarshall(JNIEnv* env, jclass clazz, jlong nativ 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 @@ static const JNINativeMethod gParcelMethods[] = { {"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 000000000000..9491a1ecdad3 --- /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); + 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 abcd1e7049ef..1aed501335c4 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -192,18 +192,12 @@ static void report_exception(JNIEnv* env, jthrowable excep, const char* msg) 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 20dfe7809728..56505afc78b2 100644 --- a/core/jni/android_util_Log.cpp +++ b/core/jni/android_util_Log.cpp @@ -58,16 +58,7 @@ static jboolean android_util_Log_isLoggable(JNIEnv* env, jobject clazz, jstring 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 dc365b41d119..8b8231447643 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -289,6 +289,14 @@ static void nativeSetLayer(JNIEnv* env, jclass clazz, jlong nativeObject, jint z } } +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 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (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 98c9e781efee..ce951defadbc 100644 --- a/core/proto/android/providers/settings.proto +++ b/core/proto/android/providers/settings.proto @@ -499,7 +499,7 @@ message SecureSettingsProto { 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 bd7f79e12e3f..8869593c2194 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 --> @@ -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 --> @@ -3532,6 +3556,11 @@ android:process=":ui"> </activity> + <activity android:name="com.android.settings.notification.NotificationAccessConfirmationActivity" + android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert" + android:excludeFromRecents="true"> + </activity> + <receiver android:name="com.android.server.BootReceiver" android:systemUserOnly="true"> <intent-filter android:priority="1000"> diff --git a/core/res/res/drawable-hdpi/ic_accessibility_magnification.png b/core/res/res/drawable-hdpi/ic_accessibility_magnification.png Binary files differnew file mode 100755 index 000000000000..a91bc6ec90ed --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_accessibility_magnification.png diff --git a/core/res/res/drawable-mdpi/ic_accessibility_magnification.png b/core/res/res/drawable-mdpi/ic_accessibility_magnification.png Binary files differnew file mode 100755 index 000000000000..9ec51075a5ed --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_accessibility_magnification.png diff --git a/core/res/res/drawable-xhdpi/ic_accessibility_magnification.png b/core/res/res/drawable-xhdpi/ic_accessibility_magnification.png Binary files differnew file mode 100755 index 000000000000..0b3a32ed1792 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_accessibility_magnification.png diff --git a/core/res/res/drawable-xxhdpi/ic_accessibility_magnification.png b/core/res/res/drawable-xxhdpi/ic_accessibility_magnification.png Binary files differnew file mode 100755 index 000000000000..3eeb1c9f8dd8 --- /dev/null +++ b/core/res/res/drawable-xxhdpi/ic_accessibility_magnification.png diff --git a/core/res/res/drawable-xxxhdpi/ic_accessibility_magnification.png b/core/res/res/drawable-xxxhdpi/ic_accessibility_magnification.png Binary files differnew file mode 100755 index 000000000000..7d376126b4d7 --- /dev/null +++ b/core/res/res/drawable-xxxhdpi/ic_accessibility_magnification.png diff --git a/packages/SystemUI/res/anim/tv_pip_overlay_fade_in_animation.xml b/core/res/res/drawable/autofill_dataset_picker_background.xml index 33bceaa77ce9..b5617e177feb 100644 --- a/packages/SystemUI/res/anim/tv_pip_overlay_fade_in_animation.xml +++ b/core/res/res/drawable/autofill_dataset_picker_background.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 The Android Open Source Project +<!-- Copyright (C) 2017 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,8 +14,9 @@ limitations under the License. --> -<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" - android:propertyName="alpha" - android:valueTo="1" - android:interpolator="@android:interpolator/fast_out_slow_in" - android:duration="350" /> +<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 c7aacb92af60..3a2815c2eea8 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 f020112d1329..33efbbac8690 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 133265b60e1f..528efca49fc3 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 59e183f4f1c1..2155c8f4061d 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 07d03ce98a1f..41a0153c129a 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 06ac6814e1e4..570e3c40966b 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 1d137d0f92b5..6da988aaa15a 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 88286333f7d2..86bb518423ef 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 d12a104b49e2..2702b13886d3 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 2a77fac6a568..cfb81771683f 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 3a5fdec17958..83db42c202e0 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 92294dc466ac..6b8fa7878877 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 ada00d28c024..0a63cdf968b8 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 eab70785007a..0b9b95dde278 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 e66a146f5c8e..1708834ce416 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 a0ebdebe6ea0..6e930ffc1c0b 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 5805f8334b42..99fa2e56a525 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 500754d6ae91..0a6a7d5554bf 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 500754d6ae91..0a6a7d5554bf 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 500754d6ae91..0a6a7d5554bf 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 feccac999e86..df55b6cac142 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 f5bb4a0aa04c..c46146d01637 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 aa73458241c8..4bd9ef8796e8 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 d151045a6f2d..5c1b423ca721 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 edf9bf8d11de..7312fa6c0099 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 af73c15e1aef..5d12753967a9 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 1e25181a1585..6bcc8ae0437e 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 25bd58a1f908..fdea62aa9283 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 a726854f20b0..eb220f41b49b 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 f3e52e1b0122..82481d5d8b94 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 0e94ce3885ac..5e7edfad64db 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 7ed77949db28..d95f8c884f8a 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 8ca82d3abffa..9e5c53e289a8 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 b97bb1be1752..d6a75d570459 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 62c1703ef18f..cd4e63ef2c3c 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 b5acbecc21fe..d87725e14d51 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 ffd363ce8bc2..06850c849095 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 de88b08eb0ab..846ce5640788 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 a600652a87a7..f627b22ece5f 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 b9d496b54818..6157f6b4588a 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 01088aa04f68..bf7fdf6ba1c3 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 5e56ed067f5d..7e97f956010b 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 27b629a74a3f..94f4df8b2663 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 24e4676e166f..a24eb0666828 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 7e417f19e643..f4d15aa1e69f 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 0603d1c69254..e57c85147780 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 2345bdf0c583..e98c66cfefc5 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 9e8a34edf264..4251a52b7ba9 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 b073652ee401..2fb9553a45f8 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 84aa13c61adb..8f80f1ad9c7d 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 4cd99a30d38a..88aacdae5da4 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 2f77ffc8c9a7..47696761bb16 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 9211121456cc..e414985cad35 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 e8e0da3c80d9..52524226fd46 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 4db1c7ee5149..9c638ec61f72 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 fe910aeff2bf..86c18d6ac7db 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 1bfc77aa2454..af8c0a296e8b 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 3fe7fb0d3a0f..71fd285222a3 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 5f61e89af749..dee76d573d27 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 9c059f9c3be6..2212c06178c7 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 8d89c17bb731..241b2fe61b9e 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 9c059f9c3be6..2212c06178c7 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 007ac8cdbfdb..f347a8ebe075 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 c64f92979185..3ac621a7c3e5 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 2a76c979a7ee..6c595fb763a2 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 a1b3ad4fa7e6..af5268e3ccf4 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 f003c0b814ec..877add7727af 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 05feb1ae8fac..b645553c0b60 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 8c7ad9329655..6e13582897da 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 cbb84afc7764..90dfd681afd1 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 7cd8c3ad316f..664a038a0806 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 16ced0a0625c..1f817576ce28 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 c143d4fb617b..0fb49d57bbc8 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 f308bcfab3df..ed22eef67566 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 fa02f8f5c8ce..8b5962f70c57 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 4275e5cb6046..7be1384f8a66 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 187904dbff84..6c5846d9eabe 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 f87cf54ce9b0..ccaa412ab181 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 f841f1ce6e71..ee2438f42d85 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 ba72144ddf2e..c85f41393ba6 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 8f110d1f40a3..1daecddef701 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 556a5c77a0d5..902cfea8f65b 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 c16d59a58454..91c5df38c28d 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 e05aebf90588..52898345796b 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 d26d952224f1..4fb21fae8908 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. @@ -1372,6 +1371,22 @@ Corresponds to {@link android.view.inputmethod.EditorInfo#IME_ACTION_PREVIOUS}. --> <flag name="actionPrevious" value="0x00000007" /> + <!-- Used to request that the IME should not update any personalized data such as typing + history and personalized language model based on what the user typed on this text + editing object. Typical use cases are: + <ul> + <li>When the application is in a special mode, where user's activities are expected + to be not recorded in the application's history. Some web browsers and chat + applications may have this kind of modes.</li> + <li>When storing typing history does not make much sense. Specifying this flag in + typing games may help to avoid typing history from being filled up with words that + the user is less likely to type in their daily life. Another example is that when + the application already knows that the expected input is not a valid word (e.g. a + promotion code that is not a valid word in any natural language).</li> + </ul> + <p>Applications need to be aware that the flag is not a guarantee, and some IMEs may + not respect it.</p> --> + <flag name="flagNoPersonalizedLearning" value="0x1000000" /> <!-- Used to request that the IME never go into fullscreen mode. Applications need to be aware that the flag is not a guarantee, and not all IMEs will respect it. @@ -2049,6 +2064,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. --> @@ -2294,18 +2320,7 @@ <enum name="auto" value="0x00000010" /> </attr> - <!-- Controls the autofill behavior for this view. --> - <attr name="autofillMode"> - <!-- Inherit the behavior from the parent. If there is no parent it is auto. This is the - default value for this attribute.--> - <enum name="inherit" value="0" /> - <!-- Allows this view to automatically trigger an autofill request when it get focus. - --> - <enum name="auto" value="1" /> - <!-- Do not trigger an autofill request when this view is focused. The user can still - manually force an autofill request for this view. --> - <enum name="manual" value="2" /> - </attr> + <attr name="__removed3" /> <!-- Describes the content of a view so that a autofill service can fill in the appropriate data. Multiple hints can be combined in a comma separated list or an array of strings @@ -2953,6 +2968,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 +3232,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 diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 3e4b66d780ad..569646820402 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 3dd7ad415baf..45dccb6bfe33 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 1d1fd5e470a2..213d6cafa72b 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" /> @@ -2797,7 +2797,7 @@ <public name="numericModifiers" /> <public name="fontProviderAuthority" /> <public name="fontProviderQuery" /> - <public name="autofillMode" /> + <public name="__removed3" /> <public name="primaryContentAlpha" /> <public name="secondaryContentAlpha" /> <public name="requiredFeature" /> @@ -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 08216742add5..bd350730a8e2 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3000,6 +3000,8 @@ <!-- Do not translate. Default access point SSID used for tethering --> <string name="wifi_tether_configure_ssid_default" translatable="false">AndroidAP</string> + <!-- Do not translate. Default access point SSID used for local only hotspot --> + <string name="wifi_localhotspot_configure_ssid_default" translatable="false">AndroidShare</string> <!-- A notification is shown the first time a connection is attempted on an app owned AP --> <!-- title for this message --> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 7dac18dbda8d..2ae2ca00c167 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -322,6 +322,7 @@ please see styles_device_defaults.xml. <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 @@ please see styles_device_defaults.xml. <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 @@ please see styles_device_defaults.xml. <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 7cb9ba8cd64b..f2da8457601c 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -19,6 +19,9 @@ <!-- Private symbols that we need to reference from framework code. See frameworks/base/core/res/MakeJavaSymbols.sed for how to easily generate this. + + Can be referenced in java code as: com.android.internal.R.<type>.<name> + and in layout xml as: "@*android:<type>/<name>" --> <java-symbol type="id" name="account_name" /> <java-symbol type="id" name="account_row_icon" /> @@ -434,7 +437,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" /> @@ -1004,6 +1006,7 @@ <java-symbol type="string" name="wifi_p2p_turnon_message" /> <java-symbol type="string" name="wifi_p2p_frequency_conflict_message" /> <java-symbol type="string" name="wifi_tether_configure_ssid_default" /> + <java-symbol type="string" name="wifi_localhotspot_configure_ssid_default" /> <java-symbol type="string" name="wifi_watchdog_network_disabled" /> <java-symbol type="string" name="wifi_watchdog_network_disabled_detailed" /> <java-symbol type="string" name="imei" /> @@ -2858,6 +2861,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 +2870,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 +2894,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 9911d9db6c03..e0b4ec5027bb 100644 --- a/core/res/res/values/themes_device_defaults.xml +++ b/core/res/res/values/themes_device_defaults.xml @@ -748,12 +748,12 @@ easier. <!-- @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 9dafa7a02849..86abe9782c09 100644 --- a/core/res/res/values/themes_material.xml +++ b/core/res/res/values/themes_material.xml @@ -214,7 +214,7 @@ please see themes_device_defaults.xml. <!-- 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 @@ please see themes_device_defaults.xml. <!-- 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 59f8ecc278ad..000000000000 --- 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 6bcf8fc43d10..0e1e6ac98672 100644 --- a/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java +++ b/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java @@ -27,6 +27,6 @@ public class BasicAnimatorActivity extends Activity { 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 fba6aaf3f406..000000000000 --- 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 5ade66e59776..7550cb5211b9 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 @@ package android.graphics.drawable; 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 @@ public class AdaptiveIconDrawableTest extends AndroidTestCase { * 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 @@ public class AdaptiveIconDrawableTest extends AndroidTestCase { * 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 @@ public class AdaptiveIconDrawableTest extends AndroidTestCase { } } + /** + * 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 b50955b82b36..b7a48c7e6825 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 @@ public class IconTest extends AndroidTestCase { 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 f4a5e09033ed..43cd373ef850 100644 --- a/core/tests/coretests/src/android/os/BrightnessLimit.java +++ b/core/tests/coretests/src/android/os/BrightnessLimit.java @@ -40,7 +40,7 @@ public class BrightnessLimit extends Activity implements OnClickListener { 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 000000000000..aaaf55ccf799 --- /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 1dd3ef6f012e..ccc8c184fdf7 100644 --- a/core/tests/coretests/src/android/provider/FontsContractTest.java +++ b/core/tests/coretests/src/android/provider/FontsContractTest.java @@ -17,29 +17,29 @@ package android.provider; 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 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> { 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 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> { 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); - - verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE,null); + mProvider.setResultCode(RESULT_CODE_FONT_UNAVAILABLE); + 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_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); - - verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY,null); + mProvider.setResultCode(RESULT_CODE_MALFORMED_QUERY); + 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_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); - - verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND, null); + FontInfo[] fonts = FontsContract.getFontFromProvider( + getMockContext(), request, TestFontsProvider.AUTHORITY, 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); - - verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND, null); - } - - 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); - - verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND, null); + FontInfo[] fonts = FontsContract.getFontFromProvider( + getMockContext(), request, TestFontsProvider.AUTHORITY, null); + + assertNotNull(fonts); + assertEquals(3, 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()); + + 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 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> { 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 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> { 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 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> { 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 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> { 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 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> { 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 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> { 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 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> { 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 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> { 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 782a50f12b2b..d7887d333095 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -473,7 +473,7 @@ public class SettingsBackupTest { 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 fa921071874d..d3c7470bd0f9 100644 --- a/core/tests/coretests/src/android/view/Disabled.java +++ b/core/tests/coretests/src/android/view/Disabled.java @@ -34,16 +34,16 @@ public class Disabled extends Activity implements OnClickListener { 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 a75b23aaee04..58bfb8a77064 100644 --- a/core/tests/coretests/src/android/view/DrawableBgMinSize.java +++ b/core/tests/coretests/src/android/view/DrawableBgMinSize.java @@ -58,14 +58,14 @@ public class DrawableBgMinSize extends Activity implements OnClickListener { 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 6e11ede201db..85ce04fae71b 100644 --- a/core/tests/coretests/src/android/view/PopupWindowVisibility.java +++ b/core/tests/coretests/src/android/view/PopupWindowVisibility.java @@ -45,13 +45,13 @@ public class PopupWindowVisibility extends Activity implements OnClickListener { 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 @@ public class PopupWindowVisibility extends Activity implements OnClickListener { 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 981c6c06ce7f..60bbee483173 100644 --- a/core/tests/coretests/src/android/view/PreDrawListener.java +++ b/core/tests/coretests/src/android/view/PreDrawListener.java @@ -75,9 +75,9 @@ public class PreDrawListener extends Activity implements OnClickListener { 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 97ff252eb034..031568c5a446 100644 --- a/core/tests/coretests/src/android/view/Visibility.java +++ b/core/tests/coretests/src/android/view/Visibility.java @@ -37,9 +37,9 @@ public class Visibility extends Activity { 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 7290a62f3133..f98a0a882764 100644 --- a/core/tests/coretests/src/android/view/VisibilityCallback.java +++ b/core/tests/coretests/src/android/view/VisibilityCallback.java @@ -45,9 +45,9 @@ public class VisibilityCallback extends Activity { 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 23dc80f97b61..13cef5290a4e 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 @@ public class InputMethodInfoTest { 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 @@ public class InputMethodInfoTest { 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 f6cec26f3e08..b4e05aa26de7 100644 --- a/core/tests/coretests/src/android/widget/AutoCompleteTextViewSimple.java +++ b/core/tests/coretests/src/android/widget/AutoCompleteTextViewSimple.java @@ -47,7 +47,7 @@ public class AutoCompleteTextViewSimple extends Activity // 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 7edab008c4ef..3029134251dd 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.dragHandle; 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 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV 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 1e887120e1d2..335d021efd14 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 final class TextViewActions { */ 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 @@ public final class TextViewActions { 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 @@ public final class TextViewActions { 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 @@ public final class TextViewActions { 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 @@ public final class TextViewActions { /** * @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 fef84f4d1517..6e44cd83b048 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.NoMatchingViewException; 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 @@ public final class TextViewAssertions { } /** - * 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 @@ public final class TextViewAssertions { 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 f7d91aa31357..f6b0520fbadb 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 @@ public class DescendantFocusability extends Activity { 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 93245e7b8116..b3d5ec5e5099 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 @@ public class FocusAfterRemoval extends Activity { 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 @@ public class FocusAfterRemoval extends Activity { // 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 @@ public class FocusAfterRemoval extends Activity { }); // 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 @@ public class FocusAfterRemoval extends Activity { }); // 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 db082ec6a5b7..acd632f3402b 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 class LinearLayoutGrid extends Activity { } 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 @@ public class LinearLayoutGrid extends Activity { 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 ceb0e953cf5c..b9082011f8b4 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 @@ public class ListWithFooterViewAndNewLabels extends ListActivity { 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 21d762a55061..4daf0b4206b0 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 @@ public class RequestFocus extends Activity { 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 0b9e4c5c146b..c3156dcbb819 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 @@ public class GridPadding extends Activity { 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 4290941426de..0ce5a31c8539 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 @@ public class GridScrollListener extends Activity implements AbsListView.OnScroll 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 0ef5db951a29..ad89bb6ab90c 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 @@ public class GridThrasher extends Activity implements AdapterView.OnItemSelected 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 fe2525f5f3ba..83331caa6069 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 @@ public class LLEditTextThenButton extends Activity { 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 3d0144f9f8cc..ab2f060eafc2 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 @@ public class LLOfButtons1 extends Activity { 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 class LLOfButtons1 extends Activity { } 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 3928c03e01a5..9b5a0879d6ba 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 @@ public class ListDividers extends Activity { 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 9e9d1b05cabe..c2ac90e7c47c 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 @@ public class ListFilter extends ListActivity implements OnClickListener { 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 5f09ff6209c6..a373a5b19be3 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 @@ public class ListInHorizontal extends Activity { 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 d5d726191ae3..76814fb480cd 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 @@ public class ListRecyclerProfiling extends Activity { 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 58a31dc4f2cb..f349dc6ac13a 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 @@ public class ListScrollListener extends ListActivity implements AbsListView.OnSc 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 ba3d5901fab5..0237a9551ce5 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 @@ public class ListThrasher extends ListActivity implements AdapterView.OnItemSele 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 9cc85441e631..afc275f25181 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 @@ public class RequestRectangleVisible extends Activity { 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 0e2586d2d856..731b25a08926 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 @@ public class RequestRectangleVisibleWithInternalScroll extends Activity { 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 4d0892c35aaf..027ea0f83350 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 @@ public class ScrollViewButtonsAndLabels extends Activity { 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 1080a9fcfe71..1859378e4c1f 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 @@ public class ChooserActivityTest { } @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 @@ public class ChooserActivityTest { 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 000000000000..284ab605c3b5 --- /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 686f75b6710b..515e5580a73c 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 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe } 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 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe .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 2b0ae2107b96..d8de70c75972 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 @@ public class BatteryStatsBackgroundStatsTest extends TestCase { 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/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index ec653d0849b1..7f07f03dde61 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -40,6 +40,7 @@ applications that come with the platform <privapp-permissions package="com.android.defcontainer"> <permission name="android.permission.ACCESS_CACHE_FILESYSTEM"/> + <permission name="android.permission.ALLOCATE_AGGRESSIVE"/> <permission name="android.permission.INTERACT_ACROSS_USERS"/> <permission name="android.permission.WRITE_MEDIA_STORAGE"/> </privapp-permissions> diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml index 3dab1f7e20e1..39b0bc7d6ca6 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/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 919068500e6f..7a8e4873a7c9 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -916,9 +916,8 @@ public final class Bitmap implements Parcelable { * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to * mark the bitmap as opaque. Doing so will clear the bitmap in black * instead of transparent. - * @param colorSpace The color space of the bitmap. If null, - * {@link ColorSpace.Named#SRGB sRGB} is assumed. This argument is - * ignored if the config is not {@link Config#ARGB_8888}. + * @param colorSpace The color space of the bitmap. If null or if the config is not + * {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB} is assumed. * * @throws IllegalArgumentException if the width or height are <= 0, if * Config is Config.HARDWARE (because hardware bitmaps are always @@ -968,9 +967,8 @@ public final class Bitmap implements Parcelable { * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to * mark the bitmap as opaque. Doing so will clear the bitmap in black * instead of transparent. - * @param colorSpace The color space of the bitmap. If null, - * {@link ColorSpace.Named#SRGB sRGB} is assumed. This argument is - * ignored if the config is not {@link Config#ARGB_8888}. + * @param colorSpace The color space of the bitmap. If null or if the config is not + * {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB} is assumed. * * @throws IllegalArgumentException if the width or height are <= 0, if * Config is Config.HARDWARE (because hardware bitmaps are always diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index ceedc1fdb360..3b272c8ddec7 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -43,7 +43,6 @@ public class BitmapFactory { * the same result from the decoder as if null were passed. */ public Options() { - inDither = false; inScaled = true; inPremultiplied = true; } @@ -114,8 +113,8 @@ public class BitmapFactory { /** * If set to true, the decoder will return null (no bitmap), but - * the out... fields will still be set, allowing the caller to query - * the bitmap without having to allocate the memory for its pixels. + * the <code>out...</code> fields will still be set, allowing the caller to + * query the bitmap without having to allocate the memory for its pixels. */ public boolean inJustDecodeBounds; @@ -144,6 +143,35 @@ public class BitmapFactory { public Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888; /** + * <p>If this is non-null, the decoder will try to decode into this + * color space. If it is null, or the request cannot be met, + * the decoder will pick either the color space embedded in the image + * or the color space best suited for the requested image configuration + * (for instance {@link ColorSpace.Named#SRGB sRGB} for + * the {@link Bitmap.Config#ARGB_8888} configuration).</p> + * + * <p>{@link Bitmap.Config#RGBA_F16} always uses the + * {@link ColorSpace.Named#LINEAR_EXTENDED_SRGB scRGB} color space). + * Bitmaps in other configurations without an embedded color space are + * assumed to be in the {@link ColorSpace.Named#SRGB sRGB} color space.</p> + * + * <p class="note">Only {@link ColorSpace.Model#RGB} color spaces are + * currently supported. An <code>IllegalArgumentException</code> will + * be thrown by the decode methods when setting a non-RGB color space + * such as {@link ColorSpace.Named#CIE_LAB Lab}.</p> + * + * <p class="note">The specified color space's transfer function must be + * an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}. An + * <code>IllegalArgumentException</code> will be thrown by the decode methods + * if calling {@link ColorSpace.Rgb#getTransferParameters()} on the + * specified color space returns null.</p> + * + * <p>After decode, the bitmap's color space is stored in + * {@link #outColorSpace}.</p> + */ + public ColorSpace inPreferredColorSpace = null; + + /** * If true (which is the default), the resulting bitmap will have its * color channels pre-multipled by the alpha channel. * @@ -403,9 +431,22 @@ public class BitmapFactory { } static void validate(Options opts) { - if (opts != null && opts.inMutable && opts.inPreferredConfig == Bitmap.Config.HARDWARE) { + if (opts == null) return; + + if (opts.inMutable && opts.inPreferredConfig == Bitmap.Config.HARDWARE) { throw new IllegalArgumentException("Bitmaps with Config.HARWARE are always immutable"); } + + if (opts.inPreferredColorSpace != null) { + if (!(opts.inPreferredColorSpace instanceof ColorSpace.Rgb)) { + throw new IllegalArgumentException("The destination color space must use the " + + "RGB color model"); + } + if (((ColorSpace.Rgb) opts.inPreferredColorSpace).getTransferParameters() == null) { + throw new IllegalArgumentException("The destination color space must use an " + + "ICC parametric transfer function"); + } + } } } @@ -421,7 +462,9 @@ public class BitmapFactory { * size be returned (in opts.outWidth and opts.outHeight) * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig} * is {@link android.graphics.Bitmap.Config#HARDWARE} - * and {@link BitmapFactory.Options#inMutable} is set. + * and {@link BitmapFactory.Options#inMutable} is set, if the specified color space + * is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer + * function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve} */ public static Bitmap decodeFile(String pathName, Options opts) { validate(opts); @@ -463,7 +506,9 @@ public class BitmapFactory { * resources, which we pass to be able to scale the bitmap accordingly. * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig} * is {@link android.graphics.Bitmap.Config#HARDWARE} - * and {@link BitmapFactory.Options#inMutable} is set. + * and {@link BitmapFactory.Options#inMutable} is set, if the specified color space + * is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer + * function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve} */ public static Bitmap decodeResourceStream(Resources res, TypedValue value, InputStream is, Rect pad, Options opts) { @@ -501,7 +546,9 @@ public class BitmapFactory { * size be returned (in opts.outWidth and opts.outHeight) * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig} * is {@link android.graphics.Bitmap.Config#HARDWARE} - * and {@link BitmapFactory.Options#inMutable} is set. + * and {@link BitmapFactory.Options#inMutable} is set, if the specified color space + * is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer + * function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve} */ public static Bitmap decodeResource(Resources res, int id, Options opts) { validate(opts); @@ -559,7 +606,9 @@ public class BitmapFactory { * size be returned (in opts.outWidth and opts.outHeight) * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig} * is {@link android.graphics.Bitmap.Config#HARDWARE} - * and {@link BitmapFactory.Options#inMutable} is set. + * and {@link BitmapFactory.Options#inMutable} is set, if the specified color space + * is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer + * function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve} */ public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts) { if ((offset | length) < 0 || data.length < offset + length) { @@ -641,7 +690,9 @@ public class BitmapFactory { * size be returned (in opts.outWidth and opts.outHeight) * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig} * is {@link android.graphics.Bitmap.Config#HARDWARE} - * and {@link BitmapFactory.Options#inMutable} is set. + * and {@link BitmapFactory.Options#inMutable} is set, if the specified color space + * is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer + * function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve} * * <p class="note">Prior to {@link android.os.Build.VERSION_CODES#KITKAT}, * if {@link InputStream#markSupported is.markSupported()} returns true, @@ -720,7 +771,9 @@ public class BitmapFactory { * @return the decoded bitmap, or null * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig} * is {@link android.graphics.Bitmap.Config#HARDWARE} - * and {@link BitmapFactory.Options#inMutable} is set. + * and {@link BitmapFactory.Options#inMutable} is set, if the specified color space + * is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer + * function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve} */ public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) { validate(opts); diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java index 04abca1f4bd4..2da27c7dfdbf 100644 --- a/graphics/java/android/graphics/BitmapRegionDecoder.java +++ b/graphics/java/android/graphics/BitmapRegionDecoder.java @@ -180,7 +180,9 @@ public final class BitmapRegionDecoder { * decoded. * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig} * is {@link android.graphics.Bitmap.Config#HARDWARE} - * and {@link BitmapFactory.Options#inMutable} is set. + * and {@link BitmapFactory.Options#inMutable} is set, if the specified color space + * is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer + * function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve} */ public Bitmap decodeRegion(Rect rect, BitmapFactory.Options options) { BitmapFactory.Options.validate(options); diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 7289429537fe..2a2e14b2df6d 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -157,10 +157,12 @@ public class Canvas extends BaseCanvas { /** * 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/Color.java b/graphics/java/android/graphics/Color.java index 218b857ce83c..8cbf921f6a34 100644 --- a/graphics/java/android/graphics/Color.java +++ b/graphics/java/android/graphics/Color.java @@ -538,7 +538,7 @@ public class Color { /** * Returns the value of the alpha component in the range \([0..1]\). * Calling this method is equivalent to - * <code>getComponent(getComponentCount())</code>. + * <code>getComponent(getComponentCount() - 1)</code>. * * @see #red() * @see #green() @@ -690,9 +690,8 @@ public class Color { * Returns the color space encoded in the specified color long. * * @param color The color long whose color space to extract - * @return A non-null color space instance. If the color long encodes - * an unknown or invalid color space, the {@link ColorSpace.Named#SRGB sRGB} - * color space is returned + * @return A non-null color space instance + * @throws IllegalArgumentException If the encoded color space is invalid or unknown * * @see #red(long) * @see #green(long) @@ -787,6 +786,7 @@ public class Color { * * @param color The color to test * @return True if the color is in the sRGB color space, false otherwise + * @throws IllegalArgumentException If the encoded color space is invalid or unknown * * @see #isInColorSpace(long, ColorSpace) * @see #isWideGamut(long) @@ -802,6 +802,7 @@ public class Color { * * @param color The color to test * @return True if the color is in a wide-gamut color space, false otherwise + * @throws IllegalArgumentException If the encoded color space is invalid or unknown * * @see #isInColorSpace(long, ColorSpace) * @see #isSrgb(long) @@ -831,6 +832,7 @@ public class Color { * a color space conversion is applied if needed. * * @return An ARGB color in the sRGB color space + * @throws IllegalArgumentException If the encoded color space is invalid or unknown */ @ColorInt public static int toArgb(@ColorLong long color) { @@ -873,6 +875,7 @@ public class Color { * * @param color The color long to create a <code>Color</code> from * @return A non-null instance of {@link Color} + * @throws IllegalArgumentException If the encoded color space is invalid or unknown */ @NonNull public static Color valueOf(@ColorLong long color) { @@ -1100,6 +1103,7 @@ public class Color { * @param color The color long to convert * @param colorSpace The destination color space * @return A color long in the destination color space + * @throws IllegalArgumentException If the encoded color space is invalid or unknown */ @ColorLong public static long convert(@ColorLong long color, @NonNull ColorSpace colorSpace) { @@ -1206,7 +1210,7 @@ public class Color { * @return A value between 0 (darkest black) and 1 (lightest white) * * @throws IllegalArgumentException If the specified color's color space - * does not use the {@link ColorSpace.Model#RGB RGB} color model + * is unknown or does not use the {@link ColorSpace.Model#RGB RGB} color model */ public static float luminance(@ColorLong long color) { ColorSpace colorSpace = colorSpace(color); diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java index 4fc63eacc4f1..f2957a30b05e 100644 --- a/graphics/java/android/graphics/ColorSpace.java +++ b/graphics/java/android/graphics/ColorSpace.java @@ -885,8 +885,32 @@ public abstract class ColorSpace { } /** - * 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 */ @@ -1314,9 +1338,8 @@ public abstract class ColorSpace { } /** - * <p>Returns an instance of {@link ColorSpace} whose ID matches the specified - * ID. If the ID is < 0 or > {@link #MAX_ID}, calling this method is equivalent - * to calling <code>get(Named.SRGB)</code>.</p> + * <p>Returns an instance of {@link ColorSpace} whose ID matches the + * specified ID.</p> * * <p>This method always returns the same instance for a given ID.</p> * @@ -1324,11 +1347,14 @@ public abstract class ColorSpace { * * @param index An integer ID between {@link #MIN_ID} and {@link #MAX_ID} * @return A non-null {@link ColorSpace} instance + * @throws IllegalArgumentException If the ID does not match the ID of one of the + * {@link Named named color spaces} */ @NonNull static ColorSpace get(@IntRange(from = MIN_ID, to = MAX_ID) int index) { if (index < 0 || index > Named.values().length) { - return get(Named.SRGB); + throw new IllegalArgumentException("Invalid ID, must be in the range [0.." + + Named.values().length + "]"); } return sNamedColorSpaces[index]; } @@ -1566,7 +1592,7 @@ public abstract class ColorSpace { Math.abs(a.a - b.a) < 1e-3 && Math.abs(a.b - b.b) < 1e-3 && Math.abs(a.c - b.c) < 1e-3 && - Math.abs(a.d - b.d) < 1e-3 && + Math.abs(a.d - b.d) < 2e-3 && // Special case for variations in sRGB OETF/EOTF Math.abs(a.e - b.e) < 1e-3 && Math.abs(a.f - b.f) < 1e-3 && Math.abs(a.g - b.g) < 1e-3; @@ -2079,8 +2105,11 @@ public abstract class ColorSpace { 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)) { @@ -2495,7 +2524,7 @@ public abstract class ColorSpace { 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); } diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java index 4b1b0c641807..d9a77e752823 100644 --- a/graphics/java/android/graphics/FontFamily.java +++ b/graphics/java/android/graphics/FontFamily.java @@ -52,12 +52,19 @@ public class FontFamily { 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 @@ public class FontFamily { 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 @@ public class FontFamily { 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 5afe5e9f14e9..97d3e5ee5609 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -33,6 +33,8 @@ import android.graphics.FontListParser; 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 @@ public class Typeface { /** * 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 class Typeface { 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 @@ public class Typeface { 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 @@ public class Typeface { 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 class Typeface { */ 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 @@ public class Typeface { * 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 @@ public class Typeface { 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 @@ public class Typeface { 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 @@ public class Typeface { /** * 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 @@ public class Typeface { /** * 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 @@ public class Typeface { 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 boolean mHasSourceSet = false; - private boolean mRecycled = false; - - /** Use Builder.obtain() instead */ - private void Builder() {} - - private static AtomicReference<Builder> mCache = new AtomicReference<>(); - - /** - * 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; + private FontsContract.FontInfo[] mFonts; + private Map<Uri, ByteBuffer> mFontBuffers; - mCache.compareAndSet(null, this); - } + private String mFallbackFamilyName; - 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."); - } - } + private int mWeight = RESOLVE_BY_FONT_TABLE; + private int mItalic = RESOLVE_BY_FONT_TABLE; /** - * 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 @@ public class Typeface { /** * 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 @@ public class Typeface { * 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 @@ public class Typeface { * @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 @@ public class Typeface { } /** + * 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 @@ public class Typeface { * @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 @@ public class Typeface { 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 @@ public class Typeface { 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 @@ public class Typeface { final FontFamily fontFamily = new FontFamily(); if (!fontFamily.addFontFromBuffer(buffer, mTtcIndex, mAxes, mWeight, mItalic)) { fontFamily.abortCreation(); - return null; + return resolveFallbackTypeface(); + } + if (!fontFamily.freeze()) { + return resolveFallbackTypeface(); } - fontFamily.freeze(); 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(); + } + if (!fontFamily.freeze()) { + return resolveFallbackTypeface(); } - fontFamily.freeze(); 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 @@ public class Typeface { 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 @@ public class Typeface { * @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 @@ public class Typeface { 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 @@ public class Typeface { 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 @@ public class Typeface { native_instance = ni; mStyle = nativeGetStyle(ni); + mBaseWeight = nativeGetBaseWeight(ni); } private static FontFamily makeFamilyFromParsed(FontConfig.Family family, @@ -1023,11 +1127,16 @@ public class Typeface { } } 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 null; + } return fontFamily; } @@ -1052,7 +1161,10 @@ public class Typeface { for (int i = 0; i < fontConfig.getFamilies().length; i++) { FontConfig.Family f = fontConfig.getFamilies()[i]; if (i == 0 || f.getName() == null) { - familyList.add(makeFamilyFromParsed(f, bufferForPath)); + FontFamily family = makeFamilyFromParsed(f, bufferForPath); + if (family != null) { + familyList.add(family); + } } } sFallbackFonts = familyList.toArray(new FontFamily[familyList.size()]); @@ -1069,8 +1181,12 @@ public class Typeface { typeface = sDefaultTypeface; } else { FontFamily fontFamily = makeFamilyFromParsed(f, bufferForPath); + if (fontFamily == null) { + continue; + } 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 +1284,16 @@ public class Typeface { } 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 643c0dab0635..283a3e2b0b1e 100644 --- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java +++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java @@ -29,6 +29,7 @@ import android.content.res.TypedArray; 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 org.xmlpull.v1.XmlPullParserException; 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 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback * @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 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback 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 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback 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 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback * 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 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback } /** + * 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 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback } /** + * 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 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback 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 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback } 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 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback return mLayerState.isStateful(); } + /** @hide */ + @Override + public boolean hasFocusStateSpecified() { + return mLayerState.hasFocusStateSpecified(); + } + @Override protected boolean onStateChange(int[] state) { boolean changed = false; @@ -1035,6 +1087,17 @@ public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback 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 6deeb0d9af9a..5004667c1089 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -737,6 +737,12 @@ public class BitmapDrawable extends Drawable { || 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 7524cac47491..559e3d3cc98e 100644 --- a/graphics/java/android/graphics/drawable/ColorDrawable.java +++ b/graphics/java/android/graphics/drawable/ColorDrawable.java @@ -207,6 +207,12 @@ public class ColorDrawable extends Drawable { 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 850f40ec3eb6..44fb1c75684e 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -26,6 +26,7 @@ import android.annotation.ColorInt; 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 @@ public abstract class Drawable { } /** + * 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 a491d7e771dc..aa4cd9cba4a7 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -242,6 +242,18 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { 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 5887939b05a4..431b63bd64e5 100644 --- a/graphics/java/android/graphics/drawable/DrawableWrapper.java +++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java @@ -323,6 +323,12 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb 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 7aad7df05fed..6c3aea2202a2 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -987,6 +987,15 @@ public class GradientDrawable extends Drawable { || (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 b159f0f4a2be..4725c2c4c0e5 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -1476,6 +1476,12 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { return mLayerState.isStateful(); } + /** @hide */ + @Override + public boolean hasFocusStateSpecified() { + return mLayerState.hasFocusStateSpecified(); + } + @Override protected boolean onStateChange(int[] state) { boolean changed = false; @@ -2117,6 +2123,18 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { 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 c7183d9e8f50..17900204fa22 100644 --- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java +++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java @@ -574,6 +574,12 @@ public class NinePatchDrawable extends Drawable { 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 f83c160b6c20..bfd0604a7c3f 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -377,6 +377,12 @@ public class RippleDrawable extends LayerDrawable { 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 67586077cd0a..34da928bb6f1 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.PorterDuff.Mode; 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 @@ public class ShapeDrawable extends Drawable { 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 @@ public class ShapeDrawable extends Drawable { 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 64a9eb5380cd..c98f1608c665 100644 --- a/graphics/java/android/graphics/drawable/StateListDrawable.java +++ b/graphics/java/android/graphics/drawable/StateListDrawable.java @@ -90,6 +90,12 @@ public class StateListDrawable extends DrawableContainer { 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 @@ public class StateListDrawable extends DrawableContainer { 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 a1539b8f805a..41e5af13358d 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -413,6 +413,12 @@ public class VectorDrawable extends Drawable { 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 @@ public class VectorDrawable extends Drawable { || (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 @@ public class VectorDrawable extends Drawable { } @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 @@ public class VectorDrawable extends Drawable { } @Override + public boolean hasFocusStateSpecified() { + return false; + } + + @Override int getNativeSize() { return NATIVE_ALLOCATION_SIZE; } @@ -1819,6 +1850,14 @@ public class VectorDrawable extends Drawable { } @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 @@ public class VectorDrawable extends Drawable { 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 91ec0e8df912..fb2a3a873394 100644 --- a/graphics/java/android/graphics/fonts/FontVariationAxis.java +++ b/graphics/java/android/graphics/fonts/FontVariationAxis.java @@ -18,8 +18,6 @@ package android.graphics.fonts; 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 @@ import java.util.regex.Pattern; /** * 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 @@ public final class FontVariationAxis implements Parcelable { } /** - * @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/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index 3e7a246bb281..931a55a70fd8 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -600,12 +600,12 @@ void verify(const ProgramDescription& description, const Glop& glop) { void GlopBuilder::build() { REQUIRE_STAGES(kAllStages); if (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) { - if (mOutGlop->fill.texture.texture->target() == GL_TEXTURE_2D) { + Texture* texture = mOutGlop->fill.texture.texture; + if (texture->target() == GL_TEXTURE_2D) { mDescription.hasTexture = true; } else { mDescription.hasExternalTexture = true; } - Texture* texture = mOutGlop->fill.texture.texture; mDescription.hasLinearTexture = texture->isLinear(); mDescription.hasColorSpaceConversion = texture->hasColorSpaceConversion(); mDescription.transferFunction = texture->getTransferFunctionType(); diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 9f649ead2b52..d95acff8a38e 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(SkCanvas* canvas, XformToSRGB xformToSRGB) 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 @@ void SkiaCanvas::reset(SkCanvas* skiaCanvas) { // 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 @@ void SkiaCanvas::setDrawFilter(SkDrawFilter* drawFilter) { } // ---------------------------------------------------------------------------- +// 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 13f979cf7d71..aeecafafbae2 100644 --- a/libs/hwui/SkiaCanvas.h +++ b/libs/hwui/SkiaCanvas.h @@ -102,6 +102,8 @@ public: 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 ed328328dbd6..86af67837dcd 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 @@ public: 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 4b8575adb32b..4fb4b53346e0 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 @@ Typeface* Typeface::createFromTypeface(Typeface* src, SkTypeface::Style style) { 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::createWeightAlias(Typeface* src, int weight) { } 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; + } + } + + // Sanitize the invalid value passed from public API. + if (weight < 0) { + weight = SkFontStyle::kNormal_Weight; } - result->fBaseWeight = 400; + + 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 @@ void Typeface::setRobotoTypefaceForTest() { 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 19a4f6c5acd5..e35a7b46c4b2 100644 --- a/libs/hwui/hwui/Typeface.h +++ b/libs/hwui/hwui/Typeface.h @@ -42,13 +42,16 @@ struct ANDROID_API Typeface { 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 d26eb59a039a..68a08693249c 100644 --- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp +++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp @@ -190,9 +190,32 @@ void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable* } 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 44476af742f1..0aecb8540e4e 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 @@ TEST(SkiaCanvas, colorSpaceXform) { 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 @@ TEST(SkiaCanvas, colorSpaceXform) { 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 aac9727614ea..de85c1660ba5 100644 --- a/location/java/android/location/GnssMeasurement.java +++ b/location/java/android/location/GnssMeasurement.java @@ -670,6 +670,8 @@ public final class GnssMeasurement implements Parcelable { * 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 @@ public final class GnssMeasurement implements Parcelable { } /** - * 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 @@ public final class GnssMeasurement implements Parcelable { * 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 @@ public final class GnssMeasurement implements Parcelable { 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 e90a174eb9be..a44bc5b9db26 100644 --- a/location/java/android/location/GnssStatus.java +++ b/location/java/android/location/GnssStatus.java @@ -224,7 +224,7 @@ public final class GnssStatus { * * @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 @@ public final class GnssStatus { * 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 4c39c308ef87..6bc5e917aa32 100644 --- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java +++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java @@ -242,8 +242,7 @@ public class GpsNetInitiatedHandler { } 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 7f5d3a084cb4..bf5939fa1737 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -2523,8 +2523,11 @@ public class AudioTrack extends PlayerBase 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 @@ public class AudioTrack extends PlayerBase } mAvSyncBytesRemaining -= ret; - if (mAvSyncBytesRemaining == 0) { - mAvSyncHeader = null; - } return ret; } diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java index 611fdd1d997b..ce50cc801daf 100644 --- a/media/java/android/media/MediaCas.java +++ b/media/java/android/media/MediaCas.java @@ -51,12 +51,13 @@ import android.util.Singleton; * 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 @@ import android.util.Singleton; * 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 @@ public final class MediaCas { } /** + * 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,47 +506,20 @@ public final class MediaCas { } /** - * Open a session for the specified program. - * - * @param programNumber program_number of the program (as in ISO/IEC13818-1). + * Open a session to descramble one or more streams scrambled by the + * conditional access system. * - * @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 { - validateInternalStates(); - - try { - return mICas.openSession(programNumber); - } catch (ServiceSpecificException e) { - MediaCasException.throwExceptions(e); - } catch (RemoteException e) { - cleanupAndRethrowIllegalState(); - } - return null; - } - - /** - * 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 { + public Session openSession() throws MediaCasException { validateInternalStates(); try { - return mICas.openSessionForStream(programNumber, elementaryPID); + return createFromSessionId(mICas.openSession()); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); } catch (RemoteException e) { @@ -454,92 +529,6 @@ public final class MediaCas { } /** - * 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 @@ public final class MediaCas { } } - /** - * Release the MediaCas instance. - */ - public void release() { + @Override + public void close() { if (mICas != null) { try { mICas.release(); @@ -666,6 +653,6 @@ public final class MediaCas { @Override protected void finalize() { - release(); + close(); } }
\ No newline at end of file diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index e628d18d8490..6cab56c1d466 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -23,12 +23,12 @@ import android.graphics.ImageFormat; import android.graphics.Rect; import android.graphics.SurfaceTexture; import android.media.MediaCodecInfo.CodecCapabilities; -import android.media.MediaMetricsSet; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.PersistableBundle; import android.view.Surface; import java.io.IOException; @@ -3188,20 +3188,19 @@ final public class MediaCodec { /** * Return Metrics data about the current codec instance. * - * @return a MediaMetricsSet containing the set of attributes and values + * @return a {@link PersistableBundle} containing the set of attributes and values * available for the media being handled by this instance of MediaCodec - * The attributes are descibed in {@link MediaMetricsSet.MediaCodec}. + * The attributes are descibed in {@link MetricsConstants}. * - * Additional vendor-specific fields may also be present in - * the return value. + * Additional vendor-specific fields may also be present in + * the return value. */ - public MediaMetricsSet getMetrics() { - Bundle bundle = native_getMetrics(); - MediaMetricsSet mSet = new MediaMetricsSet(bundle); - return mSet; + public PersistableBundle getMetrics() { + PersistableBundle bundle = native_getMetrics(); + return bundle; } - private native Bundle native_getMetrics(); + private native PersistableBundle native_getMetrics(); /** * Change a video encoder's target bitrate on the fly. The value is an @@ -3660,4 +3659,80 @@ final public class MediaCodec { private final ByteBuffer mData; } } + + public final static class MetricsConstants + { + private MetricsConstants() {} + + /** + * Key to extract the codec being used + * from the {@link MediaCodec#getMetrics} return value. + * The value is a String. + */ + public static final String CODEC = "android.media.mediacodec.codec"; + + /** + * Key to extract the MIME type + * from the {@link MediaCodec#getMetrics} return value. + * The value is a String. + */ + public static final String MIME_TYPE = "android.media.mediacodec.mime"; + + /** + * Key to extract what the codec mode + * from the {@link MediaCodec#getMetrics} return value. + * The value is a String. Values will be one of the constants + * {@link #MODE_AUDIO} or {@link #MODE_VIDEO}. + */ + public static final String MODE = "android.media.mediacodec.mode"; + + /** + * The value returned for the key {@link #MODE} when the + * codec is a audio codec. + */ + public static final String MODE_AUDIO = "audio"; + + /** + * The value returned for the key {@link #MODE} when the + * codec is a video codec. + */ + public static final String MODE_VIDEO = "video"; + + /** + * Key to extract the flag indicating whether the codec is running + * as an encoder or decoder from the {@link MediaCodec#getMetrics} return value. + * The value is an integer. + * A 0 indicates decoder; 1 indicates encoder. + */ + public static final String ENCODER = "android.media.mediacodec.encoder"; + + /** + * Key to extract the flag indicating whether the codec is running + * in secure (DRM) mode from the {@link MediaCodec#getMetrics} return value. + * The value is an integer. + */ + public static final String SECURE = "android.media.mediacodec.secure"; + + /** + * Key to extract the width (in pixels) of the video track + * from the {@link MediaCodec#getMetrics} return value. + * The value is an integer. + */ + public static final String WIDTH = "android.media.mediacodec.width"; + + /** + * Key to extract the height (in pixels) of the video track + * from the {@link MediaCodec#getMetrics} return value. + * The value is an integer. + */ + public static final String HEIGHT = "android.media.mediacodec.height"; + + /** + * Key to extract the rotation (in degrees) to properly orient the video + * from the {@link MediaCodec#getMetrics} return. + * The value is a integer. + */ + public static final String ROTATION = "android.media.mediacodec.rotation"; + + } } diff --git a/media/java/android/media/MediaDescrambler.java b/media/java/android/media/MediaDescrambler.java index 2dd109721ca8..b75b7dd8b742 100644 --- a/media/java/android/media/MediaDescrambler.java +++ b/media/java/android/media/MediaDescrambler.java @@ -38,7 +38,7 @@ import java.nio.ByteBuffer; * 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 @@ public final class MediaDescrambler { * 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 @@ public final class MediaDescrambler { * 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 @@ public final class MediaDescrambler { * @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 @@ public final class MediaDescrambler { 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 @@ public final class MediaDescrambler { @Override protected void finalize() { - release(); + close(); } private static native final void native_init(); @@ -237,7 +238,8 @@ public final class MediaDescrambler { 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 b8d1d12b350e..88b1c5ffcc7e 100644 --- a/media/java/android/media/MediaDrm.java +++ b/media/java/android/media/MediaDrm.java @@ -474,6 +474,9 @@ public final class MediaDrm { /** * 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 2ed6668112ce..fe461be6dea5 100644 --- a/media/java/android/media/MediaExtractor.java +++ b/media/java/android/media/MediaExtractor.java @@ -25,10 +25,10 @@ import android.content.res.AssetFileDescriptor; import android.media.MediaCodec; import android.media.MediaFormat; import android.media.MediaHTTPService; -import android.media.MediaMetricsSet; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; +import android.os.PersistableBundle; import com.android.internal.util.Preconditions; @@ -259,11 +259,71 @@ final public class MediaExtractor { * @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 @@ final public class MediaExtractor { 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 @@ final public class MediaExtractor { } }; } - return null; } + return null; } /** @@ -654,22 +689,21 @@ final public class MediaExtractor { /** * Return Metrics data about the current media container. * - * @return a MediaMetricsSet containing the set of attributes and values + * @return a {@link PersistableBundle} containing the set of attributes and values * available for the media container being handled by this instance * of MediaExtractor. - * The attributes are descibed in {@link MediaMetricsSet.MediaExtractor}. + * The attributes are descibed in {@link MetricsConstants}. * * Additional vendor-specific fields may also be present in * the return value. */ - public MediaMetricsSet getMetrics() { - Bundle bundle = native_getMetrics(); - MediaMetricsSet mSet = new MediaMetricsSet(bundle); - return mSet; + public PersistableBundle getMetrics() { + PersistableBundle bundle = native_getMetrics(); + return bundle; } - private native Bundle native_getMetrics(); + private native PersistableBundle native_getMetrics(); private static native final void native_init(); private native final void native_setup(); @@ -680,5 +714,35 @@ final public class MediaExtractor { native_init(); } + private MediaCas mMediaCas; + private long mNativeContext; + + public final static class MetricsConstants + { + private MetricsConstants() {} + + /** + * Key to extract the container format + * from the {@link MediaExtractor#getMetrics} return value. + * The value is a String. + */ + public static final String FORMAT = "android.media.mediaextractor.fmt"; + + /** + * Key to extract the container MIME type + * from the {@link MediaExtractor#getMetrics} return value. + * The value is a String. + */ + public static final String MIME_TYPE = "android.media.mediaextractor.mime"; + + /** + * Key to extract the number of tracks in the container + * from the {@link MediaExtractor#getMetrics} return value. + * The value is an integer. + */ + public static final String TRACKS = "android.media.mediaextractor.ntrk"; + + } + } diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java index e77c00b17365..ed5f7d848663 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -767,6 +767,29 @@ public final class MediaFormat { */ 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/MediaMetricsSet.java b/media/java/android/media/MediaMetricsSet.java deleted file mode 100644 index 5ecbee2127fc..000000000000 --- a/media/java/android/media/MediaMetricsSet.java +++ /dev/null @@ -1,491 +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.media; - -import android.os.Bundle; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.Runnable; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.ref.WeakReference; -import java.net.HttpCookie; -import java.net.HttpURLConnection; -import java.net.InetSocketAddress; -import java.net.URL; -import java.nio.ByteOrder; -import java.util.Arrays; -import java.util.BitSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Scanner; -import java.util.Set; -import java.util.UUID; -import java.util.Vector; - - -/** - * MediaMetricsSet contains the results returned by the getMetrics() - * methods defined in other Media classes such as - * {@link MediaCodec}, {@link MediaExtractor}, {@link MediaPlayer}, - * and {@link MediaRecorder}. - * - * MediaMetricsSet behaves similarly to a {@link Bundle}. It contains - * a set of keys and values. - * Methods such as {@link #getInt} and {@link #getString} are provided - * to extract values of the corresponding types. - * The {@link #keySet} method can be used to discover all of the keys - * that are present in the particular instance. - * - */ -public final class MediaMetricsSet -{ - - /** - * This MediaCodec class holds the constants defining keys related to - * the metrics for a MediaCodec. - */ - public final static class MediaCodec - { - private MediaCodec() {} - - /** - * Key to extract the codec being used - * from the {@link MediaCodec#getMetrics} return value. - * The value is a String. - */ - public static final String KEY_CODEC = "android.media.mediacodec.codec"; - - /** - * Key to extract the MIME type - * from the {@link MediaCodec#getMetrics} return value. - * The value is a String. - */ - public static final String KEY_MIME = "android.media.mediacodec.mime"; - - /** - * Key to extract what the codec mode - * from the {@link MediaCodec#getMetrics} return value. - * The value is a String. Values will be one of the constants - * MODE_AUDIO or MODE_VIDEO. - */ - public static final String KEY_MODE = "android.media.mediacodec.mode"; - - /** - * The value returned for the key {@link #KEY_MODE} when the - * codec is a audio codec. - */ - public static final String MODE_AUDIO = "audio"; - - /** - * The value returned for the key {@link #KEY_MODE} when the - * codec is a video codec. - */ - public static final String MODE_VIDEO = "video"; - - /** - * Key to extract the flag indicating whether the codec is running - * as an encoder or decoder from the {@link MediaCodec#getMetrics} return value. - * The value is an integer. - * A 0 indicates decoder; 1 indicates encoder. - */ - public static final String KEY_ENCODER = "android.media.mediacodec.encoder"; - - /** - * Key to extract the flag indicating whether the codec is running - * in secure (DRM) mode from the {@link MediaCodec#getMetrics} return value. - * The value is an integer. - */ - public static final String KEY_SECURE = "android.media.mediacodec.secure"; - - /** - * Key to extract the width (in pixels) of the video track - * from the {@link MediaCodec#getMetrics} return value. - * The value is an integer. - */ - public static final String KEY_WIDTH = "android.media.mediacodec.width"; - - /** - * Key to extract the height (in pixels) of the video track - * from the {@link MediaCodec#getMetrics} return value. - * The value is an integer. - */ - public static final String KEY_HEIGHT = "android.media.mediacodec.height"; - - /** - * Key to extract the rotation (in degrees) to properly orient the video - * from the {@link MediaCodec#getMetrics} return. - * The value is a integer. - */ - public static final String KEY_ROTATION = "android.media.mediacodec.rotation"; - - } - - /** - * This class holds the constants defining keys related to - * the metrics for a MediaExtractor. - */ - public final static class MediaExtractor - { - private MediaExtractor() {} - - /** - * Key to extract the container format - * from the {@link MediaExtractor#getMetrics} return value. - * The value is a String. - */ - public static final String KEY_FORMAT = "android.media.mediaextractor.fmt"; - - /** - * Key to extract the container MIME type - * from the {@link MediaExtractor#getMetrics} return value. - * The value is a String. - */ - public static final String KEY_MIME = "android.media.mediaextractor.mime"; - - /** - * Key to extract the number of tracks in the container - * from the {@link MediaExtractor#getMetrics} return value. - * The value is an integer. - */ - public static final String KEY_TRACKS = "android.media.mediaextractor.ntrk"; - - } - - /** - * This class holds the constants defining keys related to - * the metrics for a MediaPlayer. - */ - public final static class MediaPlayer - { - private MediaPlayer() {} - - /** - * Key to extract the MIME type of the video track - * from the {@link MediaPlayer#getMetrics} return value. - * The value is a String. - */ - public static final String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime"; - - /** - * Key to extract the codec being used to decode the video track - * from the {@link MediaPlayer#getMetrics} return value. - * The value is a String. - */ - public static final String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec"; - - /** - * Key to extract the width (in pixels) of the video track - * from the {@link MediaPlayer#getMetrics} return value. - * The value is an integer. - */ - public static final String KEY_WIDTH = "android.media.mediaplayer.width"; - - /** - * Key to extract the height (in pixels) of the video track - * from the {@link MediaPlayer#getMetrics} return value. - * The value is an integer. - */ - public static final String KEY_HEIGHT = "android.media.mediaplayer.height"; - - /** - * Key to extract the count of video frames played - * from the {@link MediaPlayer#getMetrics} return value. - * The value is an integer. - */ - public static final String KEY_FRAMES = "android.media.mediaplayer.frames"; - - /** - * Key to extract the count of video frames dropped - * from the {@link MediaPlayer#getMetrics} return value. - * The value is an integer. - */ - public static final String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped"; - - /** - * Key to extract the MIME type of the audio track - * from the {@link MediaPlayer#getMetrics} return value. - * The value is a String. - */ - public static final String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime"; - - /** - * Key to extract the codec being used to decode the audio track - * from the {@link MediaPlayer#getMetrics} return value. - * The value is a String. - */ - public static final String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec"; - - /** - * Key to extract the duration (in milliseconds) of the - * media being played - * from the {@link MediaPlayer#getMetrics} return value. - * The value is a long. - */ - public static final String KEY_DURATION = "android.media.mediaplayer.durationMs"; - - /** - * Key to extract the playing time (in milliseconds) of the - * media being played - * from the {@link MediaPlayer#getMetrics} return value. - * The value is a long. - */ - public static final String KEY_PLAYING = "android.media.mediaplayer.playingMs"; - - /** - * Key to extract the count of errors encountered while - * playing the media - * from the {@link MediaPlayer#getMetrics} return value. - * The value is an integer. - */ - public static final String KEY_ERRORS = "android.media.mediaplayer.err"; - - /** - * Key to extract an (optional) error code detected while - * playing the media - * from the {@link MediaPlayer#getMetrics} return value. - * The value is an integer. - */ - public static final String KEY_ERROR_CODE = "android.media.mediaplayer.errcode"; - - } - - /** - * This class holds the constants defining keys related to - * the metrics for a MediaRecorder. - */ - public final static class MediaRecorder - { - private MediaRecorder() {} - - /** - * Key to extract the audio bitrate - * from the {@link MediaRecorder#getMetrics} return. - * The value is an integer. - */ - public static final String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate"; - - /** - * Key to extract the number of audio channels - * from the {@link MediaRecorder#getMetrics} return. - * The value is an integer. - */ - public static final String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels"; - - /** - * Key to extract the audio samplerate - * from the {@link MediaRecorder#getMetrics} return. - * The value is an integer. - */ - public static final String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate"; - - /** - * Key to extract the audio timescale - * from the {@link MediaRecorder#getMetrics} return. - * The value is an integer. - */ - public static final String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale"; - - /** - * Key to extract the video capture frame rate - * from the {@link MediaRecorder#getMetrics} return. - * The value is a double. - */ - public static final String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps"; - - /** - * Key to extract the video capture framerate enable value - * from the {@link MediaRecorder#getMetrics} return. - * The value is an integer. - */ - public static final String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable"; - - /** - * Key to extract the intended playback frame rate - * from the {@link MediaRecorder#getMetrics} return. - * The value is an integer. - */ - public static final String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate"; - - /** - * Key to extract the height (in pixels) of the captured video - * from the {@link MediaRecorder#getMetrics} return. - * The value is an integer. - */ - public static final String KEY_HEIGHT = "android.media.mediarecorder.height"; - - /** - * Key to extract the recorded movies time units - * from the {@link MediaRecorder#getMetrics} return. - * The value is an integer. - * A value of 1000 indicates that the movie's timing is in milliseconds. - */ - public static final String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale"; - - /** - * Key to extract the rotation (in degrees) to properly orient the video - * from the {@link MediaRecorder#getMetrics} return. - * The value is an integer. - */ - public static final String KEY_ROTATION = "android.media.mediarecorder.rotation"; - - /** - * Key to extract the video bitrate from being used - * from the {@link MediaRecorder#getMetrics} return. - * The value is an integer. - */ - public static final String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate"; - - /** - * Key to extract the value for how often video iframes are generated - * from the {@link MediaRecorder#getMetrics} return. - * The value is an integer. - */ - public static final String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval"; - - /** - * Key to extract the video encoding level - * from the {@link MediaRecorder#getMetrics} return. - * The value is an integer. - */ - public static final String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level"; - - /** - * Key to extract the video encoding profile - * from the {@link MediaRecorder#getMetrics} return. - * The value is an integer. - */ - public static final String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile"; - - /** - * Key to extract the recorded video time units - * from the {@link MediaRecorder#getMetrics} return. - * The value is an integer. - * A value of 1000 indicates that the video's timing is in milliseconds. - */ - public static final String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale"; - - /** - * Key to extract the width (in pixels) of the captured video - * from the {@link MediaRecorder#getMetrics} return. - * The value is an integer. - */ - public static final String KEY_WIDTH = "android.media.mediarecorder.width"; - - } - - /* - * Methods that we want - */ - - private Bundle mBundle; - - MediaMetricsSet(Bundle bundle) { - mBundle = bundle; - } - - /** - * Returns the number of mappings contained in this Bundle. - * - * @return the number of mappings as an int. - */ - public int size() { - return mBundle.size(); - } - - /** - * Returns true if the mapping of this MediaMetricsSet is empty, - * false otherwise. - */ - public boolean isEmpty() { - return mBundle.isEmpty(); - } - - /** - * Returns the value associated with the given key, or defaultValue if - * no mapping of the desired type exists for the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist - * @return a double value - */ - public double getDouble(String key, double defaultValue) { - return mBundle.getDouble(key, defaultValue); - } - - /** - * Returns the value associated with the given key, or defaultValue if - * no mapping of the desired type exists for the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist - * @return an int value - */ - public int getInt(String key, int defaultValue) { - return mBundle.getInt(key, defaultValue); - } - - /** - * Returns the value associated with the given key, or defaultValue if - * no mapping of the desired type exists for the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist - * @return a long value - */ - public long getLong(String key, long defaultValue) { - return mBundle.getLong(key, defaultValue); - } - - /** - * Returns the value associated with the given key, or defaultValue if - * no mapping of the desired type exists for the given key or if a null - * value is explicitly associated with the given key. - * - * @param key a String - * @param defaultValue Value to return if key does not exist or if a null - * value is associated with the given key. - * @return the String value associated with the given key, or defaultValue - * if no valid String object is currently mapped to that key. - */ - public String getString(String key, String defaultValue) { - return mBundle.getString(key, defaultValue); - } - - /** - * Returns a Set containing the Strings used as keys in this Bundle. - * - * @return a Set of String keys - */ - public Set<String> keySet() { - return mBundle.keySet(); - } - - - - public String toString() { - return mBundle.toString(); - } - -} - diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 71a968b4d4b5..9386246bd128 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -33,6 +33,7 @@ import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.Parcelable; +import android.os.PersistableBundle; import android.os.Process; import android.os.PowerManager; import android.os.SystemProperties; @@ -48,7 +49,6 @@ import android.graphics.SurfaceTexture; import android.media.AudioManager; import android.media.MediaDrm; import android.media.MediaFormat; -import android.media.MediaMetricsSet; import android.media.MediaTimeProvider; import android.media.PlaybackParams; import android.media.SubtitleController; @@ -1491,20 +1491,19 @@ public class MediaPlayer extends PlayerBase /** * Return Metrics data about the current player. * - * @return a MediaMetricsSet containing the set of attributes and values + * @return a {@link PersistableBundle} containing the set of attributes and values * available for the media being handled by this instance of MediaPlayer - * The attributes are descibed in {@link MediaMetricsSet.MediaPlayer}. + * The attributes are descibed in {@link MetricsConstants}. * * Additional vendor-specific fields may also be present in * the return value. */ - public MediaMetricsSet getMetrics() { - Bundle bundle = native_getMetrics(); - MediaMetricsSet mSet = new MediaMetricsSet(bundle); - return mSet; + public PersistableBundle getMetrics() { + PersistableBundle bundle = native_getMetrics(); + return bundle; } - private native Bundle native_getMetrics(); + private native PersistableBundle native_getMetrics(); /** * Checks whether the MediaPlayer is playing. @@ -5418,4 +5417,98 @@ public class MediaPlayer extends PlayerBase } } } + + public final static class MetricsConstants + { + private MetricsConstants() {} + + /** + * Key to extract the MIME type of the video track + * from the {@link MediaPlayer#getMetrics} return value. + * The value is a String. + */ + public static final String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime"; + + /** + * Key to extract the codec being used to decode the video track + * from the {@link MediaPlayer#getMetrics} return value. + * The value is a String. + */ + public static final String CODEC_VIDEO = "android.media.mediaplayer.video.codec"; + + /** + * Key to extract the width (in pixels) of the video track + * from the {@link MediaPlayer#getMetrics} return value. + * The value is an integer. + */ + public static final String WIDTH = "android.media.mediaplayer.width"; + + /** + * Key to extract the height (in pixels) of the video track + * from the {@link MediaPlayer#getMetrics} return value. + * The value is an integer. + */ + public static final String HEIGHT = "android.media.mediaplayer.height"; + + /** + * Key to extract the count of video frames played + * from the {@link MediaPlayer#getMetrics} return value. + * The value is an integer. + */ + public static final String FRAMES = "android.media.mediaplayer.frames"; + + /** + * Key to extract the count of video frames dropped + * from the {@link MediaPlayer#getMetrics} return value. + * The value is an integer. + */ + public static final String FRAMES_DROPPED = "android.media.mediaplayer.dropped"; + + /** + * Key to extract the MIME type of the audio track + * from the {@link MediaPlayer#getMetrics} return value. + * The value is a String. + */ + public static final String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime"; + + /** + * Key to extract the codec being used to decode the audio track + * from the {@link MediaPlayer#getMetrics} return value. + * The value is a String. + */ + public static final String CODEC_AUDIO = "android.media.mediaplayer.audio.codec"; + + /** + * Key to extract the duration (in milliseconds) of the + * media being played + * from the {@link MediaPlayer#getMetrics} return value. + * The value is a long. + */ + public static final String DURATION = "android.media.mediaplayer.durationMs"; + + /** + * Key to extract the playing time (in milliseconds) of the + * media being played + * from the {@link MediaPlayer#getMetrics} return value. + * The value is a long. + */ + public static final String PLAYING = "android.media.mediaplayer.playingMs"; + + /** + * Key to extract the count of errors encountered while + * playing the media + * from the {@link MediaPlayer#getMetrics} return value. + * The value is an integer. + */ + public static final String ERRORS = "android.media.mediaplayer.err"; + + /** + * Key to extract an (optional) error code detected while + * playing the media + * from the {@link MediaPlayer#getMetrics} return value. + * The value is an integer. + */ + public static final String ERROR_CODE = "android.media.mediaplayer.errcode"; + + } } diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 4675e327ce25..997d56222ff7 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -20,14 +20,15 @@ import android.annotation.NonNull; import android.annotation.SystemApi; import android.app.ActivityThread; import android.hardware.Camera; -import android.media.MediaMetricsSet; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.PersistableBundle; import android.util.Log; import android.view.Surface; +import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.io.RandomAccessFile; @@ -92,6 +93,7 @@ public class MediaRecorder private String mPath; private FileDescriptor mFd; + private File mFile; private EventHandler mEventHandler; private OnErrorListener mOnErrorListener; private OnInfoListener mOnInfoListener; @@ -804,10 +806,26 @@ public class MediaRecorder public void setOutputFile(FileDescriptor fd) throws IllegalStateException { mPath = null; + mFile = null; mFd = fd; } /** + * Pass in the file object to be written. Call this after setOutputFormat() but before prepare(). + * File should be seekable. After setting the next output file, application should not use the + * file until {@link #stop}. Application is responsible for cleaning up unused files after + * {@link #stop} is called. + * + * @param file the file object to be written into. + */ + public void setOutputFile(File file) + { + mPath = null; + mFd = null; + mFile = file; + } + + /** * Sets the next output file descriptor to be used when the maximum filesize is reached * on the prior output {@link #setOutputFile} or {@link #setNextOutputFile}). File descriptor * must be seekable and writable. After setting the next output file, application should not @@ -842,15 +860,16 @@ public class MediaRecorder public void setOutputFile(String path) throws IllegalStateException { mFd = null; + mFile = null; mPath = path; } /** - * Sets the next output file path to be used when the maximum filesize is reached - * on the prior output {@link #setOutputFile} or {@link #setNextOutputFile}). File should - * be seekable. After setting the next output file, application should not use the file - * referenced by this file descriptor until {@link #stop}. Application must call this - * after receiving on the {@link android.media.MediaRecorder.OnInfoListener} a "what" code of + * Sets the next output file to be used when the maximum filesize is reached on the prior + * output {@link #setOutputFile} or {@link #setNextOutputFile}). File should be seekable. + * After setting the next output file, application should not use the file until {@link #stop}. + * Application must call this after receiving on the + * {@link android.media.MediaRecorder.OnInfoListener} a "what" code of * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING} and before receiving a "what" code of * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}. The file is not used until switching to * that output. Application will receive {@link #MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED} @@ -858,19 +877,17 @@ public class MediaRecorder * the previous one has not been used. Application is responsible for cleaning up unused files * after {@link #stop} is called. * - * @param path The pathname to use. + * @param file The file to use. * @throws IllegalStateException if it is called before prepare(). * @throws IOException if setNextOutputFile fails otherwise. */ - public void setNextOutputFile(String path) throws IllegalStateException, IOException + public void setNextOutputFile(File file) throws IllegalStateException, IOException { - if (path != null) { - RandomAccessFile file = new RandomAccessFile(path, "rws"); - try { - _setNextOutputFile(file.getFD()); - } finally { - file.close(); - } + RandomAccessFile f = new RandomAccessFile(file, "rws"); + try { + _setNextOutputFile(f.getFD()); + } finally { + f.close(); } } @@ -899,6 +916,13 @@ public class MediaRecorder } } else if (mFd != null) { _setOutputFile(mFd); + } else if (mFile != null) { + RandomAccessFile file = new RandomAccessFile(mFile, "rws"); + try { + _setOutputFile(file.getFD()); + } finally { + file.close(); + } } else { throw new IOException("No valid output file"); } @@ -1267,23 +1291,142 @@ public class MediaRecorder /** * Return Metrics data about the current Mediarecorder instance. * - * @return a MediaMetricsSet containing the set of attributes and values + * @return a {@link PersistableBundle} containing the set of attributes and values * available for the media being generated by this instance of * MediaRecorder. - * The attributes are descibed in {@link MediaMetricsSet.MediaRecorder}. + * The attributes are descibed in {@link MetricsConstants}. * * Additional vendor-specific fields may also be present in * the return value. */ - public MediaMetricsSet getMetrics() { - Bundle bundle = native_getMetrics(); - MediaMetricsSet mSet = new MediaMetricsSet(bundle); - return mSet; + public PersistableBundle getMetrics() { + PersistableBundle bundle = native_getMetrics(); + return bundle; } - private native Bundle native_getMetrics(); + private native PersistableBundle native_getMetrics(); @Override protected void finalize() { native_finalize(); } + + public final static class MetricsConstants + { + private MetricsConstants() {} + + /** + * Key to extract the audio bitrate + * from the {@link MediaRecorder#getMetrics} return. + * The value is an integer. + */ + public static final String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate"; + + /** + * Key to extract the number of audio channels + * from the {@link MediaRecorder#getMetrics} return. + * The value is an integer. + */ + public static final String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels"; + + /** + * Key to extract the audio samplerate + * from the {@link MediaRecorder#getMetrics} return. + * The value is an integer. + */ + public static final String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate"; + + /** + * Key to extract the audio timescale + * from the {@link MediaRecorder#getMetrics} return. + * The value is an integer. + */ + public static final String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale"; + + /** + * Key to extract the video capture frame rate + * from the {@link MediaRecorder#getMetrics} return. + * The value is a double. + */ + public static final String CAPTURE_FPS = "android.media.mediarecorder.capture-fps"; + + /** + * Key to extract the video capture framerate enable value + * from the {@link MediaRecorder#getMetrics} return. + * The value is an integer. + */ + public static final String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable"; + + /** + * Key to extract the intended playback frame rate + * from the {@link MediaRecorder#getMetrics} return. + * The value is an integer. + */ + public static final String FRAMERATE = "android.media.mediarecorder.frame-rate"; + + /** + * Key to extract the height (in pixels) of the captured video + * from the {@link MediaRecorder#getMetrics} return. + * The value is an integer. + */ + public static final String HEIGHT = "android.media.mediarecorder.height"; + + /** + * Key to extract the recorded movies time units + * from the {@link MediaRecorder#getMetrics} return. + * The value is an integer. + * A value of 1000 indicates that the movie's timing is in milliseconds. + */ + public static final String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale"; + + /** + * Key to extract the rotation (in degrees) to properly orient the video + * from the {@link MediaRecorder#getMetrics} return. + * The value is an integer. + */ + public static final String ROTATION = "android.media.mediarecorder.rotation"; + + /** + * Key to extract the video bitrate from being used + * from the {@link MediaRecorder#getMetrics} return. + * The value is an integer. + */ + public static final String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate"; + + /** + * Key to extract the value for how often video iframes are generated + * from the {@link MediaRecorder#getMetrics} return. + * The value is an integer. + */ + public static final String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval"; + + /** + * Key to extract the video encoding level + * from the {@link MediaRecorder#getMetrics} return. + * The value is an integer. + */ + public static final String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level"; + + /** + * Key to extract the video encoding profile + * from the {@link MediaRecorder#getMetrics} return. + * The value is an integer. + */ + public static final String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile"; + + /** + * Key to extract the recorded video time units + * from the {@link MediaRecorder#getMetrics} return. + * The value is an integer. + * A value of 1000 indicates that the video's timing is in milliseconds. + */ + public static final String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale"; + + /** + * Key to extract the width (in pixels) of the captured video + * from the {@link MediaRecorder#getMetrics} return. + * The value is an integer. + */ + public static final String WIDTH = "android.media.mediarecorder.width"; + + } } diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java index af11e07d2f98..1dda6a4c77f7 100644 --- a/media/java/android/media/VolumeShaper.java +++ b/media/java/android/media/VolumeShaper.java @@ -301,7 +301,7 @@ public final class VolumeShaper implements AutoCloseable { .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 @@ public final class VolumeShaper implements AutoCloseable { .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 @@ public final class VolumeShaper implements AutoCloseable { 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 @@ public final class VolumeShaper implements AutoCloseable { /** * Returns the duration of the volume shape in milliseconds. */ - public double getDurationMs() { + public double getDurationMillis() { return mDurationMs; } @@ -700,7 +700,7 @@ public final class VolumeShaper implements AutoCloseable { * .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 @@ public final class VolumeShaper implements AutoCloseable { 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 @@ public final class VolumeShaper implements AutoCloseable { * * 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 @@ public final class VolumeShaper implements AutoCloseable { * 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 0d51b5b508b8..b076bb67738f 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 @@ interface ITvInputManager { // 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 e82dd8255d21..1b55380ed5a9 100644 --- a/media/java/android/media/tv/TvContract.java +++ b/media/java/android/media/tv/TvContract.java @@ -21,9 +21,11 @@ import android.annotation.NonNull; 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 @@ public final class TvContract { 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 @@ public final class TvContract { * 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 final class TvContract { 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 @@ public final class TvContract { "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 final class TvContract { 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 final class TvContract { 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 @@ public final class TvContract { 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 @@ public final class TvContract { * @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 @@ public final class TvContract { * <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 @@ public final class TvContract { 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 @@ public final class TvContract { 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 @@ public final class TvContract { * @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 @@ public final class TvContract { */ 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 @@ public final class TvContract { * <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 @@ public final class TvContract { * <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 @@ public final class TvContract { 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 final class TvContract { */ 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 09b2050b1b1a..68ee02cab7a4 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; 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 @@ public final class TvInputManager { } /** + * 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 @@ public final class TvInputManager { } /** + * 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_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index a8dd3133b275..2178607152c6 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -2002,7 +2002,7 @@ static const JNINativeMethod gMethods[] = { { "getName", "()Ljava/lang/String;", (void *)android_media_MediaCodec_getName }, - { "native_getMetrics", "()Landroid/os/Bundle;", + { "native_getMetrics", "()Landroid/os/PersistableBundle;", (void *)android_media_MediaCodec_native_getMetrics}, { "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V", diff --git a/media/jni/android_media_MediaDescrambler.cpp b/media/jni/android_media_MediaDescrambler.cpp index f031dbb273c6..85d33b773007 100644 --- a/media/jni/android_media_MediaDescrambler.cpp +++ b/media/jni/android_media_MediaDescrambler.cpp @@ -54,11 +54,10 @@ static void setDescrambler( } 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 @@ static status_t getBufferAndSize( 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 void throwServiceSpecificException( 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 @@ static jint android_media_MediaDescrambler_native_descramble( numBytesOfEncryptedDataObj, &subSamples); if (totalLength < 0) { jniThrowException(env, "java/lang/IllegalArgumentException", - "Invalid sub sample info!"); + "Invalid subsample info!"); return -1; } @@ -315,16 +311,23 @@ static jint android_media_MediaDescrambler_native_descramble( 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 @@ static const JNINativeMethod gMethods[] = { (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/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp index c2cfed9bfa2f..9e5d3d12f0bd 100644 --- a/media/jni/android_media_MediaExtractor.cpp +++ b/media/jni/android_media_MediaExtractor.cpp @@ -905,7 +905,7 @@ static const JNINativeMethod gMethods[] = { { "hasCacheReachedEndOfStream", "()Z", (void *)android_media_MediaExtractor_hasCacheReachedEOS }, - {"native_getMetrics", "()Landroid/os/Bundle;", + {"native_getMetrics", "()Landroid/os/PersistableBundle;", (void *)android_media_MediaExtractor_native_getMetrics}, }; diff --git a/media/jni/android_media_MediaMetricsJNI.cpp b/media/jni/android_media_MediaMetricsJNI.cpp index fb606bac7828..8979cec2e864 100644 --- a/media/jni/android_media_MediaMetricsJNI.cpp +++ b/media/jni/android_media_MediaMetricsJNI.cpp @@ -24,15 +24,12 @@ namespace android { -// place the attributes into a java Bundle object -// decide whether this is appropriately scoped here. -// if we do it somewhere else, we have to figure a "give me all the attrs" -// access to the inside of MediaAnalyticsItem +// place the attributes into a java PersistableBundle object jobject MediaMetricsJNI::writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle) { - jclass clazzBundle = env->FindClass("android/os/Bundle"); + jclass clazzBundle = env->FindClass("android/os/PersistableBundle"); if (clazzBundle==NULL) { - ALOGD("can't find android/os/Bundle"); + ALOGD("can't find android/os/PersistableBundle"); return NULL; } // sometimes the caller provides one for us to fill @@ -58,7 +55,7 @@ jobject MediaMetricsJNI::writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *i // -- get name, get type, get value // -- insert appropriately into the bundle for (size_t i = 0 ; i < item->mPropCount; i++ ) { - MediaAnalyticsItem::Prop *prop = &item->mProps[i]; + MediaAnalyticsItem::Prop *prop = &item->mProps[i]; // build the key parameter from prop->mName jstring keyName = env->NewStringUTF(prop->mName); // invoke the appropriate method to insert diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp index 1b52cf58cbff..2fc4afd28335 100644 --- a/media/jni/android_media_MediaPlayer.cpp +++ b/media/jni/android_media_MediaPlayer.cpp @@ -1393,7 +1393,7 @@ static const JNINativeMethod gMethods[] = { {"_stop", "()V", (void *)android_media_MediaPlayer_stop}, {"getVideoWidth", "()I", (void *)android_media_MediaPlayer_getVideoWidth}, {"getVideoHeight", "()I", (void *)android_media_MediaPlayer_getVideoHeight}, - {"native_getMetrics", "()Landroid/os/Bundle;", (void *)android_media_MediaPlayer_native_getMetrics}, + {"native_getMetrics", "()Landroid/os/PersistableBundle;", (void *)android_media_MediaPlayer_native_getMetrics}, {"setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer_setPlaybackParams}, {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer_getPlaybackParams}, {"setSyncParams", "(Landroid/media/SyncParams;)V", (void *)android_media_MediaPlayer_setSyncParams}, diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp index 7a63e003875a..2c1e834187e8 100644 --- a/media/jni/android_media_MediaRecorder.cpp +++ b/media/jni/android_media_MediaRecorder.cpp @@ -688,7 +688,7 @@ static const JNINativeMethod gMethods[] = { {"native_finalize", "()V", (void *)android_media_MediaRecorder_native_finalize}, {"native_setInputSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaRecorder_setInputSurface }, - {"native_getMetrics", "()Landroid/os/Bundle;", (void *)android_media_MediaRecorder_native_getMetrics}, + {"native_getMetrics", "()Landroid/os/PersistableBundle;", (void *)android_media_MediaRecorder_native_getMetrics}, }; // This function only registers the native methods, and is called from 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 c0c303426573..0b62bca9a7ec 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 class CameraEffectsRecordingSample extends Activity { 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/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java index 444705cfc79f..ece700dc8b6d 100644 --- a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java +++ b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java @@ -100,8 +100,8 @@ public final class BluetoothMidiDevice { int newState) { String intentAction; if (newState == BluetoothProfile.STATE_CONNECTED) { - Log.i(TAG, "Connected to GATT server."); - Log.i(TAG, "Attempting to start service discovery:" + + Log.d(TAG, "Connected to GATT server."); + Log.d(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices()); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { Log.i(TAG, "Disconnected from GATT server."); @@ -112,24 +112,24 @@ public final class BluetoothMidiDevice { @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { - List<BluetoothGattService> services = mBluetoothGatt.getServices(); - for (BluetoothGattService service : services) { - if (MIDI_SERVICE.equals(service.getUuid())) { - Log.d(TAG, "found MIDI_SERVICE"); - List<BluetoothGattCharacteristic> characteristics - = service.getCharacteristics(); - for (BluetoothGattCharacteristic characteristic : characteristics) { - if (MIDI_CHARACTERISTIC.equals(characteristic.getUuid())) { - Log.d(TAG, "found MIDI_CHARACTERISTIC"); - mCharacteristic = characteristic; - - // Specification says to read the characteristic first and then - // switch to receiving notifications - mBluetoothGatt.readCharacteristic(characteristic); - break; - } - } - break; + BluetoothGattService service = gatt.getService(MIDI_SERVICE); + if (service != null) { + Log.d(TAG, "found MIDI_SERVICE"); + BluetoothGattCharacteristic characteristic + = service.getCharacteristic(MIDI_CHARACTERISTIC); + if (characteristic != null) { + Log.d(TAG, "found MIDI_CHARACTERISTIC"); + mCharacteristic = characteristic; + + // Request a lower Connection Interval for better latency. + boolean result = gatt.requestConnectionPriority( + BluetoothGatt.CONNECTION_PRIORITY_HIGH); + Log.d(TAG, "requestConnectionPriority(CONNECTION_PRIORITY_HIGH):" + + result); + + // Specification says to read the characteristic first and then + // switch to receiving notifications + mBluetoothGatt.readCharacteristic(characteristic); } } } else { diff --git a/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java b/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java index 1a10d6422184..cce2acc5869a 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 @@ public class BassBoostTest extends Activity implements OnCheckedChangeListener { 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 594e8446faa7..1731dba88757 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 @@ public class EnvReverbTest extends Activity implements OnCheckedChangeListener, 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 f30a26f39c64..fd5695603ee2 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 @@ public class EqualizerTest extends Activity implements OnCheckedChangeListener { 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 bb32e6fa7603..4f2180fac5e5 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 @@ public class VirtualizerTest extends Activity implements OnCheckedChangeListener 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 60583e0adf72..7db1d8d8625e 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 @@ public class VisualizerTest extends Activity implements OnCheckedChangeListener 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 c3dd842903ec..963b20d11243 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 @@ public class Camera2SurfaceViewActivity extends Activity implements SurfaceHolde 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 0969b10b1f90..b0ca0bb74548 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 @@ public class NativeMidi extends Activity 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 7e21876accb2..8427d16d9760 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 @@ public class ScoAudioTest extends Activity { 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 @@ public class ScoAudioTest extends Activity { 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 @@ public class ScoAudioTest extends Activity { 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 @@ public class ScoAudioTest extends Activity { 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 @@ public class ScoAudioTest extends Activity { 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 @@ public class ScoAudioTest extends Activity { 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 @@ public class ScoAudioTest extends Activity { 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/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java index 7fa57367301e..9fa7a6646c9c 100644 --- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java +++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java @@ -173,13 +173,13 @@ public class BackupRestoreConfirmation extends Activity { 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 @@ public class BackupRestoreConfirmation extends Activity { 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 6394c64b74cc..5d20cf38e21b 100644 --- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java +++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java @@ -117,7 +117,7 @@ public class CaptivePortalLoginActivity extends Activity { } 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 @@ public class CaptivePortalLoginActivity extends Activity { @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 @@ public class CaptivePortalLoginActivity extends Activity { // 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 @@ public class CaptivePortalLoginActivity extends Activity { 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/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java index a5820f2da56c..6276ce3f0b98 100644 --- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java +++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java @@ -91,7 +91,7 @@ public class CaptivePortalLoginActivity extends Activity { 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 @@ public class CaptivePortalLoginActivity extends Activity { @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 @@ public class CaptivePortalLoginActivity extends Activity { // 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 @@ public class CaptivePortalLoginActivity extends Activity { 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 14b9de59bf5a..b145290d0ce6 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java @@ -34,6 +34,7 @@ import android.widget.ProgressBar; import android.widget.TextView; import com.android.companiondevicemanager.DeviceDiscoveryService.DeviceFilterPair; +import com.android.internal.util.Preconditions; public class DeviceChooserActivity extends Activity { @@ -65,7 +66,7 @@ public class DeviceChooserActivity extends Activity { } 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() { @@ -78,22 +79,35 @@ public class DeviceChooserActivity extends Activity { } mPairButton = findViewById(R.id.button_pair); - mPairButton.setOnClickListener((view) -> - onPairTapped(getService().mSelectedDevice)); + mPairButton.setOnClickListener(v -> onPairTapped(getService().mSelectedDevice)); updatePairButtonEnabled(); mCancelButton = findViewById(R.id.button_cancel); - mCancelButton.setOnClickListener((view) -> { - setResult(RESULT_CANCELED); - finish(); - }); + mCancelButton.setOnClickListener(v -> cancel()); + } + + private void cancel() { + getService().onCancel(); + setResult(RESULT_CANCELED); + finish(); + } + + @Override + protected void onPause() { + super.onPause(); + if (!isFinishing()) { + cancel(); + } } private CharSequence getCallingAppName() { try { final PackageManager packageManager = getPackageManager(); + String callingPackage = Preconditions.checkStringNotEmpty( + getCallingPackage(), + "This activity must be called for result"); return packageManager.getApplicationLabel( - packageManager.getApplicationInfo(getCallingPackage(), 0)); + packageManager.getApplicationInfo(callingPackage, 0)); } catch (PackageManager.NameNotFoundException e) { throw new RuntimeException(e); } @@ -101,7 +115,7 @@ public class DeviceChooserActivity extends Activity { @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/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java index 1b6aca1ba65e..246bd2bc7ce0 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java @@ -110,6 +110,11 @@ public class DeviceDiscoveryService extends Service { private final ScanCallback mBLEScanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { + if (DEBUG) { + Log.i(LOG_TAG, + "BLE.onScanResult(callbackType = " + callbackType + ", result = " + result + + ")"); + } final DeviceFilterPair<ScanResult> deviceFilterPair = DeviceFilterPair.findMatch(result, mBLEFilters); if (deviceFilterPair == null) return; @@ -126,6 +131,10 @@ public class DeviceDiscoveryService extends Service { private BroadcastReceiver mBluetoothDeviceFoundBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + if (DEBUG) { + Log.i(LOG_TAG, + "BL.onReceive(context = " + context + ", intent = " + intent + ")"); + } final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); final DeviceFilterPair<BluetoothDevice> deviceFilterPair = DeviceFilterPair.findMatch(device, mBluetoothFilters); @@ -191,7 +200,8 @@ public class DeviceDiscoveryService extends Service { mBLEScanFilters = CollectionUtils.map(mBLEFilters, BluetoothLEDeviceFilter::getScanFilter); reset(); - } + } else if (DEBUG) Log.i(LOG_TAG, "startDiscovery: duplicate request: " + request); + if (!ArrayUtils.isEmpty(mDevicesFound)) { onReadyToShowUI(); } @@ -221,6 +231,7 @@ public class DeviceDiscoveryService extends Service { } private void reset() { + if (DEBUG) Log.i(LOG_TAG, "reset()"); mDevicesFound.clear(); mSelectedDevice = null; mDevicesAdapter.notifyDataSetChanged(); @@ -294,6 +305,14 @@ public class DeviceDiscoveryService extends Service { } } + void onCancel() { + try { + mServiceCallback.onDeviceSelectionCancel(); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + class DevicesAdapter extends ArrayAdapter<DeviceFilterPair> { //TODO wifi icon private Drawable BLUETOOTH_ICON = icon(android.R.drawable.stat_sys_data_bluetooth); @@ -369,8 +388,15 @@ public class DeviceDiscoveryService extends Service { public static <T extends Parcelable> DeviceFilterPair<T> findMatch( T dev, @Nullable List<? extends DeviceFilter<T>> filters) { if (isEmpty(filters)) return new DeviceFilterPair<>(dev, null); - final DeviceFilter<T> matchingFilter = CollectionUtils.find(filters, (f) -> f.matches(dev)); - return matchingFilter != null ? new DeviceFilterPair<>(dev, matchingFilter) : null; + final DeviceFilter<T> matchingFilter + = CollectionUtils.find(filters, f -> f.matches(dev)); + + DeviceFilterPair<T> result = matchingFilter != null + ? new DeviceFilterPair<>(dev, matchingFilter) + : null; + if (DEBUG) Log.i(LOG_TAG, "findMatch(dev = " + dev + ", filters = " + filters + + ") -> " + result); + return result; } public String getDisplayName() { diff --git a/packages/DefaultContainerService/AndroidManifest.xml b/packages/DefaultContainerService/AndroidManifest.xml index 55d000c14ad1..e399fb170759 100644 --- a/packages/DefaultContainerService/AndroidManifest.xml +++ b/packages/DefaultContainerService/AndroidManifest.xml @@ -1,5 +1,6 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.defcontainer" coreApp="true"> + <uses-permission android:name="android.permission.ALLOCATE_AGGRESSIVE"/> <uses-permission android:name="android.permission.ASEC_ACCESS"/> <uses-permission android:name="android.permission.ASEC_CREATE"/> <uses-permission android:name="android.permission.ASEC_DESTROY"/> diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java index 37a68e0c557a..934787774637 100644 --- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java @@ -30,6 +30,7 @@ import android.content.pm.PackageParser.PackageLite; import android.content.pm.PackageParser.PackageParserException; import android.content.res.ObbInfo; import android.content.res.ObbScanner; +import android.os.Binder; import android.os.Environment; import android.os.Environment.UserEnvironment; import android.os.FileUtils; @@ -179,6 +180,15 @@ public class DefaultContainerService extends IntentService { return ret; } + final int recommendedInstallLocation; + final long token = Binder.clearCallingIdentity(); + try { + recommendedInstallLocation = PackageHelper.resolveInstallLocation(context, + pkg.packageName, pkg.installLocation, sizeBytes, flags); + } finally { + Binder.restoreCallingIdentity(token); + } + ret.packageName = pkg.packageName; ret.splitNames = pkg.splitNames; ret.versionCode = pkg.versionCode; @@ -186,8 +196,7 @@ public class DefaultContainerService extends IntentService { ret.splitRevisionCodes = pkg.splitRevisionCodes; ret.installLocation = pkg.installLocation; ret.verifiers = pkg.verifiers; - ret.recommendedInstallLocation = PackageHelper.resolveInstallLocation(context, - pkg.packageName, pkg.installLocation, sizeBytes, flags); + ret.recommendedInstallLocation = recommendedInstallLocation; ret.multiArch = pkg.multiArch; return ret; diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java index f59f0d97d24b..689e38142988 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 @@ public class NekoLand extends Activity implements PrefsListener { 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 9d2f7bbf155f..235b621097cb 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 ea8837b32474..911ff54cad6c 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 194e66b4a05b..1eb3020f4a7b 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 e60b5a9a373a..db88f2c038ec 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java @@ -509,7 +509,7 @@ public class MtpDocumentsProvider extends DocumentsProvider { 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 @@ public class MtpDocumentsProvider extends DocumentsProvider { 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 664d3c99344b..fa1a12030240 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 @@ import java.util.Set; */ 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 class MtpDocumentsService extends Service { 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 @@ public class MtpDocumentsService extends Service { * 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 StatusBarNotification[] activeNotifications = - mNotificationManager.getActiveNotifications(); + 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 (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; + 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(record.deviceId, createNotification(this, record)); + // 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 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 @@ public class MtpDocumentsService extends Service { 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 d8c3d357b563..c5292b878f37 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 @@ class ServiceIntentSender { /** * 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 74dd429d8af5..ed2dc3826a67 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 ae0a45c78ff9..7fd2238703f1 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 @@ public class MainActivity extends Activity { 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 afbd0d151b3d..a6778c82021a 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 @@ public class OSUWebView extends Activity { 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-km/strings.xml b/packages/PrintSpooler/res/values-km/strings.xml index 2bc7baa8a4ff..44098566e496 100644 --- a/packages/PrintSpooler/res/values-km/strings.xml +++ b/packages/PrintSpooler/res/values-km/strings.xml @@ -61,8 +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> - <string name="notification_channel_progress" msgid="872788690775721436">"កំពុងដំណើរការកិច្ចការបោះពុម្ព"</string> - <string name="notification_channel_failure" msgid="9042250774797916414">"មិនអាចដំណើរការកិច្ចការបោះពុម្ពបានទេ"</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-pa/strings.xml b/packages/PrintSpooler/res/values-pa/strings.xml index 6fd021b3082c..d7885ad32cf2 100644 --- a/packages/PrintSpooler/res/values-pa/strings.xml +++ b/packages/PrintSpooler/res/values-pa/strings.xml @@ -61,8 +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> - <string name="notification_channel_progress" msgid="872788690775721436">"ਚੱਲ ਰਹੇ ਪ੍ਰਿੰਟ ਕੰਮ"</string> - <string name="notification_channel_failure" msgid="9042250774797916414">"ਪ੍ਰਿੰਟ ਦੇ ਕੰਮ ਅਸਫਲ ਰਹੇ"</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/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java index 4cce166db645..ccdec6216679 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 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat 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 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat 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 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat // 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 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat 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 6f0caa244281..a9a6cbd47699 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 @@ public final class SelectPrinterActivity extends Activity implements 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 @@ public final class SelectPrinterActivity extends Activity implements 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 0bb4bfa18513..8b00ed053b26 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 @@ public final class PrintContentView extends ViewGroup implements View.OnClickLis @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/layout/settings_with_drawer.xml b/packages/SettingsLib/res/layout/settings_with_drawer.xml index e9c175f6fed0..55c192d56a4d 100644 --- a/packages/SettingsLib/res/layout/settings_with_drawer.xml +++ b/packages/SettingsLib/res/layout/settings_with_drawer.xml @@ -25,17 +25,13 @@ android:layout_height="match_parent" android:orientation="vertical" android:fitsSystemWindows="true"> - <FrameLayout + <Toolbar + android:id="@+id/action_bar" style="?android:attr/actionBarStyle" android:layout_width="match_parent" android:layout_height="wrap_content" - android:theme="?android:attr/actionBarTheme"> - <Toolbar - android:id="@+id/action_bar" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:navigationContentDescription="@*android:string/action_bar_up_description"/> - </FrameLayout> + android:theme="?android:attr/actionBarTheme" + android:navigationContentDescription="@*android:string/action_bar_up_description"/> <FrameLayout android:id="@+id/content_header_container" style="?android:attr/actionBarStyle" diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index 94c3907ce784..f92cac831f65 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -125,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"> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index acc0ce07007c..32a950465e85 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-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml index 2b762dfa5a14..444ffbc4de22 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 2f92ecdc0163..8f4aec1a446f 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -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-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 701d80d27820..875e8517410d 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 f7c95f0628b8..3def72d33296 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-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 89f82afb745a..9c5c22bb6ef8 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-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index 67412cf036e2..c31f12d72ea8 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-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index db590f78a749..ebed18ddc90e 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 ad9c7694b52b..70cac5e060d3 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 34f2822eed60..82ffa683a425 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -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 5b2541c8e7d1..2d8defafdcc5 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.BatteryStats.HistoryItem; 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 @@ public class BatteryInfo { 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 @@ public class BatteryInfo { 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 @@ public class BatteryInfo { : 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 78ad34acf8f0..0ab296e3405a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/Utils.java +++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java @@ -186,6 +186,11 @@ public class Utils { 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 8833fb8cab53..8a86c13abb7d 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 @@ public class ApplicationsState { 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 @@ public class ApplicationsState { @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 class ApplicationsState { } }; - 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/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java index 61ca13d2819a..9d6505bc5130 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 class BatteryMeterDrawableBase extends Drawable { 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 @@ public class BatteryMeterDrawableBase extends Drawable { 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 @@ public class BatteryMeterDrawableBase extends Drawable { 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 @@ public class BatteryMeterDrawableBase extends Drawable { 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 @@ public class BatteryMeterDrawableBase extends Drawable { 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 @@ public class BatteryMeterDrawableBase extends Drawable { 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 @@ public class BatteryMeterDrawableBase extends Drawable { 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 class BatteryMeterDrawableBase extends Drawable { 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 c6a45bcf1e9f..e2c05a193882 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 class UsageView extends FrameLayout { 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 @@ public class UsageView extends FrameLayout { 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 901848af43a0..9e9bc9359cda 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 @@ public class AccessPoint implements Comparable<AccessPoint> { 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(); + 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; - if (mAccessPointListener != null) { - mAccessPointListener.onAccessPointChanged(this); - } } 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 fc8c42cd663f..314791e3105a 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 @@ public class WifiTracker { 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() @@ -233,10 +234,19 @@ public class WifiTracker { } /** - * Forces an update of the wifi networks when not scanning. + * Synchronously update the list of access points with the latest information. */ public void forceUpdate() { + mWorkHandler.removeMessages(WorkHandler.MSG_UPDATE_ACCESS_POINTS); + + mLastInfo = mWifiManager.getConnectionInfo(); + mLastNetworkInfo = mConnectivityManager.getNetworkInfo(mWifiManager.getCurrentNetwork()); updateAccessPoints(); + + // Synchronously copy access points + mMainHandler.removeMessages(MainHandler.MSG_ACCESS_POINT_CHANGED); + mMainHandler.handleMessage( + Message.obtain(mMainHandler, MainHandler.MSG_ACCESS_POINT_CHANGED)); } /** @@ -640,20 +650,24 @@ public class WifiTracker { (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 +732,8 @@ public class WifiTracker { 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 6a029f0be64d..fed18fa1bcb0 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 @@ public class ApplicationsStateTest { } @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 @@ public class ApplicationsStateTest { } @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 4de2c1249241..83667ea00629 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 @@ public class BatteryMeterDrawableBaseTest { 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 85b04c8fdf15..820231ef76c4 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 @@ public class AppRestrictionsHelperTest extends BaseTest { 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 b71915f30e1c..b938fe2ac2db 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 @@ -20,9 +20,9 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; - import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; @@ -32,12 +32,13 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; +import android.net.Network; import android.net.NetworkBadging; import android.net.NetworkInfo; import android.net.NetworkKey; import android.net.NetworkScoreManager; -import android.net.ScoredNetwork; import android.net.RssiCurve; +import android.net.ScoredNetwork; import android.net.WifiKey; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; @@ -46,10 +47,10 @@ import android.net.wifi.WifiManager; import android.net.wifi.WifiNetworkScoreCache; import android.net.wifi.WifiSsid; import android.os.Bundle; -import android.os.SystemClock; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; +import android.os.SystemClock; import android.provider.Settings; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; @@ -61,8 +62,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; -import org.mockito.Matchers; import org.mockito.Captor; +import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; @@ -100,6 +101,16 @@ public class WifiTrackerTest { 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 @@ public class WifiTrackerTest { 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 @@ public class WifiTrackerTest { } @Test - public void scoreCacheUpdateScoresShouldTriggerOnAccessPointsChanged() throws InterruptedException { + public void scoreCacheUpdateScoresShouldTriggerOnAccessPointsChanged() + throws InterruptedException { WifiTracker tracker = createMockedWifiTracker(); startTracking(tracker); sendScanResultsAndProcess(tracker); @@ -463,7 +469,7 @@ public class WifiTrackerTest { @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,53 @@ public class WifiTrackerTest { 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); + } + + @Test + public void forceUpdateShouldSynchronouslyFetchLatestInformation() throws Exception { + when(mockWifiManager.getConnectionInfo()).thenReturn(CONNECTED_AP_1_INFO); + + WifiConfiguration configuration = new WifiConfiguration(); + configuration.SSID = SSID_1; + configuration.BSSID = BSSID_1; + configuration.networkId = CONNECTED_NETWORK_ID; + when(mockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(configuration)); + + NetworkInfo networkInfo = new NetworkInfo( + ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype"); + networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "connected", "test"); + when(mockConnectivityManager.getNetworkInfo(any(Network.class))).thenReturn(networkInfo); + + + WifiTracker tracker = createMockedWifiTracker(); + startTracking(tracker); + tracker.forceUpdate(); + + verify(mockWifiListener).onAccessPointsChanged(); + assertThat(tracker.getAccessPoints().size()).isEqualTo(2); + assertThat(tracker.getAccessPoints().get(0).isActive()).isTrue(); + } +}
\ 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 962c4e7c3a27..69efc9e76ae0 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.RobolectricTestRunner; 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 @@ public class BatteryInfoTest { 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 @@ public class BatteryInfoTest { 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 @@ public class BatteryInfoTest { 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 4a54c0e909d2..bac694f535a7 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 @@ class SettingsProtoDumpUtil { 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/res/values-b+sr+Latn/strings.xml b/packages/Shell/res/values-b+sr+Latn/strings.xml index 5809bfc25419..805aed68ba81 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 f69317c12a32..bea1c30d4d4a 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 8815e948811c..fab8063c96fb 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 53c5b1b6b2bc..5ee0c64c9591 100644 --- a/packages/SystemUI/Android.mk +++ b/packages/SystemUI/Android.mk @@ -35,6 +35,7 @@ LOCAL_STATIC_ANDROID_LIBRARIES := \ 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 8dde35782be5..4a7d0fd8d1ff 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 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem 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 interface NotificationMenuRowPlugin extends Plugin { 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 3ea22e9c1c81..39cba742d9b5 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 46aa39dc472b..e1bf6cbd2198 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 c7cfe88e35b4..b28a0cc16015 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 e1dfc04d689c..89caf904c803 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 04256f1882dc..86f81bc54dc6 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 dede5370d7a3..53a559f92f1a 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/anim/tv_pip_onboarding_background_enter_animation.xml b/packages/SystemUI/res/anim/tv_pip_onboarding_background_enter_animation.xml deleted file mode 100644 index 9ab41d0be525..000000000000 --- a/packages/SystemUI/res/anim/tv_pip_onboarding_background_enter_animation.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<set xmlns:android="http://schemas.android.com/apk/res/android"> - - <objectAnimator - android:propertyName="alpha" - android:valueFrom="0" - android:valueTo="0.9" - android:interpolator="@android:interpolator/linear" - android:duration="@integer/tv_pip_onboarding_anim_duration" /> -</set> diff --git a/packages/SystemUI/res/anim/tv_pip_onboarding_button_enter_animation.xml b/packages/SystemUI/res/anim/tv_pip_onboarding_button_enter_animation.xml deleted file mode 100644 index 01c263b05217..000000000000 --- a/packages/SystemUI/res/anim/tv_pip_onboarding_button_enter_animation.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<set xmlns:android="http://schemas.android.com/apk/res/android"> - - <objectAnimator - android:propertyName="translationY" - android:valueFrom="114dp" - android:valueTo="0dp" - android:interpolator="@android:interpolator/fast_out_slow_in" - android:duration="@integer/tv_pip_onboarding_anim_duration" /> - <objectAnimator - android:propertyName="alpha" - android:valueTo="1" - android:interpolator="@android:interpolator/linear" - android:duration="@integer/tv_pip_onboarding_anim_duration" /> -</set> diff --git a/packages/SystemUI/res/anim/tv_pip_onboarding_description_enter_animation.xml b/packages/SystemUI/res/anim/tv_pip_onboarding_description_enter_animation.xml deleted file mode 100644 index a12b3b680613..000000000000 --- a/packages/SystemUI/res/anim/tv_pip_onboarding_description_enter_animation.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<set xmlns:android="http://schemas.android.com/apk/res/android"> - - <objectAnimator - android:propertyName="translationY" - android:valueFrom="84dp" - android:valueTo="0dp" - android:interpolator="@android:interpolator/fast_out_slow_in" - android:duration="@integer/tv_pip_onboarding_anim_duration" /> - <objectAnimator - android:propertyName="alpha" - android:valueTo="1" - android:interpolator="@android:interpolator/linear" - android:duration="@integer/tv_pip_onboarding_anim_duration" /> -</set> diff --git a/packages/SystemUI/res/anim/tv_pip_onboarding_image_enter_animation.xml b/packages/SystemUI/res/anim/tv_pip_onboarding_image_enter_animation.xml deleted file mode 100644 index ae9677ed8a0a..000000000000 --- a/packages/SystemUI/res/anim/tv_pip_onboarding_image_enter_animation.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<set xmlns:android="http://schemas.android.com/apk/res/android"> - - <objectAnimator - android:propertyName="translationY" - android:valueFrom="114dp" - android:valueTo="0dp" - android:interpolator="@android:interpolator/fast_out_slow_in" - android:duration="@integer/tv_pip_onboarding_anim_duration" /> - <objectAnimator - android:propertyName="alpha" - android:valueTo="1" - android:interpolator="@android:interpolator/fast_out_slow_in" - android:duration="@integer/tv_pip_onboarding_anim_duration" /> -</set> diff --git a/packages/SystemUI/res/anim/tv_pip_onboarding_title_enter_animation.xml b/packages/SystemUI/res/anim/tv_pip_onboarding_title_enter_animation.xml deleted file mode 100644 index 4bde070dafbe..000000000000 --- a/packages/SystemUI/res/anim/tv_pip_onboarding_title_enter_animation.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<set xmlns:android="http://schemas.android.com/apk/res/android"> - - <objectAnimator - android:propertyName="translationY" - android:valueFrom="84dp" - android:valueTo="0dp" - android:interpolator="@android:interpolator/fast_out_slow_in" - android:duration="@integer/tv_pip_onboarding_anim_duration" /> - <objectAnimator - android:propertyName="alpha" - android:valueTo="1" - android:interpolator="@android:interpolator/fast_out_slow_in" - android:duration="@integer/tv_pip_onboarding_anim_duration" /> -</set> diff --git a/packages/SystemUI/res/anim/tv_pip_overlay_fade_out_animation.xml b/packages/SystemUI/res/anim/tv_pip_overlay_fade_out_animation.xml deleted file mode 100644 index a12ddffc0bfc..000000000000 --- a/packages/SystemUI/res/anim/tv_pip_overlay_fade_out_animation.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" - android:propertyName="alpha" - android:valueTo="0" - android:interpolator="@android:interpolator/fast_out_slow_in" - android:duration="500" /> diff --git a/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png Binary files differindex 6737c80fc8f9..32f1ed79c993 100644 --- a/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png +++ b/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png diff --git a/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png Binary files differindex d9e33eb3c54f..33826a664951 100644 --- a/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png +++ b/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png diff --git a/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png Binary files differindex 64daf208d235..c1157f4316cf 100644 --- a/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png +++ b/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_0.png b/packages/SystemUI/res/drawable-xhdpi/remote_0.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_1.png b/packages/SystemUI/res/drawable-xhdpi/remote_1.png Binary files differdeleted file mode 100644 index 252ff5ed4971..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_1.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_10.png b/packages/SystemUI/res/drawable-xhdpi/remote_10.png Binary files differdeleted file mode 100644 index 5e52b378abfe..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_10.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_100.png b/packages/SystemUI/res/drawable-xhdpi/remote_100.png Binary files differdeleted file mode 100644 index f604808357ca..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_101.png b/packages/SystemUI/res/drawable-xhdpi/remote_101.png Binary files differdeleted file mode 100644 index 0272e45267d6..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_101.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_102.png b/packages/SystemUI/res/drawable-xhdpi/remote_102.png Binary files differdeleted file mode 100644 index aaa35c01bb26..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_102.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_103.png b/packages/SystemUI/res/drawable-xhdpi/remote_103.png Binary files differdeleted file mode 100644 index 20f95a582737..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_103.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_104.png b/packages/SystemUI/res/drawable-xhdpi/remote_104.png Binary files differdeleted file mode 100644 index 052f23e67d3f..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_104.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_105.png b/packages/SystemUI/res/drawable-xhdpi/remote_105.png Binary files differdeleted file mode 100644 index c5c82566d62a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_105.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_106.png b/packages/SystemUI/res/drawable-xhdpi/remote_106.png Binary files differdeleted file mode 100644 index 4e804feaf18a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_106.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_107.png b/packages/SystemUI/res/drawable-xhdpi/remote_107.png Binary files differdeleted file mode 100644 index 76669ccd2193..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_107.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_108.png b/packages/SystemUI/res/drawable-xhdpi/remote_108.png Binary files differdeleted file mode 100644 index c1b2f3bb5a1a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_108.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_109.png b/packages/SystemUI/res/drawable-xhdpi/remote_109.png Binary files differdeleted file mode 100644 index 79e1d7b221b0..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_109.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_11.png b/packages/SystemUI/res/drawable-xhdpi/remote_11.png Binary files differdeleted file mode 100644 index cfec6cbd4722..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_11.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_110.png b/packages/SystemUI/res/drawable-xhdpi/remote_110.png Binary files differdeleted file mode 100644 index d90229739200..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_110.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_111.png b/packages/SystemUI/res/drawable-xhdpi/remote_111.png Binary files differdeleted file mode 100644 index e48ed0b4c3c4..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_111.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_112.png b/packages/SystemUI/res/drawable-xhdpi/remote_112.png Binary files differdeleted file mode 100644 index 90dd1a232cb3..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_112.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_113.png b/packages/SystemUI/res/drawable-xhdpi/remote_113.png Binary files differdeleted file mode 100644 index 8fb4ad2aad87..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_113.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_114.png b/packages/SystemUI/res/drawable-xhdpi/remote_114.png Binary files differdeleted file mode 100644 index 76873fb35534..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_114.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_115.png b/packages/SystemUI/res/drawable-xhdpi/remote_115.png Binary files differdeleted file mode 100644 index e923d4c53d19..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_115.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_116.png b/packages/SystemUI/res/drawable-xhdpi/remote_116.png Binary files differdeleted file mode 100644 index 41d512488e4a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_116.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_117.png b/packages/SystemUI/res/drawable-xhdpi/remote_117.png Binary files differdeleted file mode 100644 index eacde6446953..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_117.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_118.png b/packages/SystemUI/res/drawable-xhdpi/remote_118.png Binary files differdeleted file mode 100644 index 5dc1fb035f2a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_118.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_119.png b/packages/SystemUI/res/drawable-xhdpi/remote_119.png Binary files differdeleted file mode 100644 index a16f037f1599..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_119.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_12.png b/packages/SystemUI/res/drawable-xhdpi/remote_12.png Binary files differdeleted file mode 100644 index 28bb387291e9..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_12.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_120.png b/packages/SystemUI/res/drawable-xhdpi/remote_120.png Binary files differdeleted file mode 100644 index fe3ef4176991..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_120.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_121.png b/packages/SystemUI/res/drawable-xhdpi/remote_121.png Binary files differdeleted file mode 100644 index ef2b892ffe6d..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_121.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_122.png b/packages/SystemUI/res/drawable-xhdpi/remote_122.png Binary files differdeleted file mode 100644 index 53429765345c..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_122.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_123.png b/packages/SystemUI/res/drawable-xhdpi/remote_123.png Binary files differdeleted file mode 100644 index bb8a53a5aa68..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_123.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_124.png b/packages/SystemUI/res/drawable-xhdpi/remote_124.png Binary files differdeleted file mode 100644 index b68337e53e9d..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_124.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_125.png b/packages/SystemUI/res/drawable-xhdpi/remote_125.png Binary files differdeleted file mode 100644 index 81fa3a789542..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_125.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_126.png b/packages/SystemUI/res/drawable-xhdpi/remote_126.png Binary files differdeleted file mode 100644 index 2339d74f33e0..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_126.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_127.png b/packages/SystemUI/res/drawable-xhdpi/remote_127.png Binary files differdeleted file mode 100644 index 90d1e0b453df..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_127.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_128.png b/packages/SystemUI/res/drawable-xhdpi/remote_128.png Binary files differdeleted file mode 100644 index 6de4eb8cb77b..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_128.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_129.png b/packages/SystemUI/res/drawable-xhdpi/remote_129.png Binary files differdeleted file mode 100644 index 908607425ff8..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_129.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_13.png b/packages/SystemUI/res/drawable-xhdpi/remote_13.png Binary files differdeleted file mode 100644 index a1e212dc4f11..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_13.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_130.png b/packages/SystemUI/res/drawable-xhdpi/remote_130.png Binary files differdeleted file mode 100644 index 2bc9698cc095..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_130.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_131.png b/packages/SystemUI/res/drawable-xhdpi/remote_131.png Binary files differdeleted file mode 100644 index d18d2c672992..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_131.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_132.png b/packages/SystemUI/res/drawable-xhdpi/remote_132.png Binary files differdeleted file mode 100644 index 10a00cdd06bf..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_132.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_133.png b/packages/SystemUI/res/drawable-xhdpi/remote_133.png Binary files differdeleted file mode 100644 index 6f495b42513a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_133.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_134.png b/packages/SystemUI/res/drawable-xhdpi/remote_134.png Binary files differdeleted file mode 100644 index 703f2c634263..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_134.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_135.png b/packages/SystemUI/res/drawable-xhdpi/remote_135.png Binary files differdeleted file mode 100644 index f4105b0a38ab..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_135.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_136.png b/packages/SystemUI/res/drawable-xhdpi/remote_136.png Binary files differdeleted file mode 100644 index 0c3a5bcdc8a3..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_136.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_137.png b/packages/SystemUI/res/drawable-xhdpi/remote_137.png Binary files differdeleted file mode 100644 index cbebc05275e6..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_137.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_138.png b/packages/SystemUI/res/drawable-xhdpi/remote_138.png Binary files differdeleted file mode 100644 index 6dfefb0934d7..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_138.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_139.png b/packages/SystemUI/res/drawable-xhdpi/remote_139.png Binary files differdeleted file mode 100644 index 1acfdd6fbf50..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_139.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_14.png b/packages/SystemUI/res/drawable-xhdpi/remote_14.png Binary files differdeleted file mode 100644 index a503cdf2f54e..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_14.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_140.png b/packages/SystemUI/res/drawable-xhdpi/remote_140.png Binary files differdeleted file mode 100644 index 70d27c18f0ca..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_140.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_141.png b/packages/SystemUI/res/drawable-xhdpi/remote_141.png Binary files differdeleted file mode 100644 index d523a0c2c754..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_141.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_142.png b/packages/SystemUI/res/drawable-xhdpi/remote_142.png Binary files differdeleted file mode 100644 index ed6a65d1b9e1..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_142.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_143.png b/packages/SystemUI/res/drawable-xhdpi/remote_143.png Binary files differdeleted file mode 100644 index 9b048e693d4d..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_143.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_144.png b/packages/SystemUI/res/drawable-xhdpi/remote_144.png Binary files differdeleted file mode 100644 index 9e2337d15735..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_144.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_145.png b/packages/SystemUI/res/drawable-xhdpi/remote_145.png Binary files differdeleted file mode 100644 index 3f30629c6715..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_145.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_146.png b/packages/SystemUI/res/drawable-xhdpi/remote_146.png Binary files differdeleted file mode 100644 index 1288039fe4fb..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_146.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_147.png b/packages/SystemUI/res/drawable-xhdpi/remote_147.png Binary files differdeleted file mode 100644 index d060539088ef..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_147.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_148.png b/packages/SystemUI/res/drawable-xhdpi/remote_148.png Binary files differdeleted file mode 100644 index 5be839d42dfe..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_148.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_149.png b/packages/SystemUI/res/drawable-xhdpi/remote_149.png Binary files differdeleted file mode 100644 index 39d31bad5af7..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_149.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_15.png b/packages/SystemUI/res/drawable-xhdpi/remote_15.png Binary files differdeleted file mode 100644 index 56955952ebe1..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_150.png b/packages/SystemUI/res/drawable-xhdpi/remote_150.png Binary files differdeleted file mode 100644 index ec2667c2c3d3..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_150.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_151.png b/packages/SystemUI/res/drawable-xhdpi/remote_151.png Binary files differdeleted file mode 100644 index ec2667c2c3d3..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_151.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_152.png b/packages/SystemUI/res/drawable-xhdpi/remote_152.png Binary files differdeleted file mode 100644 index a5d58c8ff7b4..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_152.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_153.png b/packages/SystemUI/res/drawable-xhdpi/remote_153.png Binary files differdeleted file mode 100644 index a5d58c8ff7b4..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_153.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_154.png b/packages/SystemUI/res/drawable-xhdpi/remote_154.png Binary files differdeleted file mode 100644 index a5d58c8ff7b4..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_154.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_155.png b/packages/SystemUI/res/drawable-xhdpi/remote_155.png Binary files differdeleted file mode 100644 index 793d41179a18..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_155.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_156.png b/packages/SystemUI/res/drawable-xhdpi/remote_156.png Binary files differdeleted file mode 100644 index 793d41179a18..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_156.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_157.png b/packages/SystemUI/res/drawable-xhdpi/remote_157.png Binary files differdeleted file mode 100644 index f9d6cdc166f3..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_157.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_158.png b/packages/SystemUI/res/drawable-xhdpi/remote_158.png Binary files differdeleted file mode 100644 index da8d5d79f1ed..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_158.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_159.png b/packages/SystemUI/res/drawable-xhdpi/remote_159.png Binary files differdeleted file mode 100644 index 1e0b097db178..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_159.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_16.png b/packages/SystemUI/res/drawable-xhdpi/remote_16.png Binary files differdeleted file mode 100644 index 4ae106cc45d6..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_16.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_160.png b/packages/SystemUI/res/drawable-xhdpi/remote_160.png Binary files differdeleted file mode 100644 index 8aa68ad78783..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_160.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_161.png b/packages/SystemUI/res/drawable-xhdpi/remote_161.png Binary files differdeleted file mode 100644 index e49fdd9c71ba..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_161.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_162.png b/packages/SystemUI/res/drawable-xhdpi/remote_162.png Binary files differdeleted file mode 100644 index 69257a072b4a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_162.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_163.png b/packages/SystemUI/res/drawable-xhdpi/remote_163.png Binary files differdeleted file mode 100644 index 8f0c3d5f261e..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_163.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_164.png b/packages/SystemUI/res/drawable-xhdpi/remote_164.png Binary files differdeleted file mode 100644 index a4c3229e80a9..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_164.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_165.png b/packages/SystemUI/res/drawable-xhdpi/remote_165.png Binary files differdeleted file mode 100644 index 46fae23e534a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_165.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_166.png b/packages/SystemUI/res/drawable-xhdpi/remote_166.png Binary files differdeleted file mode 100644 index 40d5a9b76f4c..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_166.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_167.png b/packages/SystemUI/res/drawable-xhdpi/remote_167.png Binary files differdeleted file mode 100644 index 6bd0380a3e9a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_167.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_168.png b/packages/SystemUI/res/drawable-xhdpi/remote_168.png Binary files differdeleted file mode 100644 index 03904bf47dd4..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_168.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_169.png b/packages/SystemUI/res/drawable-xhdpi/remote_169.png Binary files differdeleted file mode 100644 index 564a1610d777..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_169.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_17.png b/packages/SystemUI/res/drawable-xhdpi/remote_17.png Binary files differdeleted file mode 100644 index 0703e1a183aa..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_17.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_170.png b/packages/SystemUI/res/drawable-xhdpi/remote_170.png Binary files differdeleted file mode 100644 index 0411f94479e2..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_170.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_171.png b/packages/SystemUI/res/drawable-xhdpi/remote_171.png Binary files differdeleted file mode 100644 index ec141e92e566..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_171.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_172.png b/packages/SystemUI/res/drawable-xhdpi/remote_172.png Binary files differdeleted file mode 100644 index cb9ecaf985b0..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_172.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_173.png b/packages/SystemUI/res/drawable-xhdpi/remote_173.png Binary files differdeleted file mode 100644 index 484ee5128bb8..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_173.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_174.png b/packages/SystemUI/res/drawable-xhdpi/remote_174.png Binary files differdeleted file mode 100644 index 85a31351c800..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_174.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_175.png b/packages/SystemUI/res/drawable-xhdpi/remote_175.png Binary files differdeleted file mode 100644 index edd65074519d..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_175.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_176.png b/packages/SystemUI/res/drawable-xhdpi/remote_176.png Binary files differdeleted file mode 100644 index d95a68b3020f..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_176.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_177.png b/packages/SystemUI/res/drawable-xhdpi/remote_177.png Binary files differdeleted file mode 100644 index 305641f8d83c..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_177.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_178.png b/packages/SystemUI/res/drawable-xhdpi/remote_178.png Binary files differdeleted file mode 100644 index 59de0e58446a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_178.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_179.png b/packages/SystemUI/res/drawable-xhdpi/remote_179.png Binary files differdeleted file mode 100644 index 414e548c17f6..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_179.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_18.png b/packages/SystemUI/res/drawable-xhdpi/remote_18.png Binary files differdeleted file mode 100644 index 74df1e4520d5..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_18.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_180.png b/packages/SystemUI/res/drawable-xhdpi/remote_180.png Binary files differdeleted file mode 100644 index b5d925c0997e..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_180.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_181.png b/packages/SystemUI/res/drawable-xhdpi/remote_181.png Binary files differdeleted file mode 100644 index e8a71278cc03..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_181.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_182.png b/packages/SystemUI/res/drawable-xhdpi/remote_182.png Binary files differdeleted file mode 100644 index 29c70375de42..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_182.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_183.png b/packages/SystemUI/res/drawable-xhdpi/remote_183.png Binary files differdeleted file mode 100644 index 9491d9467d2d..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_183.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_184.png b/packages/SystemUI/res/drawable-xhdpi/remote_184.png Binary files differdeleted file mode 100644 index 4aa0e3253a83..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_184.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_185.png b/packages/SystemUI/res/drawable-xhdpi/remote_185.png Binary files differdeleted file mode 100644 index 2a0dde86123d..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_185.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_186.png b/packages/SystemUI/res/drawable-xhdpi/remote_186.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_186.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_187.png b/packages/SystemUI/res/drawable-xhdpi/remote_187.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_187.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_188.png b/packages/SystemUI/res/drawable-xhdpi/remote_188.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_188.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_189.png b/packages/SystemUI/res/drawable-xhdpi/remote_189.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_189.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_19.png b/packages/SystemUI/res/drawable-xhdpi/remote_19.png Binary files differdeleted file mode 100644 index 222ea31194af..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_19.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_190.png b/packages/SystemUI/res/drawable-xhdpi/remote_190.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_190.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_191.png b/packages/SystemUI/res/drawable-xhdpi/remote_191.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_191.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_192.png b/packages/SystemUI/res/drawable-xhdpi/remote_192.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_192.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_193.png b/packages/SystemUI/res/drawable-xhdpi/remote_193.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_193.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_194.png b/packages/SystemUI/res/drawable-xhdpi/remote_194.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_194.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_195.png b/packages/SystemUI/res/drawable-xhdpi/remote_195.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_195.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_196.png b/packages/SystemUI/res/drawable-xhdpi/remote_196.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_196.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_197.png b/packages/SystemUI/res/drawable-xhdpi/remote_197.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_197.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_198.png b/packages/SystemUI/res/drawable-xhdpi/remote_198.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_198.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_199.png b/packages/SystemUI/res/drawable-xhdpi/remote_199.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_199.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_2.png b/packages/SystemUI/res/drawable-xhdpi/remote_2.png Binary files differdeleted file mode 100644 index fb3f7ef1364c..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_2.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_20.png b/packages/SystemUI/res/drawable-xhdpi/remote_20.png Binary files differdeleted file mode 100644 index 646587c3e29c..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_20.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_200.png b/packages/SystemUI/res/drawable-xhdpi/remote_200.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_200.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_201.png b/packages/SystemUI/res/drawable-xhdpi/remote_201.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_201.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_202.png b/packages/SystemUI/res/drawable-xhdpi/remote_202.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_202.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_203.png b/packages/SystemUI/res/drawable-xhdpi/remote_203.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_203.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_204.png b/packages/SystemUI/res/drawable-xhdpi/remote_204.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_204.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_205.png b/packages/SystemUI/res/drawable-xhdpi/remote_205.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_205.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_206.png b/packages/SystemUI/res/drawable-xhdpi/remote_206.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_206.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_207.png b/packages/SystemUI/res/drawable-xhdpi/remote_207.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_207.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_208.png b/packages/SystemUI/res/drawable-xhdpi/remote_208.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_208.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_209.png b/packages/SystemUI/res/drawable-xhdpi/remote_209.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_209.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_21.png b/packages/SystemUI/res/drawable-xhdpi/remote_21.png Binary files differdeleted file mode 100644 index 5858ba92ce7a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_21.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_210.png b/packages/SystemUI/res/drawable-xhdpi/remote_210.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_210.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_211.png b/packages/SystemUI/res/drawable-xhdpi/remote_211.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_211.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_212.png b/packages/SystemUI/res/drawable-xhdpi/remote_212.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_212.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_213.png b/packages/SystemUI/res/drawable-xhdpi/remote_213.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_213.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_214.png b/packages/SystemUI/res/drawable-xhdpi/remote_214.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_214.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_215.png b/packages/SystemUI/res/drawable-xhdpi/remote_215.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_215.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_216.png b/packages/SystemUI/res/drawable-xhdpi/remote_216.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_216.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_217.png b/packages/SystemUI/res/drawable-xhdpi/remote_217.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_217.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_218.png b/packages/SystemUI/res/drawable-xhdpi/remote_218.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_218.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_219.png b/packages/SystemUI/res/drawable-xhdpi/remote_219.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_219.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_22.png b/packages/SystemUI/res/drawable-xhdpi/remote_22.png Binary files differdeleted file mode 100644 index 197480232386..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_22.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_220.png b/packages/SystemUI/res/drawable-xhdpi/remote_220.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_220.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_221.png b/packages/SystemUI/res/drawable-xhdpi/remote_221.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_221.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_222.png b/packages/SystemUI/res/drawable-xhdpi/remote_222.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_222.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_223.png b/packages/SystemUI/res/drawable-xhdpi/remote_223.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_223.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_224.png b/packages/SystemUI/res/drawable-xhdpi/remote_224.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_224.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_225.png b/packages/SystemUI/res/drawable-xhdpi/remote_225.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_225.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_226.png b/packages/SystemUI/res/drawable-xhdpi/remote_226.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_226.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_227.png b/packages/SystemUI/res/drawable-xhdpi/remote_227.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_227.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_228.png b/packages/SystemUI/res/drawable-xhdpi/remote_228.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_228.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_229.png b/packages/SystemUI/res/drawable-xhdpi/remote_229.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_229.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_23.png b/packages/SystemUI/res/drawable-xhdpi/remote_23.png Binary files differdeleted file mode 100644 index 96b7c3546d76..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_23.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_230.png b/packages/SystemUI/res/drawable-xhdpi/remote_230.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_230.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_231.png b/packages/SystemUI/res/drawable-xhdpi/remote_231.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_231.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_232.png b/packages/SystemUI/res/drawable-xhdpi/remote_232.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_232.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_233.png b/packages/SystemUI/res/drawable-xhdpi/remote_233.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_233.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_234.png b/packages/SystemUI/res/drawable-xhdpi/remote_234.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_234.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_235.png b/packages/SystemUI/res/drawable-xhdpi/remote_235.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_235.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_236.png b/packages/SystemUI/res/drawable-xhdpi/remote_236.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_236.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_237.png b/packages/SystemUI/res/drawable-xhdpi/remote_237.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_237.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_238.png b/packages/SystemUI/res/drawable-xhdpi/remote_238.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_238.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_239.png b/packages/SystemUI/res/drawable-xhdpi/remote_239.png Binary files differdeleted file mode 100644 index 5bda52e3b089..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_239.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_24.png b/packages/SystemUI/res/drawable-xhdpi/remote_24.png Binary files differdeleted file mode 100644 index 0437200d773a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_24.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_25.png b/packages/SystemUI/res/drawable-xhdpi/remote_25.png Binary files differdeleted file mode 100644 index 60b0f154369c..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_25.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_26.png b/packages/SystemUI/res/drawable-xhdpi/remote_26.png Binary files differdeleted file mode 100644 index c34ed97b5c93..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_26.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_27.png b/packages/SystemUI/res/drawable-xhdpi/remote_27.png Binary files differdeleted file mode 100644 index 1a83664c5ebc..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_27.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_28.png b/packages/SystemUI/res/drawable-xhdpi/remote_28.png Binary files differdeleted file mode 100644 index a3685ad396ab..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_29.png b/packages/SystemUI/res/drawable-xhdpi/remote_29.png Binary files differdeleted file mode 100644 index f7135eb8321a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_29.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_3.png b/packages/SystemUI/res/drawable-xhdpi/remote_3.png Binary files differdeleted file mode 100644 index 937da65ea9a1..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_3.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_30.png b/packages/SystemUI/res/drawable-xhdpi/remote_30.png Binary files differdeleted file mode 100644 index 718cf524f151..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_30.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_31.png b/packages/SystemUI/res/drawable-xhdpi/remote_31.png Binary files differdeleted file mode 100644 index c0b55df68f75..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_31.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_32.png b/packages/SystemUI/res/drawable-xhdpi/remote_32.png Binary files differdeleted file mode 100644 index 7a1ce9fd43c6..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_32.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_33.png b/packages/SystemUI/res/drawable-xhdpi/remote_33.png Binary files differdeleted file mode 100644 index 5428bcf327ef..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_33.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_34.png b/packages/SystemUI/res/drawable-xhdpi/remote_34.png Binary files differdeleted file mode 100644 index 264efe87f164..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_34.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_35.png b/packages/SystemUI/res/drawable-xhdpi/remote_35.png Binary files differdeleted file mode 100644 index a5c450f4bab6..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_35.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_36.png b/packages/SystemUI/res/drawable-xhdpi/remote_36.png Binary files differdeleted file mode 100644 index 3e469e4a3b36..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_36.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_37.png b/packages/SystemUI/res/drawable-xhdpi/remote_37.png Binary files differdeleted file mode 100644 index 124ebe4f1599..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_37.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_38.png b/packages/SystemUI/res/drawable-xhdpi/remote_38.png Binary files differdeleted file mode 100644 index b2b48448c568..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_38.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_39.png b/packages/SystemUI/res/drawable-xhdpi/remote_39.png Binary files differdeleted file mode 100644 index a6d1733b1d6b..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_39.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_4.png b/packages/SystemUI/res/drawable-xhdpi/remote_4.png Binary files differdeleted file mode 100644 index c282f406839b..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_4.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_40.png b/packages/SystemUI/res/drawable-xhdpi/remote_40.png Binary files differdeleted file mode 100644 index 4cd615c16b93..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_40.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_41.png b/packages/SystemUI/res/drawable-xhdpi/remote_41.png Binary files differdeleted file mode 100644 index c746ae0fcc82..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_41.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_42.png b/packages/SystemUI/res/drawable-xhdpi/remote_42.png Binary files differdeleted file mode 100644 index a93f1984dce4..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_42.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_43.png b/packages/SystemUI/res/drawable-xhdpi/remote_43.png Binary files differdeleted file mode 100644 index 966e563e3fa2..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_44.png b/packages/SystemUI/res/drawable-xhdpi/remote_44.png Binary files differdeleted file mode 100644 index beb7031cd7aa..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_44.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_45.png b/packages/SystemUI/res/drawable-xhdpi/remote_45.png Binary files differdeleted file mode 100644 index 718e1678af57..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_45.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_46.png b/packages/SystemUI/res/drawable-xhdpi/remote_46.png Binary files differdeleted file mode 100644 index aa54ddbf61d1..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_46.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_47.png b/packages/SystemUI/res/drawable-xhdpi/remote_47.png Binary files differdeleted file mode 100644 index 1d112707ea68..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_47.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_48.png b/packages/SystemUI/res/drawable-xhdpi/remote_48.png Binary files differdeleted file mode 100644 index ab31163c9096..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_48.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_49.png b/packages/SystemUI/res/drawable-xhdpi/remote_49.png Binary files differdeleted file mode 100644 index 219b7f645484..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_49.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_5.png b/packages/SystemUI/res/drawable-xhdpi/remote_5.png Binary files differdeleted file mode 100644 index 15f69e19c75a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_5.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_50.png b/packages/SystemUI/res/drawable-xhdpi/remote_50.png Binary files differdeleted file mode 100644 index 8a9725fb6777..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_50.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_51.png b/packages/SystemUI/res/drawable-xhdpi/remote_51.png Binary files differdeleted file mode 100644 index bc839cfc7fbc..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_51.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_52.png b/packages/SystemUI/res/drawable-xhdpi/remote_52.png Binary files differdeleted file mode 100644 index 7bab6e54ad23..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_52.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_53.png b/packages/SystemUI/res/drawable-xhdpi/remote_53.png Binary files differdeleted file mode 100644 index 34ab855027f6..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_53.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_54.png b/packages/SystemUI/res/drawable-xhdpi/remote_54.png Binary files differdeleted file mode 100644 index 5bd9f59afe3b..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_54.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_55.png b/packages/SystemUI/res/drawable-xhdpi/remote_55.png Binary files differdeleted file mode 100644 index 1ff17f4c0aff..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_55.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_56.png b/packages/SystemUI/res/drawable-xhdpi/remote_56.png Binary files differdeleted file mode 100644 index d57e067639a9..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_56.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_57.png b/packages/SystemUI/res/drawable-xhdpi/remote_57.png Binary files differdeleted file mode 100644 index a1bdae110893..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_58.png b/packages/SystemUI/res/drawable-xhdpi/remote_58.png Binary files differdeleted file mode 100644 index c8bc6a4548ad..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_58.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_59.png b/packages/SystemUI/res/drawable-xhdpi/remote_59.png Binary files differdeleted file mode 100644 index 526a24ea965e..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_59.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_6.png b/packages/SystemUI/res/drawable-xhdpi/remote_6.png Binary files differdeleted file mode 100644 index 2b6732fca80e..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_6.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_60.png b/packages/SystemUI/res/drawable-xhdpi/remote_60.png Binary files differdeleted file mode 100644 index 080619ecbc7f..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_60.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_61.png b/packages/SystemUI/res/drawable-xhdpi/remote_61.png Binary files differdeleted file mode 100644 index 5932a8ca2952..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_61.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_62.png b/packages/SystemUI/res/drawable-xhdpi/remote_62.png Binary files differdeleted file mode 100644 index d1233dd34f3c..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_62.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_63.png b/packages/SystemUI/res/drawable-xhdpi/remote_63.png Binary files differdeleted file mode 100644 index 4f230c7cad23..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_63.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_64.png b/packages/SystemUI/res/drawable-xhdpi/remote_64.png Binary files differdeleted file mode 100644 index 6b89fcbdcefd..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_64.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_65.png b/packages/SystemUI/res/drawable-xhdpi/remote_65.png Binary files differdeleted file mode 100644 index 87597b1fae43..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_65.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_66.png b/packages/SystemUI/res/drawable-xhdpi/remote_66.png Binary files differdeleted file mode 100644 index 0ee8c1e4ab81..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_66.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_67.png b/packages/SystemUI/res/drawable-xhdpi/remote_67.png Binary files differdeleted file mode 100644 index 9aca8fddd52c..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_67.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_68.png b/packages/SystemUI/res/drawable-xhdpi/remote_68.png Binary files differdeleted file mode 100644 index 5f263aedff0c..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_68.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_69.png b/packages/SystemUI/res/drawable-xhdpi/remote_69.png Binary files differdeleted file mode 100644 index 1a22b61407c6..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_69.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_7.png b/packages/SystemUI/res/drawable-xhdpi/remote_7.png Binary files differdeleted file mode 100644 index 9d9d699a6560..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_7.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_70.png b/packages/SystemUI/res/drawable-xhdpi/remote_70.png Binary files differdeleted file mode 100644 index 0372c50f3a8a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_70.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_71.png b/packages/SystemUI/res/drawable-xhdpi/remote_71.png Binary files differdeleted file mode 100644 index 854e3e2b4bc7..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_72.png b/packages/SystemUI/res/drawable-xhdpi/remote_72.png Binary files differdeleted file mode 100644 index 691962448e30..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_72.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_73.png b/packages/SystemUI/res/drawable-xhdpi/remote_73.png Binary files differdeleted file mode 100644 index d8e9ae182e71..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_73.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_74.png b/packages/SystemUI/res/drawable-xhdpi/remote_74.png Binary files differdeleted file mode 100644 index 24e5b6abcdf0..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_74.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_75.png b/packages/SystemUI/res/drawable-xhdpi/remote_75.png Binary files differdeleted file mode 100644 index 369a3a9c0afd..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_75.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_76.png b/packages/SystemUI/res/drawable-xhdpi/remote_76.png Binary files differdeleted file mode 100644 index 96824c6dc575..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_76.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_77.png b/packages/SystemUI/res/drawable-xhdpi/remote_77.png Binary files differdeleted file mode 100644 index dd60ccad6ab3..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_77.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_78.png b/packages/SystemUI/res/drawable-xhdpi/remote_78.png Binary files differdeleted file mode 100644 index aa3460bfc890..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_78.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_79.png b/packages/SystemUI/res/drawable-xhdpi/remote_79.png Binary files differdeleted file mode 100644 index 9a60e3c9b629..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_79.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_8.png b/packages/SystemUI/res/drawable-xhdpi/remote_8.png Binary files differdeleted file mode 100644 index b73c7efb6edd..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_8.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_80.png b/packages/SystemUI/res/drawable-xhdpi/remote_80.png Binary files differdeleted file mode 100644 index cbf883c7972e..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_80.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_81.png b/packages/SystemUI/res/drawable-xhdpi/remote_81.png Binary files differdeleted file mode 100644 index 11a6add24bde..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_81.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_82.png b/packages/SystemUI/res/drawable-xhdpi/remote_82.png Binary files differdeleted file mode 100644 index e05105d9b8ea..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_82.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_83.png b/packages/SystemUI/res/drawable-xhdpi/remote_83.png Binary files differdeleted file mode 100644 index 57813aac5f0a..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_83.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_84.png b/packages/SystemUI/res/drawable-xhdpi/remote_84.png Binary files differdeleted file mode 100644 index 0f6f0fe6208b..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_84.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_85.png b/packages/SystemUI/res/drawable-xhdpi/remote_85.png Binary files differdeleted file mode 100644 index ada83ec852f4..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_86.png b/packages/SystemUI/res/drawable-xhdpi/remote_86.png Binary files differdeleted file mode 100644 index 442dd5181e67..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_86.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_87.png b/packages/SystemUI/res/drawable-xhdpi/remote_87.png Binary files differdeleted file mode 100644 index bdb4962a72a2..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_87.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_88.png b/packages/SystemUI/res/drawable-xhdpi/remote_88.png Binary files differdeleted file mode 100644 index b31800298bfd..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_88.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_89.png b/packages/SystemUI/res/drawable-xhdpi/remote_89.png Binary files differdeleted file mode 100644 index c4ed874495d6..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_89.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_9.png b/packages/SystemUI/res/drawable-xhdpi/remote_9.png Binary files differdeleted file mode 100644 index ce5041f64f4e..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_9.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_90.png b/packages/SystemUI/res/drawable-xhdpi/remote_90.png Binary files differdeleted file mode 100644 index 6a662f9d65a7..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_90.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_91.png b/packages/SystemUI/res/drawable-xhdpi/remote_91.png Binary files differdeleted file mode 100644 index 21be887a1234..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_91.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_92.png b/packages/SystemUI/res/drawable-xhdpi/remote_92.png Binary files differdeleted file mode 100644 index 1bc536165bc8..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_92.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_93.png b/packages/SystemUI/res/drawable-xhdpi/remote_93.png Binary files differdeleted file mode 100644 index 76495ac70941..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_93.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_94.png b/packages/SystemUI/res/drawable-xhdpi/remote_94.png Binary files differdeleted file mode 100644 index 081c84b9f011..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_94.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_95.png b/packages/SystemUI/res/drawable-xhdpi/remote_95.png Binary files differdeleted file mode 100644 index e9c27a8216b6..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_95.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_96.png b/packages/SystemUI/res/drawable-xhdpi/remote_96.png Binary files differdeleted file mode 100644 index 13696031d6dc..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_96.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_97.png b/packages/SystemUI/res/drawable-xhdpi/remote_97.png Binary files differdeleted file mode 100644 index fbd14583d989..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_97.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_98.png b/packages/SystemUI/res/drawable-xhdpi/remote_98.png Binary files differdeleted file mode 100644 index ccdd7a7aecca..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_98.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_99.png b/packages/SystemUI/res/drawable-xhdpi/remote_99.png Binary files differdeleted file mode 100644 index f3cb4db410cb..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/remote_99.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png Binary files differindex 49e0499c3bc8..8d58a7e01b42 100644 --- a/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png +++ b/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png diff --git a/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png Binary files differindex 0e6ca16fd5f1..6c04d1aaccea 100644 --- a/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png +++ b/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml b/packages/SystemUI/res/drawable/ic_data_off.xml index e055de77ebe5..b97ddaef6418 100644 --- a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml +++ b/packages/SystemUI/res/drawable/ic_data_off.xml @@ -1,5 +1,5 @@ <!-- - Copyright (C) 2016 The Android Open Source Project + Copyright (C) 2017 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,19 +14,14 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="32.0dp" - android:height="32.0dp" + android:width="24.0dp" + android:height="24.0dp" android:viewportWidth="24.0" android:viewportHeight="24.0"> <path - android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z" - android:fillColor="#FFFFFF"/> + 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="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" - android:fillAlpha="0.3" - android:fillColor="#FFFFFF"/> - <path - android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" - android:fillColor="#FFFFFF"/> + 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/stat_sys_signal_4.xml b/packages/SystemUI/res/drawable/ic_data_on.xml index 01f670311750..a65dc7922ceb 100644 --- a/packages/SystemUI/res/drawable/stat_sys_signal_4.xml +++ b/packages/SystemUI/res/drawable/ic_data_on.xml @@ -1,5 +1,5 @@ <!-- - Copyright (C) 2016 The Android Open Source Project + Copyright (C) 2017 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,15 +14,13 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="17.0dp" - android:height="17.0dp" + android:width="24.0dp" + android:height="24.0dp" android:viewportWidth="24.0" android:viewportHeight="24.0"> <path - android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" - android:fillColor="?attr/fillColor"/> - <path - android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" - android:fillColor="?attr/fillColor"/> + 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 000000000000..27a769724912 --- /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/ic_qs_signal_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml deleted file mode 100644 index 8a488170e438..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml +++ /dev/null @@ -1,32 +0,0 @@ -<!-- - Copyright (C) 2016 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="32.0dp" - android:height="32.0dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:pathData="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z" - android:fillColor="#FFFFFF"/> - <path - android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" - android:fillAlpha="0.3" - android:fillColor="#FFFFFF"/> - <path - android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" - android:fillColor="#FFFFFF"/> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml deleted file mode 100644 index 39cc94cad4db..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml +++ /dev/null @@ -1,32 +0,0 @@ -<!-- - Copyright (C) 2016 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="32.0dp" - android:height="32.0dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" - android:fillAlpha="0.3" - android:fillColor="#FFFFFF"/> - <path - android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" - android:fillColor="#FFFFFF"/> - <path - android:pathData="M14.1,14.1l2.9,0.0 0.0,-6.5 -15.0,15.0 12.1,0.0z" - android:fillColor="#FFFFFF"/> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml deleted file mode 100644 index 012e95e985ce..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml +++ /dev/null @@ -1,28 +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. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="32.0dp" - android:height="32.0dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" - android:fillColor="#FFFFFF"/> - <path - android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" - android:fillColor="#FFFFFF"/> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml deleted file mode 100644 index 96e2fd4e5f82..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml +++ /dev/null @@ -1,36 +0,0 @@ -<!-- - Copyright (C) 2015 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="32dp" - android:height="32dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:name="dot1" - android:fillColor="#FFFFFFFF" - android:pathData="M9.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/> - <path - android:name="dot2" - android:fillColor="#4DFFFFFF" - android:pathData="M14.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/> - <path - android:name="dot3" - android:fillColor="#4DFFFFFF" - android:pathData="M19.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/> - <path - android:fillColor="#4DFFFFFF" - android:pathData="M2.0,22.0l6.0,0.0 0.0,-4.0 14.0,0.0 0.0,-16.0z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change_animation.xml b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change_animation.xml deleted file mode 100644 index 2186aa82e83f..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change_animation.xml +++ /dev/null @@ -1,27 +0,0 @@ -<!-- - Copyright (C) 2015 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" - android:drawable="@drawable/ic_qs_signal_carrier_network_change" > - <target - android:name="dot1" - android:animation="@anim/ic_qs_signal_blink_1"/> - <target - android:name="dot2" - android:animation="@anim/ic_qs_signal_blink_2"/> - <target - android:name="dot3" - android:animation="@anim/ic_qs_signal_blink_3"/> -</animated-vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml deleted file mode 100644 index 326373ddc9e8..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml +++ /dev/null @@ -1,25 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="32dp" - android:height="32dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:fillColor="#4DFFFFFF" - android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml deleted file mode 100644 index 8baa4ebd0c26..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml +++ /dev/null @@ -1,28 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="32dp" - android:height="32dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:fillColor="#4DFFFFFF" - android:pathData="M2.0,22.0l20.0,0.0 0.0,-20.0z"/> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml deleted file mode 100644 index bf19a718e0fc..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml +++ /dev/null @@ -1,28 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="32dp" - android:height="32dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:fillColor="#4DFFFFFF" - android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M14.000000,10.000000l-12.000000,12.000000 12.000000,0.000000z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml deleted file mode 100644 index 01839e8589ef..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml +++ /dev/null @@ -1,28 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="32dp" - android:height="32dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:fillColor="#4DFFFFFF" - android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M16.700001,7.300000l-14.700001,14.700000 14.700001,0.000000z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml deleted file mode 100644 index 48151ad78a6c..000000000000 --- a/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml +++ /dev/null @@ -1,25 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="32dp" - android:height="32dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:fillColor="#FFFFFFFF" - android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml index 8ea9e0639108..0bdbc5f17be6 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 0b2bd22978a8..e27bc7a090c1 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 @@ Copyright (C) 2014 The Android Open Source Project 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/drawable/stat_sys_signal_0.xml b/packages/SystemUI/res/drawable/stat_sys_signal_0.xml deleted file mode 100644 index 8bc872a99951..000000000000 --- a/packages/SystemUI/res/drawable/stat_sys_signal_0.xml +++ /dev/null @@ -1,28 +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. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="17.0dp" - android:height="17.0dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" - android:fillColor="?attr/backgroundColor"/> - <path - android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" - android:fillColor="?attr/fillColor"/> -</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml deleted file mode 100644 index e267d25b43d9..000000000000 --- a/packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml +++ /dev/null @@ -1,25 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="17dp" - android:height="17dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:fillColor="?attr/backgroundColor" - android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml deleted file mode 100644 index 8fa7630b0fae..000000000000 --- a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml +++ /dev/null @@ -1,31 +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. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="17.0dp" - android:height="17.0dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z" - android:fillColor="?attr/fillColor"/> - <path - android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" - android:fillColor="?attr/backgroundColor"/> - <path - android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" - android:fillColor="?attr/fillColor"/> -</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml deleted file mode 100644 index 60822f409aee..000000000000 --- a/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml +++ /dev/null @@ -1,28 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="17dp" - android:height="17dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:fillColor="?attr/backgroundColor" - android:pathData="M2.0,22.0l20.0,0.0 0.0,-20.0z"/> - <path - android:fillColor="?attr/fillColor" - android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml b/packages/SystemUI/res/drawable/stat_sys_signal_2.xml deleted file mode 100644 index 2a660a39d510..000000000000 --- a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml +++ /dev/null @@ -1,31 +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. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="17.0dp" - android:height="17.0dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:pathData="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z" - android:fillColor="?attr/fillColor"/> - <path - android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" - android:fillColor="?attr/backgroundColor"/> - <path - android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" - android:fillColor="?attr/fillColor"/> -</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_2_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_2_fully.xml deleted file mode 100644 index 5e68eeda3b24..000000000000 --- a/packages/SystemUI/res/drawable/stat_sys_signal_2_fully.xml +++ /dev/null @@ -1,28 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="17dp" - android:height="17dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:fillColor="?attr/backgroundColor" - android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/> - <path - android:fillColor="?attr/fillColor" - android:pathData="M14.000000,10.000000l-12.000000,12.000000 12.000000,0.000000z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml b/packages/SystemUI/res/drawable/stat_sys_signal_3.xml deleted file mode 100644 index 9e0a43353eea..000000000000 --- a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml +++ /dev/null @@ -1,31 +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. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="17.0dp" - android:height="17.0dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z" - android:fillColor="?attr/backgroundColor"/> - <path - android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z" - android:fillColor="?attr/fillColor"/> - <path - android:pathData="M14.1,14.1l2.9,0.0 0.0,-6.5 -15.0,15.0 12.1,0.0z" - android:fillColor="?attr/fillColor"/> -</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_3_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_3_fully.xml deleted file mode 100644 index 599b34ae56a3..000000000000 --- a/packages/SystemUI/res/drawable/stat_sys_signal_3_fully.xml +++ /dev/null @@ -1,28 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="17dp" - android:height="17dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:fillColor="?attr/backgroundColor" - android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/> - <path - android:fillColor="?attr/fillColor" - android:pathData="M16.700001,7.300000l-14.700001,14.700000 14.700001,0.000000z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_4_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_4_fully.xml deleted file mode 100644 index b66d89a4c6bb..000000000000 --- a/packages/SystemUI/res/drawable/stat_sys_signal_4_fully.xml +++ /dev/null @@ -1,25 +0,0 @@ -<!-- -Copyright (C) 2014 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:autoMirrored="true" - android:width="17dp" - android:height="17dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:fillColor="?attr/singleToneColor" - android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change.xml b/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change.xml deleted file mode 100644 index f69ffe49b138..000000000000 --- a/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change.xml +++ /dev/null @@ -1,36 +0,0 @@ -<!-- - Copyright (C) 2015 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="17dp" - android:height="17dp" - android:viewportWidth="24.0" - android:viewportHeight="24.0"> - <path - android:name="dot1" - android:fillColor="?attr/fillColor" - android:pathData="M9.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/> - <path - android:name="dot2" - android:fillColor="?attr/backgroundColor" - android:pathData="M14.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/> - <path - android:name="dot3" - android:fillColor="?attr/backgroundColor" - android:pathData="M19.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/> - <path - android:fillColor="?attr/backgroundColor" - android:pathData="M2.0,22.0l6.0,0.0 0.0,-4.0 14.0,0.0 0.0,-16.0z"/> -</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change_animation.xml b/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change_animation.xml deleted file mode 100644 index 275f037778c0..000000000000 --- a/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change_animation.xml +++ /dev/null @@ -1,27 +0,0 @@ -<!-- - Copyright (C) 2015 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" - android:drawable="@drawable/stat_sys_signal_carrier_network_change" > - <target - android:name="dot1" - android:animation="@anim/ic_signal_blink_1"/> - <target - android:name="dot2" - android:animation="@anim/ic_signal_blink_2"/> - <target - android:name="dot3" - android:animation="@anim/ic_signal_blink_3"/> -</animated-vector> diff --git a/packages/SystemUI/res/drawable/tv_pip_onboarding_remote.xml b/packages/SystemUI/res/drawable/tv_pip_onboarding_remote.xml deleted file mode 100644 index d46108ae6ffc..000000000000 --- a/packages/SystemUI/res/drawable/tv_pip_onboarding_remote.xml +++ /dev/null @@ -1,259 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<animation-list xmlns:android="http://schemas.android.com/apk/res/android" - android:oneshot="false"> - - <item android:drawable="@drawable/remote_0" android:duration="13" /> - <item android:drawable="@drawable/remote_1" android:duration="13" /> - <item android:drawable="@drawable/remote_2" android:duration="13" /> - <item android:drawable="@drawable/remote_3" android:duration="13" /> - <item android:drawable="@drawable/remote_4" android:duration="13" /> - <item android:drawable="@drawable/remote_5" android:duration="13" /> - <item android:drawable="@drawable/remote_6" android:duration="13" /> - <item android:drawable="@drawable/remote_7" android:duration="13" /> - <item android:drawable="@drawable/remote_8" android:duration="13" /> - <item android:drawable="@drawable/remote_9" android:duration="13" /> - <item android:drawable="@drawable/remote_10" android:duration="13" /> - <item android:drawable="@drawable/remote_11" android:duration="13" /> - <item android:drawable="@drawable/remote_12" android:duration="13" /> - <item android:drawable="@drawable/remote_13" android:duration="13" /> - <item android:drawable="@drawable/remote_14" android:duration="13" /> - <item android:drawable="@drawable/remote_15" android:duration="13" /> - <item android:drawable="@drawable/remote_16" android:duration="13" /> - <item android:drawable="@drawable/remote_17" android:duration="13" /> - <item android:drawable="@drawable/remote_18" android:duration="13" /> - <item android:drawable="@drawable/remote_19" android:duration="13" /> - <item android:drawable="@drawable/remote_20" android:duration="13" /> - <item android:drawable="@drawable/remote_21" android:duration="13" /> - <item android:drawable="@drawable/remote_22" android:duration="13" /> - <item android:drawable="@drawable/remote_23" android:duration="13" /> - <item android:drawable="@drawable/remote_24" android:duration="13" /> - <item android:drawable="@drawable/remote_25" android:duration="13" /> - <item android:drawable="@drawable/remote_26" android:duration="13" /> - <item android:drawable="@drawable/remote_27" android:duration="13" /> - <item android:drawable="@drawable/remote_28" android:duration="13" /> - <item android:drawable="@drawable/remote_29" android:duration="13" /> - <item android:drawable="@drawable/remote_30" android:duration="13" /> - <item android:drawable="@drawable/remote_31" android:duration="13" /> - <item android:drawable="@drawable/remote_32" android:duration="13" /> - <item android:drawable="@drawable/remote_33" android:duration="13" /> - <item android:drawable="@drawable/remote_34" android:duration="13" /> - <item android:drawable="@drawable/remote_35" android:duration="13" /> - <item android:drawable="@drawable/remote_36" android:duration="13" /> - <item android:drawable="@drawable/remote_37" android:duration="13" /> - <item android:drawable="@drawable/remote_38" android:duration="13" /> - <item android:drawable="@drawable/remote_39" android:duration="13" /> - <item android:drawable="@drawable/remote_40" android:duration="13" /> - <item android:drawable="@drawable/remote_41" android:duration="13" /> - <item android:drawable="@drawable/remote_42" android:duration="13" /> - <item android:drawable="@drawable/remote_43" android:duration="13" /> - <item android:drawable="@drawable/remote_44" android:duration="13" /> - <item android:drawable="@drawable/remote_45" android:duration="13" /> - <item android:drawable="@drawable/remote_46" android:duration="13" /> - <item android:drawable="@drawable/remote_47" android:duration="13" /> - <item android:drawable="@drawable/remote_48" android:duration="13" /> - <item android:drawable="@drawable/remote_49" android:duration="13" /> - <item android:drawable="@drawable/remote_50" android:duration="13" /> - <item android:drawable="@drawable/remote_51" android:duration="13" /> - <item android:drawable="@drawable/remote_52" android:duration="13" /> - <item android:drawable="@drawable/remote_53" android:duration="13" /> - <item android:drawable="@drawable/remote_54" android:duration="13" /> - <item android:drawable="@drawable/remote_55" android:duration="13" /> - <item android:drawable="@drawable/remote_56" android:duration="13" /> - <item android:drawable="@drawable/remote_57" android:duration="13" /> - <item android:drawable="@drawable/remote_58" android:duration="13" /> - <item android:drawable="@drawable/remote_59" android:duration="13" /> - <item android:drawable="@drawable/remote_60" android:duration="13" /> - <item android:drawable="@drawable/remote_61" android:duration="13" /> - <item android:drawable="@drawable/remote_62" android:duration="13" /> - <item android:drawable="@drawable/remote_63" android:duration="13" /> - <item android:drawable="@drawable/remote_64" android:duration="13" /> - <item android:drawable="@drawable/remote_65" android:duration="13" /> - <item android:drawable="@drawable/remote_66" android:duration="13" /> - <item android:drawable="@drawable/remote_67" android:duration="13" /> - <item android:drawable="@drawable/remote_68" android:duration="13" /> - <item android:drawable="@drawable/remote_69" android:duration="13" /> - <item android:drawable="@drawable/remote_70" android:duration="13" /> - <item android:drawable="@drawable/remote_71" android:duration="13" /> - <item android:drawable="@drawable/remote_72" android:duration="13" /> - <item android:drawable="@drawable/remote_73" android:duration="13" /> - <item android:drawable="@drawable/remote_74" android:duration="13" /> - <item android:drawable="@drawable/remote_75" android:duration="13" /> - <item android:drawable="@drawable/remote_76" android:duration="13" /> - <item android:drawable="@drawable/remote_77" android:duration="13" /> - <item android:drawable="@drawable/remote_78" android:duration="13" /> - <item android:drawable="@drawable/remote_79" android:duration="13" /> - <item android:drawable="@drawable/remote_80" android:duration="13" /> - <item android:drawable="@drawable/remote_81" android:duration="13" /> - <item android:drawable="@drawable/remote_82" android:duration="13" /> - <item android:drawable="@drawable/remote_83" android:duration="13" /> - <item android:drawable="@drawable/remote_84" android:duration="13" /> - <item android:drawable="@drawable/remote_85" android:duration="13" /> - <item android:drawable="@drawable/remote_86" android:duration="13" /> - <item android:drawable="@drawable/remote_87" android:duration="13" /> - <item android:drawable="@drawable/remote_88" android:duration="13" /> - <item android:drawable="@drawable/remote_89" android:duration="13" /> - <item android:drawable="@drawable/remote_90" android:duration="13" /> - <item android:drawable="@drawable/remote_91" android:duration="13" /> - <item android:drawable="@drawable/remote_92" android:duration="13" /> - <item android:drawable="@drawable/remote_93" android:duration="13" /> - <item android:drawable="@drawable/remote_94" android:duration="13" /> - <item android:drawable="@drawable/remote_95" android:duration="13" /> - <item android:drawable="@drawable/remote_96" android:duration="13" /> - <item android:drawable="@drawable/remote_97" android:duration="13" /> - <item android:drawable="@drawable/remote_98" android:duration="13" /> - <item android:drawable="@drawable/remote_99" android:duration="13" /> - <item android:drawable="@drawable/remote_100" android:duration="13" /> - <item android:drawable="@drawable/remote_101" android:duration="13" /> - <item android:drawable="@drawable/remote_102" android:duration="13" /> - <item android:drawable="@drawable/remote_103" android:duration="13" /> - <item android:drawable="@drawable/remote_104" android:duration="13" /> - <item android:drawable="@drawable/remote_105" android:duration="13" /> - <item android:drawable="@drawable/remote_106" android:duration="13" /> - <item android:drawable="@drawable/remote_107" android:duration="13" /> - <item android:drawable="@drawable/remote_108" android:duration="13" /> - <item android:drawable="@drawable/remote_109" android:duration="13" /> - <item android:drawable="@drawable/remote_110" android:duration="13" /> - <item android:drawable="@drawable/remote_111" android:duration="13" /> - <item android:drawable="@drawable/remote_112" android:duration="13" /> - <item android:drawable="@drawable/remote_113" android:duration="13" /> - <item android:drawable="@drawable/remote_114" android:duration="13" /> - <item android:drawable="@drawable/remote_115" android:duration="13" /> - <item android:drawable="@drawable/remote_116" android:duration="13" /> - <item android:drawable="@drawable/remote_117" android:duration="13" /> - <item android:drawable="@drawable/remote_118" android:duration="13" /> - <item android:drawable="@drawable/remote_119" android:duration="13" /> - <item android:drawable="@drawable/remote_120" android:duration="13" /> - <item android:drawable="@drawable/remote_121" android:duration="13" /> - <item android:drawable="@drawable/remote_122" android:duration="13" /> - <item android:drawable="@drawable/remote_123" android:duration="13" /> - <item android:drawable="@drawable/remote_124" android:duration="13" /> - <item android:drawable="@drawable/remote_125" android:duration="13" /> - <item android:drawable="@drawable/remote_126" android:duration="13" /> - <item android:drawable="@drawable/remote_127" android:duration="13" /> - <item android:drawable="@drawable/remote_128" android:duration="13" /> - <item android:drawable="@drawable/remote_129" android:duration="13" /> - <item android:drawable="@drawable/remote_130" android:duration="13" /> - <item android:drawable="@drawable/remote_131" android:duration="13" /> - <item android:drawable="@drawable/remote_132" android:duration="13" /> - <item android:drawable="@drawable/remote_133" android:duration="13" /> - <item android:drawable="@drawable/remote_134" android:duration="13" /> - <item android:drawable="@drawable/remote_135" android:duration="13" /> - <item android:drawable="@drawable/remote_136" android:duration="13" /> - <item android:drawable="@drawable/remote_137" android:duration="13" /> - <item android:drawable="@drawable/remote_138" android:duration="13" /> - <item android:drawable="@drawable/remote_139" android:duration="13" /> - <item android:drawable="@drawable/remote_140" android:duration="13" /> - <item android:drawable="@drawable/remote_141" android:duration="13" /> - <item android:drawable="@drawable/remote_142" android:duration="13" /> - <item android:drawable="@drawable/remote_143" android:duration="13" /> - <item android:drawable="@drawable/remote_144" android:duration="13" /> - <item android:drawable="@drawable/remote_145" android:duration="13" /> - <item android:drawable="@drawable/remote_146" android:duration="13" /> - <item android:drawable="@drawable/remote_147" android:duration="13" /> - <item android:drawable="@drawable/remote_148" android:duration="13" /> - <item android:drawable="@drawable/remote_149" android:duration="13" /> - <item android:drawable="@drawable/remote_150" android:duration="13" /> - <item android:drawable="@drawable/remote_151" android:duration="13" /> - <item android:drawable="@drawable/remote_152" android:duration="13" /> - <item android:drawable="@drawable/remote_153" android:duration="13" /> - <item android:drawable="@drawable/remote_154" android:duration="13" /> - <item android:drawable="@drawable/remote_155" android:duration="13" /> - <item android:drawable="@drawable/remote_156" android:duration="13" /> - <item android:drawable="@drawable/remote_157" android:duration="13" /> - <item android:drawable="@drawable/remote_158" android:duration="13" /> - <item android:drawable="@drawable/remote_159" android:duration="13" /> - <item android:drawable="@drawable/remote_160" android:duration="13" /> - <item android:drawable="@drawable/remote_161" android:duration="13" /> - <item android:drawable="@drawable/remote_162" android:duration="13" /> - <item android:drawable="@drawable/remote_163" android:duration="13" /> - <item android:drawable="@drawable/remote_164" android:duration="13" /> - <item android:drawable="@drawable/remote_165" android:duration="13" /> - <item android:drawable="@drawable/remote_166" android:duration="13" /> - <item android:drawable="@drawable/remote_167" android:duration="13" /> - <item android:drawable="@drawable/remote_168" android:duration="13" /> - <item android:drawable="@drawable/remote_169" android:duration="13" /> - <item android:drawable="@drawable/remote_170" android:duration="13" /> - <item android:drawable="@drawable/remote_171" android:duration="13" /> - <item android:drawable="@drawable/remote_172" android:duration="13" /> - <item android:drawable="@drawable/remote_173" android:duration="13" /> - <item android:drawable="@drawable/remote_174" android:duration="13" /> - <item android:drawable="@drawable/remote_175" android:duration="13" /> - <item android:drawable="@drawable/remote_176" android:duration="13" /> - <item android:drawable="@drawable/remote_177" android:duration="13" /> - <item android:drawable="@drawable/remote_178" android:duration="13" /> - <item android:drawable="@drawable/remote_179" android:duration="13" /> - <item android:drawable="@drawable/remote_180" android:duration="13" /> - <item android:drawable="@drawable/remote_181" android:duration="13" /> - <item android:drawable="@drawable/remote_182" android:duration="13" /> - <item android:drawable="@drawable/remote_183" android:duration="13" /> - <item android:drawable="@drawable/remote_184" android:duration="13" /> - <item android:drawable="@drawable/remote_185" android:duration="13" /> - <item android:drawable="@drawable/remote_186" android:duration="13" /> - <item android:drawable="@drawable/remote_187" android:duration="13" /> - <item android:drawable="@drawable/remote_188" android:duration="13" /> - <item android:drawable="@drawable/remote_189" android:duration="13" /> - <item android:drawable="@drawable/remote_190" android:duration="13" /> - <item android:drawable="@drawable/remote_191" android:duration="13" /> - <item android:drawable="@drawable/remote_192" android:duration="13" /> - <item android:drawable="@drawable/remote_193" android:duration="13" /> - <item android:drawable="@drawable/remote_194" android:duration="13" /> - <item android:drawable="@drawable/remote_195" android:duration="13" /> - <item android:drawable="@drawable/remote_196" android:duration="13" /> - <item android:drawable="@drawable/remote_197" android:duration="13" /> - <item android:drawable="@drawable/remote_198" android:duration="13" /> - <item android:drawable="@drawable/remote_199" android:duration="13" /> - <item android:drawable="@drawable/remote_200" android:duration="13" /> - <item android:drawable="@drawable/remote_201" android:duration="13" /> - <item android:drawable="@drawable/remote_202" android:duration="13" /> - <item android:drawable="@drawable/remote_203" android:duration="13" /> - <item android:drawable="@drawable/remote_204" android:duration="13" /> - <item android:drawable="@drawable/remote_205" android:duration="13" /> - <item android:drawable="@drawable/remote_206" android:duration="13" /> - <item android:drawable="@drawable/remote_207" android:duration="13" /> - <item android:drawable="@drawable/remote_208" android:duration="13" /> - <item android:drawable="@drawable/remote_209" android:duration="13" /> - <item android:drawable="@drawable/remote_210" android:duration="13" /> - <item android:drawable="@drawable/remote_211" android:duration="13" /> - <item android:drawable="@drawable/remote_212" android:duration="13" /> - <item android:drawable="@drawable/remote_213" android:duration="13" /> - <item android:drawable="@drawable/remote_214" android:duration="13" /> - <item android:drawable="@drawable/remote_215" android:duration="13" /> - <item android:drawable="@drawable/remote_216" android:duration="13" /> - <item android:drawable="@drawable/remote_217" android:duration="13" /> - <item android:drawable="@drawable/remote_218" android:duration="13" /> - <item android:drawable="@drawable/remote_219" android:duration="13" /> - <item android:drawable="@drawable/remote_220" android:duration="13" /> - <item android:drawable="@drawable/remote_221" android:duration="13" /> - <item android:drawable="@drawable/remote_222" android:duration="13" /> - <item android:drawable="@drawable/remote_223" android:duration="13" /> - <item android:drawable="@drawable/remote_224" android:duration="13" /> - <item android:drawable="@drawable/remote_225" android:duration="13" /> - <item android:drawable="@drawable/remote_226" android:duration="13" /> - <item android:drawable="@drawable/remote_227" android:duration="13" /> - <item android:drawable="@drawable/remote_228" android:duration="13" /> - <item android:drawable="@drawable/remote_229" android:duration="13" /> - <item android:drawable="@drawable/remote_230" android:duration="13" /> - <item android:drawable="@drawable/remote_231" android:duration="13" /> - <item android:drawable="@drawable/remote_232" android:duration="13" /> - <item android:drawable="@drawable/remote_233" android:duration="13" /> - <item android:drawable="@drawable/remote_234" android:duration="13" /> - <item android:drawable="@drawable/remote_235" android:duration="13" /> - <item android:drawable="@drawable/remote_236" android:duration="13" /> - <item android:drawable="@drawable/remote_237" android:duration="13" /> - <item android:drawable="@drawable/remote_238" android:duration="13" /> - <item android:drawable="@drawable/remote_239" android:duration="13" /> -</animation-list> diff --git a/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml b/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml deleted file mode 100644 index 2b58fc5a5fd3..000000000000 --- a/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml +++ /dev/null @@ -1,20 +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. ---> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - - <stroke android:width="1dp" android:color="#33FFFFFF" /> -</shape> diff --git a/packages/SystemUI/res/drawable/tv_pip_overlay_text_background.xml b/packages/SystemUI/res/drawable/tv_pip_overlay_text_background.xml deleted file mode 100644 index e247dec3ae27..000000000000 --- a/packages/SystemUI/res/drawable/tv_pip_overlay_text_background.xml +++ /dev/null @@ -1,23 +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. ---> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - - <gradient - android:startColor="#B2000000" - android:endColor="#00000000" - android:angle="90"/> -</shape> diff --git a/packages/SystemUI/res/drawable/tv_pip_recents_overlay_scrim.xml b/packages/SystemUI/res/drawable/tv_pip_recents_overlay_scrim.xml deleted file mode 100644 index 57bee75165ee..000000000000 --- a/packages/SystemUI/res/drawable/tv_pip_recents_overlay_scrim.xml +++ /dev/null @@ -1,23 +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. ---> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - - <gradient - android:startColor="#80000000" - android:endColor="#00000000" - android:angle="90"/> -</shape> diff --git a/packages/SystemUI/res/layout/pip_dismiss_view.xml b/packages/SystemUI/res/layout/pip_dismiss_view.xml index 34228d9f2e2d..058f59faa566 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 44ced1736f65..8c66babd8a7f 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 660e4afbb43c..39d48ea4746e 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 64caefd3753c..9b53a97618ed 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/tv_pip_onboarding.xml b/packages/SystemUI/res/layout/tv_pip_onboarding.xml deleted file mode 100644 index fe80b9464a01..000000000000 --- a/packages/SystemUI/res/layout/tv_pip_onboarding.xml +++ /dev/null @@ -1,102 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -** -** Copyright 2016, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/pip_onboarding" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical"> - <View - android:id="@+id/background" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="#000000" - android:alpha="0" /> - - <ImageView - android:id="@+id/remote" - android:layout_width="72dp" - android:layout_height="273dp" - android:layout_marginTop="136dp" - android:layout_marginStart="304dp" - android:layout_alignParentTop="true" - android:layout_alignParentStart="true" - android:adjustViewBounds="true" - android:src="@drawable/remote" - android:alpha="0" /> - <ImageView - android:id="@+id/remote_button" - android:layout_width="50dp" - android:layout_height="50dp" - android:layout_marginTop="256dp" - android:layout_marginStart="315dp" - android:layout_alignParentTop="true" - android:layout_alignParentStart="true" - android:scaleType="fitXY" - android:src="@drawable/tv_pip_onboarding_remote" - android:alpha="0" /> - <TextView - android:id="@+id/title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="188dp" - android:layout_marginStart="406dp" - android:layout_alignParentTop="true" - android:layout_alignParentStart="true" - android:fontFamily="sans-serif" - android:textSize="24sp" - android:textColor="#EEEEEE" - android:text="@string/pip_onboarding_title" - android:alpha="0" /> - <TextView - android:id="@+id/description" - android:layout_width="200dp" - android:layout_height="wrap_content" - android:layout_marginTop="4dp" - android:layout_marginStart="408dp" - android:layout_below="@id/title" - android:layout_alignParentStart="true" - android:fontFamily="sans-serif" - android:textSize="14sp" - android:textColor="#EEEEEE" - android:lineSpacingMultiplier="1.46286" - android:text="@string/pip_onboarding_description" - android:alpha="0" /> - <Button - android:id="@+id/button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="16dp" - android:layout_marginStart="408dp" - android:layout_below="@id/description" - android:layout_alignParentStart="true" - android:gravity="center" - android:paddingTop="10dp" - android:paddingBottom="10dp" - android:paddingStart="24dp" - android:paddingEnd="24dp" - android:fontFamily="sans-serif-condensed" - android:textSize="16sp" - android:textColor="#FFFFFF" - android:textAllCaps="true" - android:text="@string/pip_onboarding_button" - android:alpha="0" - android:background="#009688" - android:elevation="4dp" /> -</RelativeLayout> diff --git a/packages/SystemUI/res/layout/tv_pip_overlay.xml b/packages/SystemUI/res/layout/tv_pip_overlay.xml deleted file mode 100644 index 608680cdf25f..000000000000 --- a/packages/SystemUI/res/layout/tv_pip_overlay.xml +++ /dev/null @@ -1,42 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -** -** Copyright 2016, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="@drawable/tv_pip_overlay_background"> - - <TextView - android:id="@+id/guide_overlay" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:paddingTop="6dp" - android:paddingBottom="6dp" - android:paddingStart="10dp" - android:paddingEnd="10dp" - android:textSize="14sp" - android:textColor="#EEEEEE" - android:fontFamily="sans-serif" - android:background="@drawable/tv_pip_overlay_text_background" - android:lineSpacingMultiplier="1.465" - android:gravity="center" - android:maxLines="2" - android:text="@string/pip_hold_home" /> -</RelativeLayout> diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml index c0be6762e4ed..870784079e77 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" > + android:layout_height="match_parent" + android:clipChildren="false" > - <com.android.systemui.volume.SegmentedButtons - android:id="@+id/zen_buttons" - android:background="@drawable/segmented_buttons_background" + <LinearLayout + android:id="@+id/edit_container" 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" /> + android:layout_height="match_parent" + android:background="?android:attr/colorPrimary" + android:clipChildren="false" + android:orientation="vertical"> - <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"> + <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" /> - <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" /> + <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" /> + <LinearLayout + 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_introduction_message" + android:id="@+id/zen_alarm_warning" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="12dp" - android:layout_marginStart="24dp" + android:layout_marginStart="18dp" + android:layout_marginEnd="16dp" android:textDirection="locale" android:lineSpacingMultiplier="1.20029" - android:layout_toStartOf="@id/zen_introduction_confirm" - android:textAppearance="@style/TextAppearance.QS.Introduction" /> + android:textAppearance="@style/TextAppearance.QS.Warning" /> + </LinearLayout> + + <LinearLayout + android:id="@android:id/empty" + android:layout_width="match_parent" + 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="@+id/zen_introduction_customize" - style="@style/QSBorderlessButton" + android:id="@android:id/title" 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" /> - <LinearLayout - android:id="@+id/zen_radio_buttons_content" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:orientation="vertical"/> + android:layout_marginTop="20dp" + android:textAppearance="@style/TextAppearance.QS.DetailEmpty"/> </LinearLayout> - <TextView - android:id="@+id/zen_alarm_warning" + <LinearLayout + android:id="@+id/auto_rule" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="18dp" + 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 8b5fab1b82d2..5859838ae99a 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 fba8bc4727c3..97b8317232c3 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 ec353358421d..f646dfa38789 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 5c62018f68e6..3223aa78fc41 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 0b44eb567393..1a1883ceb08a 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 8b01a835587c..67cdbd886e21 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 0796cffea349..59aa6055f46a 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 4b871a6311a0..88635fe31341 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 0a5a195a5c8c..a9bcf11b7c57 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 8c825094ac57..c0f6f510fb62 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 27390b966433..2ea22ec4f948 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 40347dcd9f2c..20b5bd6e63c7 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 af531a2e8c32..1b211d2cb197 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 a0f4a01b7258..68cb7e87b67f 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 7c8de3931ac7..e304b54849ca 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 25e68bb5fd9e..97801819b920 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 e36b22d78685..710c45500d0e 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 462a6e364a12..723be1531bc7 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 462a6e364a12..723be1531bc7 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 462a6e364a12..723be1531bc7 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 18fedb147d24..16e2549fe361 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 0a72eacc4f6f..2c21bae98b3f 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 b29af77062a1..fbe6dfcb837b 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 105079db7a69..c802e8a8a1c1 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 35e2a0ce90c8..9c35ddca8d89 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 ca555567363d..a949b8b815af 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 a9e788357b1e..ffbd4936adc9 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 1bcf6b4b5f94..d7f7115e3fe8 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 eb856c9ed403..ec65726a420e 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 e18628591256..3c3681de6a0f 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) --> - <skip /> - <!-- no translation found for bt_is_off (2640685272289706392) --> - <skip /> - <!-- no translation found for dnd_is_off (6167780215212497572) --> - <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) --> + <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_keep (1825009164681928736) --> + <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) --> <skip /> - <!-- no translation found for qs_dnd_replace (8019520786644276623) --> + <!-- 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-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index c41c06f5f42b..e4c107178c0d 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 dfcd5f2c6f7e..9e138aed0338 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 7ce96d3cfa0c..a34da6510f03 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 1fb282e43dd2..6635e6185218 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 153a5b725b4d..6c079440fc1d 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 e92c8d21fffd..57e031d9137d 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 b9141c7e8e55..1aab34153b34 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 d1a160cbf8f4..ab821b64b879 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) --> - <skip /> - <!-- no translation found for bt_is_off (2640685272289706392) --> - <skip /> - <!-- no translation found for dnd_is_off (6167780215212497572) --> - <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) --> + <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_keep (1825009164681928736) --> + <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) --> <skip /> - <!-- no translation found for qs_dnd_replace (8019520786644276623) --> + <!-- 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-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 4a8fb669ea65..9454d54fc52e 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 9099a0285942..5281011bfc7d 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 1ba56ac720d5..0ae02cc79047 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 989bd5e5fd25..6545d3ad951e 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 5b0a02d8bc29..fd3233ef5a2a 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 3bd22e26a644..649dd1ab85ff 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 1b0505d372c8..53b46f97c42b 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 02798f1d5513..72fc0c66f3b0 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 3470ad47d243..51d738cd7824 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 6bc7b38c22e7..b32ac24fa313 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 0b160f591f60..1ecb7cf2a934 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 2c949c9e2ca3..603224656c34 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 56d4b05cd25f..d33849d9db69 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 1bdb2723b27a..692753d20d12 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) --> - <skip /> - <!-- no translation found for bt_is_off (2640685272289706392) --> - <skip /> - <!-- no translation found for dnd_is_off (6167780215212497572) --> - <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) --> + <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 qs_dnd_keep (1825009164681928736) --> + <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) --> <skip /> - <!-- no translation found for qs_dnd_replace (8019520786644276623) --> + <!-- 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-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 76f2bf5159d3..89070f72b6e4 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 770ec034be6e..c7fb3d3645a2 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 4fe0bca13546..5bf6d5283315 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) --> - <skip /> - <!-- no translation found for bt_is_off (2640685272289706392) --> - <skip /> - <!-- no translation found for dnd_is_off (6167780215212497572) --> - <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) --> + <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 qs_dnd_keep (1825009164681928736) --> + <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) --> <skip /> - <!-- no translation found for qs_dnd_replace (8019520786644276623) --> + <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) --> <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 3c4203641a34..815293e291fc 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) --> - <skip /> - <!-- no translation found for bt_is_off (2640685272289706392) --> - <skip /> - <!-- no translation found for dnd_is_off (6167780215212497572) --> - <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) --> + <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 qs_dnd_keep (1825009164681928736) --> + <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) --> <skip /> - <!-- no translation found for qs_dnd_replace (8019520786644276623) --> + <!-- 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-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index cb75e5479709..1ad45bdf98fc 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 ee4df3880bde..183b22c53ec9 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 96eeb6a6af8f..8b9ee0b8101e 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 4ec9a0ec8c12..45e2fda3aeba 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 e8351f81a1f3..741b3d627b11 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 4ec9a0ec8c12..45e2fda3aeba 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 6cdc29c95b33..e7dffeeb7fe9 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 0bcdf7ae7f0a..75310a3e4c4a 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 419912357243..c71d5a20d131 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) --> - <skip /> - <!-- no translation found for bt_is_off (2640685272289706392) --> - <skip /> - <!-- no translation found for dnd_is_off (6167780215212497572) --> - <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) --> + <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 qs_dnd_keep (1825009164681928736) --> + <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) --> <skip /> - <!-- no translation found for qs_dnd_replace (8019520786644276623) --> + <!-- 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-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 829226e37818..59dce6ff9fb9 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 c661426a6f46..53ae44e8623c 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 dfbe4efd65de..12573bc0adec 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 f0f228fff413..664c30846adb 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 1d19a700692e..65d0712579fb 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 3dd253e4b2b8..1935944026c5 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 341f7578d86d..36d247f82f5d 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 a6a6fde6324e..766ee060887b 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 64e418d10913..ef281dc50c26 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 362867573732..9a0bad7b0d56 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 437516163510..af703c04b0d5 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 d999fc6efc1b..8edfa59583df 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 e612b6bf1edb..572f3278bd9e 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) --> - <skip /> - <!-- no translation found for bt_is_off (2640685272289706392) --> - <skip /> - <!-- no translation found for dnd_is_off (6167780215212497572) --> - <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) --> + <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 qs_dnd_keep (1825009164681928736) --> + <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) --> <skip /> - <!-- no translation found for qs_dnd_replace (8019520786644276623) --> + <!-- 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-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 844ff6016463..2f0fa7fbdab1 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 cefd071a806a..e9bc5877ce39 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 22464a60f5ee..a85548127b52 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 16101e1df44c..52d76500f404 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 e0a4b5752e7b..cd3eb5571b6b 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 e9968eb28cb0..491447788dff 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/colors_tv.xml b/packages/SystemUI/res/values/colors_tv.xml index 3817da017426..6e56d4a38d0c 100644 --- a/packages/SystemUI/res/values/colors_tv.xml +++ b/packages/SystemUI/res/values/colors_tv.xml @@ -21,4 +21,4 @@ <color name="recents_tv_card_title_text_color">#CCEEEEEE</color> <color name="recents_tv_dismiss_text_color">#7FEEEEEE</color> <color name="recents_tv_text_shadow_color">#7F000000</color> -</resources>
\ No newline at end of file +</resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 809648aba65b..9c7a6a00a4fb 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> @@ -738,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> @@ -760,4 +760,6 @@ <dimen name="default_gear_space">18dp</dimen> <dimen name="cell_overlay_padding">18dp</dimen> + <dimen name="signal_icon_size">17dp</dimen> + </resources> diff --git a/packages/SystemUI/res/values/integers_tv.xml b/packages/SystemUI/res/values/integers_tv.xml deleted file mode 100644 index 09547dad0705..000000000000 --- a/packages/SystemUI/res/values/integers_tv.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<resources> - <!-- Delay of the onboarding animation start after it launches --> - <integer name="tv_pip_onboarding_anim_start_delay">1000</integer> - <!-- Duration of the onboarding animation duration --> - <integer name="tv_pip_onboarding_anim_duration">1000</integer> -</resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 7bd9526cb274..eeb28c825ffa 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/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml index fb9e1f25f4dd..41626fcb0a49 100644 --- a/packages/SystemUI/res/values/strings_tv.xml +++ b/packages/SystemUI/res/values/strings_tv.xml @@ -27,14 +27,4 @@ <string name="pip_play">Play</string> <!-- Button to pause the current media on picture-in-picture (PIP) [CHAR LIMIT=30] --> <string name="pip_pause">Pause</string> - <!-- Overlay text on picture-in-picture (PIP) to indicate that longpress HOME key to control PIP [CHAR LIMIT=52] --> - <string name="pip_hold_home">Hold <b>HOME</b> to control PIP</string> - <!-- Picture-in-Picture (PIP) onboarding screen --> - <eat-comment /> - <!-- Title for picture-in-picture (PIP) onboarding screen to indicate that an user is in PIP mode. [CHAR LIMIT=NONE] --> - <string name="pip_onboarding_title">Picture-in-picture</string> - <!-- Description for picture-in-picture (PIP) onboarding screen to indicate that longpress HOME key to control PIP. [CHAR LIMIT=NONE] --> - <string name="pip_onboarding_description">This keeps your video in view until you play another one. Press and hold <b>HOME</b> to control it.</string> - <!-- Button to close picture-in-picture (PIP) onboarding screen. --> - <string name="pip_onboarding_button">Got it</string> </resources> diff --git a/packages/SystemUI/res/values/styles_tv.xml b/packages/SystemUI/res/values/styles_tv.xml index 3f0caab23ab4..0c4fd23ca107 100644 --- a/packages/SystemUI/res/values/styles_tv.xml +++ b/packages/SystemUI/res/values/styles_tv.xml @@ -21,5 +21,6 @@ <style name="PipTheme" parent="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:backgroundDimEnabled">false</item> + <item name="android:windowDisablePreview">true</item> </style> </resources> diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java b/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java index 0a89d9b15e26..e98ef0607951 100644 --- a/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java +++ b/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java @@ -37,8 +37,8 @@ public class EmergencyCarrierArea extends AlphaOptimizedLinearLayout { @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 5aa673b40124..abc3b94777b0 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java @@ -98,7 +98,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout 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 dd5544d2cdad..27a3f7d44890 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java @@ -143,7 +143,7 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { @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 590d8d5de672..c1cff9e8f735 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java @@ -79,11 +79,11 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { 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 d49ff975473d..b6184a883210 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java @@ -174,7 +174,7 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView 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 c2b57ffa6113..3c9a6b9dcdec 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java @@ -140,7 +140,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit 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 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit 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 108b466e44af..c04ae68dab36 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java @@ -171,7 +171,7 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView @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 8cdb906a0e56..b447979be45d 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -160,7 +160,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe } 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 839d3cec5e96..0cf890037f55 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java @@ -144,7 +144,7 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView { 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 3871448cb617..fb3cee74ab68 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java @@ -187,7 +187,7 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView { 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 b2b0ee463a97..162faa595ed3 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java @@ -115,14 +115,14 @@ public class KeyguardStatusView extends GridLayout { @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/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index f8d1bfbc18be..7a6ac571f9e0 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -165,11 +165,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private int mPhoneState; private boolean mKeyguardIsVisible; - /** - * If true, fingerprint was already authenticated and we don't need to start listening again - * until the Keyguard has been dismissed. - */ - private boolean mFingerprintAlreadyAuthenticated; private boolean mGoingToSleep; private boolean mBouncer; private boolean mBootCompleted; @@ -409,11 +404,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private void onFingerprintAuthenticated(int userId) { Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated"); mUserFingerprintAuthenticated.put(userId, true); - - // If fingerprint unlocking is allowed, this event will lead to a Keyguard dismiss or to a - // wake-up (if Keyguard is not showing), so we don't need to listen until Keyguard is - // fully gone. - mFingerprintAlreadyAuthenticated = isUnlockingWithFingerprintAllowed(); + // Don't send cancel if authentication succeeds + mFingerprintCancelSignal = null; for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -922,7 +914,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } mGoingToSleep = true; - mFingerprintAlreadyAuthenticated = false; updateFingerprintListeningState(); } @@ -1092,8 +1083,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private boolean shouldListenForFingerprint() { return (mKeyguardIsVisible || !mDeviceInteractive || mBouncer || mGoingToSleep) - && !mSwitchingUser && !mFingerprintAlreadyAuthenticated - && !isFingerprintDisabled(getCurrentUser()); + && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser()); } private void startListeningForFingerprint() { @@ -1416,9 +1406,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { cb.onKeyguardVisibilityChangedRaw(showing); } } - if (!showing) { - mFingerprintAlreadyAuthenticated = false; - } updateFingerprintListeningState(); } diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java index d57e88cce351..911ef244177c 100644 --- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java @@ -149,7 +149,7 @@ public class BatteryMeterView extends LinearLayout implements @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 429e859b5403..f4d4a9ff327d 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.StatusBarWindowManager; 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 @@ public class Dependency extends SystemUI { 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 0b0ea72053d3..7fed3e81682e 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.VelocityTracker; 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 @@ public class ExpandHelper implements Gefingerpoken { } }; + @VisibleForTesting + ObjectAnimator getScaleAnimation() { + return mScaleAnimation; + } + private class ViewScaler { ExpandableView mView; @@ -176,7 +182,8 @@ public class ExpandHelper implements Gefingerpoken { 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 @@ public class ExpandHelper implements Gefingerpoken { /** * @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 @@ public class ExpandHelper implements Gefingerpoken { * 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 class ExpandHelper implements Gefingerpoken { 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/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java index e1aaaa36d77a..1e9cbdc45425 100644 --- a/packages/SystemUI/src/com/android/systemui/Prefs.java +++ b/packages/SystemUI/src/com/android/systemui/Prefs.java @@ -41,7 +41,6 @@ public final class Prefs { Key.DND_FAVORITE_BUCKET_INDEX, Key.DND_NONE_SELECTED, Key.DND_FAVORITE_ZEN, - Key.TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN, Key.QS_HOTSPOT_ADDED, Key.QS_DATA_SAVER_ADDED, Key.QS_DATA_SAVER_DIALOG_SHOWN, @@ -62,7 +61,6 @@ public final class Prefs { String DND_FAVORITE_BUCKET_INDEX = "DndCountdownMinuteIndex"; String DND_NONE_SELECTED = "DndNoneSelected"; String DND_FAVORITE_ZEN = "DndFavoriteZen"; - String TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN = "TvPictureInPictureOnboardingShown"; String QS_HOTSPOT_ADDED = "QsHotspotAdded"; String QS_DATA_SAVER_ADDED = "QsDataSaverAdded"; String QS_DATA_SAVER_DIALOG_SHOWN = "QsDataSaverDialogShown"; diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index fbb075a5ae55..0eb469fe3366 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -158,6 +158,7 @@ public class SystemUIApplication extends Application implements SysUiServiceProv * 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 abcf27d28976..1d032e8aba48 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 @@ public class AssistOrbView extends FrameLayout { @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/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java index f3fb1efb7dec..ec56e15dbd8d 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java @@ -33,6 +33,8 @@ public interface DozeHost { boolean isPulsingBlocked(); void startPendingIntentDismissingKeyguard(PendingIntent intent); + void abortPulsing(); + void extendPulse(); interface Callback { default void onNotificationHeadsUp() {} diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java index f27521e20bbc..1cc5fb956c99 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java @@ -58,12 +58,15 @@ public class DozeMachine { /** Pulse is done showing. Followed by transition to DOZE or DOZE_AOD. */ DOZE_PULSE_DONE, /** Doze is done. DozeService is finished. */ - FINISH; + FINISH, + /** AOD, but the display is temporarily off. */ + DOZE_AOD_PAUSED; boolean canPulse() { switch (this) { case DOZE: case DOZE_AOD: + case DOZE_AOD_PAUSED: return true; default: return false; @@ -85,6 +88,7 @@ public class DozeMachine { case UNINITIALIZED: case INITIALIZED: case DOZE: + case DOZE_AOD_PAUSED: return Display.STATE_OFF; case DOZE_PULSING: case DOZE_AOD: @@ -241,6 +245,11 @@ public class DozeMachine { if (mState == State.FINISH) { return State.FINISH; } + if ((mState == State.DOZE_AOD_PAUSED || mState == State.DOZE_AOD || mState == State.DOZE) + && requestedState == State.DOZE_PULSE_DONE) { + Log.i(TAG, "Dropping pulse done because current state is already done: " + mState); + return mState; + } if (requestedState == State.DOZE_REQUEST_PULSE && !mState.canPulse()) { Log.i(TAG, "Dropping pulse request because current state can't pulse: " + mState); return mState; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index 2ac06579f259..73f522244a60 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -22,6 +22,8 @@ import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.TriggerEvent; import android.hardware.TriggerEventListener; @@ -40,6 +42,7 @@ import com.android.systemui.util.wakelock.WakeLock; import java.io.PrintWriter; import java.util.List; +import java.util.function.Consumer; public class DozeSensors { @@ -55,18 +58,22 @@ public class DozeSensors { private final DozeParameters mDozeParameters; private final AmbientDisplayConfiguration mConfig; private final WakeLock mWakeLock; + private final Consumer<Boolean> mProxCallback; private final Callback mCallback; private final Handler mHandler = new Handler(); + private final ProxSensor mProxSensor; public DozeSensors(Context context, SensorManager sensorManager, DozeParameters dozeParameters, - AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback) { + AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback, + Consumer<Boolean> proxCallback) { mContext = context; mSensorManager = sensorManager; mDozeParameters = dozeParameters; mConfig = config; mWakeLock = wakeLock; + mProxCallback = proxCallback; mResolver = mContext.getContentResolver(); mSensors = new TriggerSensor[] { @@ -86,6 +93,8 @@ public class DozeSensors { true /* configured */, DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP) }; + + mProxSensor = new ProxSensor(); mCallback = callback; } @@ -129,6 +138,10 @@ public class DozeSensors { } } + public void setProxListening(boolean listen) { + mProxSensor.setRegistered(listen); + } + private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange, Uri uri, int userId) { @@ -152,6 +165,43 @@ public class DozeSensors { } } + private class ProxSensor implements SensorEventListener { + + boolean mRegistered; + Boolean mCurrentlyFar; + + void setRegistered(boolean register) { + if (mRegistered == register) { + // Send an update even if we don't re-register. + mHandler.post(() -> { + if (mCurrentlyFar != null) { + mProxCallback.accept(mCurrentlyFar); + } + }); + return; + } + if (register) { + mRegistered = mSensorManager.registerListener(this, + mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY), + SensorManager.SENSOR_DELAY_NORMAL, mHandler); + } else { + mSensorManager.unregisterListener(this); + mRegistered = false; + mCurrentlyFar = null; + } + } + + @Override + public void onSensorChanged(SensorEvent event) { + mCurrentlyFar = event.values[0] >= event.sensor.getMaximumRange(); + mProxCallback.accept(mCurrentlyFar); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + } + } + private class TriggerSensor extends TriggerEventListener { final Sensor mSensor; final boolean mConfigured; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index 1b9bf73847b5..9b3593b9cbdd 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -46,6 +46,7 @@ import java.io.PrintWriter; public class DozeTriggers implements DozeMachine.Part { private static final String TAG = "DozeTriggers"; + private static final boolean DEBUG = DozeService.DEBUG; /** adb shell am broadcast -a com.android.systemui.doze.pulse com.android.systemui */ private static final String PULSE_ACTION = "com.android.systemui.doze.pulse"; @@ -81,7 +82,7 @@ public class DozeTriggers implements DozeMachine.Part { mWakeLock = wakeLock; mAllowPulseTriggers = allowPulseTriggers; mDozeSensors = new DozeSensors(context, mSensorManager, dozeParameters, config, - wakeLock, this::onSensor); + wakeLock, this::onSensor, this::onProximityFar); mUiModeManager = mContext.getSystemService(UiModeManager.class); } @@ -113,6 +114,22 @@ public class DozeTriggers implements DozeMachine.Part { } } + private void onProximityFar(boolean far) { + final boolean near = !far; + DozeMachine.State state = mMachine.getState(); + if (near && state == DozeMachine.State.DOZE_PULSING) { + if (DEBUG) Log.i(TAG, "Prox NEAR, ending pulse"); + mMachine.requestState(DozeMachine.State.DOZE_PULSE_DONE); + } + if (far && state == DozeMachine.State.DOZE_AOD_PAUSED) { + if (DEBUG) Log.i(TAG, "Prox FAR, unpausing AOD"); + mMachine.requestState(DozeMachine.State.DOZE_AOD); + } else if (near && state == DozeMachine.State.DOZE_AOD) { + if (DEBUG) Log.i(TAG, "Prox NEAR, pausing AOD"); + mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSED); + } + } + private void onCarMode() { mMachine.requestState(DozeMachine.State.FINISH); } @@ -131,15 +148,21 @@ public class DozeTriggers implements DozeMachine.Part { break; case DOZE: case DOZE_AOD: + case DOZE_AOD_PAUSED: + mDozeSensors.setProxListening(newState != DozeMachine.State.DOZE); mDozeSensors.setListening(true); if (oldState != DozeMachine.State.INITIALIZED) { mDozeSensors.reregisterAllSensors(); } break; + case DOZE_PULSING: + mDozeSensors.setProxListening(true); + break; case FINISH: mBroadcastReceiver.unregister(mContext); mDozeHost.removeCallback(mHostCallback); mDozeSensors.setListening(false); + mDozeSensors.setProxListening(false); break; default: } @@ -156,6 +179,7 @@ public class DozeTriggers implements DozeMachine.Part { private void requestPulse(final int reason, boolean performedProxCheck) { Assert.isMainThread(); + mDozeHost.extendPulse(); if (mPulsePending || !mAllowPulseTriggers || !canPulse()) { return; } @@ -286,6 +310,8 @@ public class DozeTriggers implements DozeMachine.Part { } private class TriggerReceiver extends BroadcastReceiver { + private boolean mRegistered; + @Override public void onReceive(Context context, Intent intent) { if (PULSE_ACTION.equals(intent.getAction())) { @@ -301,14 +327,22 @@ public class DozeTriggers implements DozeMachine.Part { } public void register(Context context) { + if (mRegistered) { + return; + } IntentFilter filter = new IntentFilter(PULSE_ACTION); filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE); filter.addAction(Intent.ACTION_USER_SWITCHED); context.registerReceiver(this, filter); + mRegistered = true; } public void unregister(Context context) { + if (!mRegistered) { + return; + } context.unregisterReceiver(this); + mRegistered = false; } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java index f577654c724c..6098a20a0c64 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java @@ -75,11 +75,14 @@ public class DozeUi implements DozeMachine.Part { scheduleTimeTick(); break; case DOZE: + case DOZE_AOD_PAUSED: unscheduleTimeTick(); break; case DOZE_REQUEST_PULSE: pulseWhileDozing(DozeLog.PULSE_REASON_NOTIFICATION /* TODO */); break; + case DOZE_PULSE_DONE: + mHost.abortPulsing(); case INITIALIZED: mHost.startDozing(); break; diff --git a/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java b/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java index cdda45f6b02c..f06ea451d4d0 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 class MLandActivity extends Activity { 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 2b6ea1572e6c..8ac97f3306be 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 android.view.View; 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 class FragmentHostManager { 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 @@ public class FragmentHostManager { // TODO: Do something? } - private View findViewById(int id) { + private <T extends View> T findViewById(int id) { return mRootView.findViewById(id); } @@ -245,7 +251,7 @@ public class FragmentHostManager { @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 114a59407487..c5653733bac7 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 @@ public class PipManager implements BasePipManager { 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 4e7cf723f662..ac0670348af2 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_ALL 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 @@ public class PipMenuActivity extends Activity { 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 @@ public class PipMenuActivity extends Activity { private ImageView mExpandButton; private int mBetweenActionPaddingLand; - private ObjectAnimator mMenuContainerAnimator; + private AnimatorSet mMenuContainerAnimator; + private ValueAnimator.AnimatorUpdateListener mMenuBgUpdateListener = new ValueAnimator.AnimatorUpdateListener() { @Override @@ -119,7 +125,8 @@ public class PipMenuActivity extends Activity { 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,19 +177,25 @@ public class PipMenuActivity extends Activity { 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); + setDisablePreviewScreenshots(true); } @Override @@ -236,7 +249,8 @@ public class PipMenuActivity extends Activity { 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 +273,28 @@ public class PipMenuActivity extends Activity { // 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 +305,6 @@ public class PipMenuActivity extends Activity { } }); } - mMenuContainerAnimator.addUpdateListener(mMenuBgUpdateListener); mMenuContainerAnimator.start(); } else { // If we are already visible, then just start the delayed dismiss and unregister any @@ -297,13 +321,18 @@ public class PipMenuActivity extends Activity { } 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 +341,9 @@ public class PipMenuActivity extends Activity { if (animationFinishedRunnable != null) { animationFinishedRunnable.run(); } - finish(); } }); - mMenuContainerAnimator.addUpdateListener(mMenuBgUpdateListener); mMenuContainerAnimator.start(); } else { // If the menu is not visible, just finish now @@ -332,11 +359,12 @@ public class PipMenuActivity extends Activity { 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 +393,14 @@ public class PipMenuActivity extends Activity { } 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 +455,17 @@ public class PipMenuActivity extends Activity { 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 +483,11 @@ public class PipMenuActivity extends Activity { 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 +514,12 @@ public class PipMenuActivity extends Activity { }, 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 875fb141bb7b..c41f898ef4fe 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 class PipMenuActivityController { 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 @@ public class PipMenuActivityController { /** * 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 @@ public class PipMenuActivityController { * 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 @@ public class PipMenuActivityController { 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 @@ public class PipMenuActivityController { @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 @@ public class PipMenuActivityController { 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 @@ public class PipMenuActivityController { 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 class PipMenuActivityController { } 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 @@ public class PipMenuActivityController { 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 @@ public class PipMenuActivityController { 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 @@ public class PipMenuActivityController { } /** - * @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 @@ public class PipMenuActivityController { /** * 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 @@ public class PipMenuActivityController { 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 @@ public class PipMenuActivityController { /** * 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 @@ public class PipMenuActivityController { 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/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java index fb8574da8e81..127296cd7f8e 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java @@ -37,10 +37,12 @@ import android.graphics.Rect; import android.os.Handler; import android.os.RemoteException; import android.util.Log; +import android.view.Choreographer; import android.view.animation.Interpolator; import com.android.internal.os.BackgroundThread; import com.android.internal.policy.PipSnapAlgorithm; +import com.android.internal.view.SurfaceFlingerVsyncChoreographer; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.statusbar.FlingAnimationUtils; @@ -72,6 +74,7 @@ public class PipMotionHelper { private Context mContext; private IActivityManager mActivityManager; + private SurfaceFlingerVsyncChoreographer mVsyncChoreographer; private Handler mHandler; private PipSnapAlgorithm mSnapAlgorithm; @@ -96,6 +99,8 @@ public class PipMotionHelper { mActivityManager = activityManager; mSnapAlgorithm = snapAlgorithm; mFlingAnimationUtils = flingAnimationUtils; + mVsyncChoreographer = new SurfaceFlingerVsyncChoreographer(mHandler, mContext.getDisplay(), + Choreographer.getInstance()); onConfigurationChanged(); } @@ -394,7 +399,7 @@ public class PipMotionHelper { */ private void resizePipUnchecked(Rect toBounds) { if (!toBounds.equals(mBounds)) { - mHandler.post(() -> { + mVsyncChoreographer.scheduleAtSfVsync(() -> { try { mActivityManager.resizePinnedStack(toBounds, null /* tempPinnedTaskBounds */); mBounds.set(toBounds); 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 161bdac77f89..3f26fddb1b3c 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 @@ public class PipTouchHandler implements TunerService.Tunable { 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 @@ public class PipTouchHandler implements TunerService.Tunable { */ 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 @@ public class PipTouchHandler implements TunerService.Tunable { 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 class PipTouchHandler implements TunerService.Tunable { 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 @@ public class PipTouchHandler implements TunerService.Tunable { // 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 @@ public class PipTouchHandler implements TunerService.Tunable { // above mNormalMovementBounds = normalMovementBounds; mExpandedMovementBounds = expandedMovementBounds; - updateMovementBounds(mIsMenuVisible); + updateMovementBounds(mMenuState); } private void onRegistrationChanged(boolean isRegistered) { @@ -303,8 +314,8 @@ public class PipTouchHandler implements TunerService.Tunable { } 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 @@ public class PipTouchHandler implements TunerService.Tunable { 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 @@ public class PipTouchHandler implements TunerService.Tunable { break; } } - return !mIsMenuVisible; + return mMenuState == MENU_STATE_NONE; } /** @@ -393,7 +404,7 @@ public class PipTouchHandler implements TunerService.Tunable { 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 @@ public class PipTouchHandler implements TunerService.Tunable { /** * 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 @@ public class PipTouchHandler implements TunerService.Tunable { 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 @@ public class PipTouchHandler implements TunerService.Tunable { } 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 @@ public class PipTouchHandler implements TunerService.Tunable { // 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 @@ public class PipTouchHandler implements TunerService.Tunable { !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 @@ public class PipTouchHandler implements TunerService.Tunable { } 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 @@ public class PipTouchHandler implements TunerService.Tunable { 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 @@ public class PipTouchHandler implements TunerService.Tunable { /** * 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 @@ public class PipTouchHandler implements TunerService.Tunable { 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 59cb0860fdfd..40a63d7d92c0 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 @@ public class PipControlButtonView extends RelativeLayout { .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 a2aff2df52e9..4c81907c35f7 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 class PipControlsView extends LinearLayout { 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 @@ public class PipControlsView extends LinearLayout { } }); - 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 @@ public class PipControlsView extends LinearLayout { } }); - 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/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java index ad290c388cb0..f2f0d7a5a86c 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java @@ -56,16 +56,12 @@ import java.util.List; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.view.Display.DEFAULT_DISPLAY; -import static com.android.systemui.Prefs.Key.TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN; - /** * Manages the picture-in-picture (PIP) UI and states. */ public class PipManager implements BasePipManager { private static final String TAG = "PipManager"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - private static final boolean DEBUG_FORCE_ONBOARDING = - SystemProperties.getBoolean("debug.tv.pip_force_onboarding", false); private static final String SETTINGS_PACKAGE_AND_CLASS_DELIMITER = "/"; private static PipManager sPipManager; @@ -76,10 +72,9 @@ public class PipManager implements BasePipManager { */ public static final int STATE_NO_PIP = 0; /** - * State when PIP is shown with an overlay message on top of it. - * This is used as default PIP state. + * State when PIP is shown. This is used as default PIP state. */ - public static final int STATE_PIP_OVERLAY = 1; + public static final int STATE_PIP = 1; /** * State when PIP menu dialog is shown. */ @@ -126,7 +121,6 @@ public class PipManager implements BasePipManager { private int mPipTaskId = TASK_ID_NO_PIP; private ComponentName mPipComponentName; private MediaController mPipMediaController; - private boolean mOnboardingShown; private String[] mLastPackagesResourceGranted; private final PinnedStackListener mPinnedStackListener = new PinnedStackListener(); @@ -212,8 +206,6 @@ public class PipManager implements BasePipManager { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_MEDIA_RESOURCE_GRANTED); mContext.registerReceiver(mBroadcastReceiver, intentFilter); - mOnboardingShown = Prefs.getBoolean( - mContext, TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN, false); if (sSettingsPackageAndClassNamePairList == null) { String[] settings = mContext.getResources().getStringArray( @@ -267,7 +259,7 @@ public class PipManager implements BasePipManager { // 1. Configuration changed due to the language change (RTL <-> RTL) // 2. SystemUI restarts after the crash mPipBounds = isSettingsShown() ? mSettingsPipBounds : mDefaultPipBounds; - resizePinnedStack(getPinnedStackInfo() == null ? STATE_NO_PIP : STATE_PIP_OVERLAY); + resizePinnedStack(getPinnedStackInfo() == null ? STATE_NO_PIP : STATE_PIP); } /** @@ -281,7 +273,7 @@ public class PipManager implements BasePipManager { * Shows the picture-in-picture menu if an activity is in picture-in-picture mode. */ public void showPictureInPictureMenu() { - if (mState == STATE_PIP_OVERLAY) { + if (mState == STATE_PIP) { resizePinnedStack(STATE_PIP_MENU); } } @@ -325,16 +317,6 @@ public class PipManager implements BasePipManager { } /** - * Shows PIP overlay UI by launching {@link PipOverlayActivity}. It also locates the pinned - * stack to the default PIP bound {@link com.android.internal.R.string - * .config_defaultPictureInPictureBounds}. - */ - private void showPipOverlay() { - if (DEBUG) Log.d(TAG, "showPipOverlay()"); - PipOverlayActivity.showPipOverlay(mContext); - } - - /** * Suspends resizing operation on the Pip until {@link #resumePipResizing} is called * @param reason The reason for suspending resizing operations on the Pip. */ @@ -388,7 +370,7 @@ public class PipManager implements BasePipManager { case STATE_PIP_MENU: mCurrentPipBounds = mMenuModePipBounds; break; - case STATE_PIP_OVERLAY: + case STATE_PIP: mCurrentPipBounds = mPipBounds; break; default: @@ -454,17 +436,6 @@ public class PipManager implements BasePipManager { mMediaListeners.remove(listener); } - private void launchPipOnboardingActivityIfNeeded() { - if (DEBUG_FORCE_ONBOARDING || !mOnboardingShown) { - mOnboardingShown = true; - Prefs.putBoolean(mContext, TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN, true); - - Intent intent = new Intent(mContext, PipOnboardingActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mContext.startActivity(intent); - } - } - /** * Returns {@code true} if PIP is shown. */ @@ -617,11 +588,11 @@ public class PipManager implements BasePipManager { return; } } - if (mState == STATE_PIP_OVERLAY) { + if (mState == STATE_PIP) { Rect bounds = isSettingsShown() ? mSettingsPipBounds : mDefaultPipBounds; if (mPipBounds != bounds) { mPipBounds = bounds; - resizePinnedStack(STATE_PIP_OVERLAY); + resizePinnedStack(STATE_PIP); } } } @@ -641,10 +612,9 @@ public class PipManager implements BasePipManager { mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1]; mPipComponentName = ComponentName.unflattenFromString( stackInfo.taskNames[stackInfo.taskNames.length - 1]); - // Set state to overlay so we show it when the pinned stack animation ends. - mState = STATE_PIP_OVERLAY; + // Set state to STATE_PIP so we show it when the pinned stack animation ends. + mState = STATE_PIP; mCurrentPipBounds = mPipBounds; - launchPipOnboardingActivityIfNeeded(); mMediaSessionManager.addOnActiveSessionsChangedListener( mActiveMediaSessionListener, null); updateMediaController(mMediaSessionManager.getActiveSessions(null)); @@ -671,9 +641,6 @@ public class PipManager implements BasePipManager { return; } switch (mState) { - case STATE_PIP_OVERLAY: - showPipOverlay(); - break; case STATE_PIP_MENU: showPipMenu(); break; 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 01d86b67eaf7..ce1bea19ef60 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 @@ public class PipMenuActivity extends Activity implements PipManager.Listener { 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); @@ -56,7 +56,7 @@ public class PipMenuActivity extends Activity implements PipManager.Listener { private void restorePipAndFinish() { if (mRestorePipSizeWhenClose) { // When PIP menu activity is closed, restore to the default position. - mPipManager.resizePinnedStack(PipManager.STATE_PIP_OVERLAY); + mPipManager.resizePinnedStack(PipManager.STATE_PIP); } finish(); } diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipOnboardingActivity.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipOnboardingActivity.java deleted file mode 100644 index 57952f43bc17..000000000000 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipOnboardingActivity.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.pip.tv; - -import android.animation.Animator; -import android.animation.AnimatorInflater; -import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; -import android.app.Activity; -import android.graphics.drawable.AnimationDrawable; -import android.os.Bundle; -import android.view.View; -import android.view.KeyEvent; -import android.widget.ImageView; - -import com.android.systemui.R; - -/** - * Activity to show an overlay on top of PIP activity to show how to pop up PIP menu. - */ -public class PipOnboardingActivity extends Activity implements PipManager.Listener { - private final PipManager mPipManager = PipManager.getInstance(); - private AnimatorSet mEnterAnimator; - - @Override - protected void onCreate(Bundle bundle) { - super.onCreate(bundle); - setContentView(R.layout.tv_pip_onboarding); - findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - finish(); - } - }); - - mPipManager.addListener(this); - } - - @Override - public void onResume() { - super.onResume(); - mEnterAnimator = new AnimatorSet(); - mEnterAnimator.playTogether( - loadAnimator(R.id.background, R.anim.tv_pip_onboarding_background_enter_animation), - loadAnimator(R.id.remote, R.anim.tv_pip_onboarding_image_enter_animation), - loadAnimator(R.id.remote_button, R.anim.tv_pip_onboarding_image_enter_animation), - loadAnimator(R.id.title, R.anim.tv_pip_onboarding_title_enter_animation), - loadAnimator(R.id.description, - R.anim.tv_pip_onboarding_description_enter_animation), - loadAnimator(R.id.button, R.anim.tv_pip_onboarding_button_enter_animation)); - mEnterAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - ImageView button = (ImageView) findViewById(R.id.remote_button); - ((AnimationDrawable) button.getDrawable()).start(); - } - }); - int delay = getResources().getInteger(R.integer.tv_pip_onboarding_anim_start_delay); - mEnterAnimator.setStartDelay(delay); - mEnterAnimator.start(); - } - - private Animator loadAnimator(int viewResId, int animResId) { - Animator animator = AnimatorInflater.loadAnimator(this, animResId); - animator.setTarget(findViewById(viewResId)); - return animator; - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - if (mEnterAnimator.isStarted()) { - return true; - } - return super.onKeyUp(keyCode, event); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (mEnterAnimator.isStarted()) { - return true; - } - return super.onKeyDown(keyCode, event); - } - - @Override - public void onPause() { - super.onPause(); - finish(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - mPipManager.removeListener(this); - } - - @Override - public void onPipEntered() { } - - @Override - public void onPipActivityClosed() { - finish(); - } - - @Override - public void onShowPipMenu() { - finish(); - } - - @Override - public void onMoveToFullscreen() { - finish(); - } - - @Override - public void onPipResizeAboutToStart() { } -} diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipOverlayActivity.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipOverlayActivity.java deleted file mode 100644 index f52121ff119f..000000000000 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipOverlayActivity.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.pip.tv; - -import android.animation.Animator; -import android.animation.AnimatorInflater; -import android.app.Activity; -import android.app.ActivityOptions; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.os.Handler; -import android.view.View; -import android.widget.ImageView; - -import com.android.systemui.R; - -import static android.app.ActivityManager.StackId.PINNED_STACK_ID; - -/** - * Activity to show an overlay on top of PIP activity to show how to pop up PIP menu. - */ -public class PipOverlayActivity extends Activity implements PipManager.Listener { - private static final long SHOW_GUIDE_OVERLAY_VIEW_DURATION_MS = 4000; - - /** - * A flag to ensure the single instance of PipOverlayActivity to prevent it from restarting. - * Note that {@link PipManager} moves the PIPed activity to fullscreen if the activity is - * restarted. It's because the activity may be started by the Launcher or an intent again, - * but we don't want do so for the PipOverlayActivity. - */ - private static boolean sActivityCreated; - - private final PipManager mPipManager = PipManager.getInstance(); - private final Handler mHandler = new Handler(); - private View mGuideOverlayView; - private View mGuideButtonsView; - private ImageView mGuideButtonPlayPauseImageView; - private final Runnable mHideGuideOverlayRunnable = new Runnable() { - public void run() { - mFadeOutAnimation.start(); - } - }; - private Animator mFadeInAnimation; - private Animator mFadeOutAnimation; - - /** - * Shows PIP overlay UI only if it's not there. - */ - static void showPipOverlay(Context context) { - if (!sActivityCreated) { - Intent intent = new Intent(context, PipOverlayActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - final ActivityOptions options = ActivityOptions.makeBasic(); - options.setLaunchStackId(PINNED_STACK_ID); - context.startActivity(intent, options.toBundle()); - } - } - - @Override - protected void onCreate(Bundle bundle) { - super.onCreate(bundle); - sActivityCreated = true; - setContentView(R.layout.tv_pip_overlay); - mGuideOverlayView = findViewById(R.id.guide_overlay); - mPipManager.addListener(this); - mFadeInAnimation = AnimatorInflater.loadAnimator( - this, R.anim.tv_pip_overlay_fade_in_animation); - mFadeInAnimation.setTarget(mGuideOverlayView); - mFadeOutAnimation = AnimatorInflater.loadAnimator( - this, R.anim.tv_pip_overlay_fade_out_animation); - mFadeOutAnimation.setTarget(mGuideOverlayView); - } - - @Override - protected void onResume() { - super.onResume(); - mFadeInAnimation.start(); - mHandler.removeCallbacks(mHideGuideOverlayRunnable); - mHandler.postDelayed(mHideGuideOverlayRunnable, SHOW_GUIDE_OVERLAY_VIEW_DURATION_MS); - } - - @Override - protected void onStop() { - super.onStop(); - mHandler.removeCallbacks(mHideGuideOverlayRunnable); - finish(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - sActivityCreated = false; - mHandler.removeCallbacksAndMessages(null); - mPipManager.removeListener(this); - mPipManager.resumePipResizing( - PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_OVERLAY_ACTIVITY_FINISH); - } - - @Override - public void onPipEntered() { } - - @Override - public void onPipActivityClosed() { - finish(); - } - - @Override - public void onShowPipMenu() { - finish(); - } - - @Override - public void onMoveToFullscreen() { - finish(); - } - - @Override - public void onPipResizeAboutToStart() { - finish(); - mPipManager.suspendPipResizing( - PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_OVERLAY_ACTIVITY_FINISH); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java index d2a291944d8d..f124e8686749 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 @@ public class QSDetail extends LinearLayout { @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 65238b118a6f..f91aa9a6d0b0 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 @@ public class QSDetailItems extends FrameLayout { @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 class QSDetailItems extends FrameLayout { } 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 2e6116dba7e9..38485c729b21 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.ImageView; 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 @@ public class QSPanel extends LinearLayout implements Tunable, Callback { 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 d0d6f6183670..7518527a3093 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.Color; 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 @@ public class QuickStatusBarHeader extends RelativeLayout { 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 596d3bc6e8f6..30053e35ef05 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 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene 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 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene 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 1aa51b1c38bf..6781c1673408 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.FIELD_ 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 @@ public abstract class QSTileImpl<TState extends State> implements QSTile { private String mTileSpec; private EnforcedAdmin mEnforcedAdmin; + private boolean mShowingDetail; public abstract TState newTileState(); @@ -286,11 +288,16 @@ public abstract class QSTileImpl<TState extends State> implements QSTile { } 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 @@ public abstract class QSTileImpl<TState extends State> implements QSTile { 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 5c998090bada..263dac0f44ec 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 @@ public class QSTileView extends QSTileBaseView { 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 @@ public class QSTileView extends QSTileBaseView { 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 @@ public class QSTileView extends QSTileBaseView { 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 8209ee2d5d99..ecc275db46b6 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 @@ public class BatterySaverTile extends QSTileImpl<BooleanState> implements 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 75e9d5ab063b..d27bb858a16b 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.Dependency; 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 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { return; } showDetail(true); - if (!mState.value) { - mState.value = true; - mController.setBluetoothEnabled(true); - } } @Override @@ -176,6 +172,9 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { @Override public void onBluetoothStateChange(boolean enabled) { refreshState(); + if (isShowingDetail()) { + mDetailAdapter.updateItems(); + } } @Override @@ -187,6 +186,9 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { } }); refreshState(); + if (isShowingDetail()) { + mDetailAdapter.updateItems(); + } } }; @@ -223,7 +225,6 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { public void setToggleState(boolean state) { MetricsLogger.action(mContext, MetricsEvent.QS_BLUETOOTH_TOGGLE, state); mController.setBluetoothEnabled(state); - showDetail(false); } @Override @@ -235,8 +236,6 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { 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 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { 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 9b3ee30a3ab0..92ff17a1f029 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.ActivityStarter; 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 @@ public class CellularTile extends QSTileImpl<SignalState> { @Override public QSIconView createTileView(Context context) { - return new CellTileView(context); + return new SignalTileView(context); } @Override @@ -118,15 +118,6 @@ public class CellularTile extends QSTileImpl<SignalState> { } 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 @@ public class CellularTile extends QSTileImpl<SignalState> { 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 @@ -164,7 +163,6 @@ public class CellularTile extends QSTileImpl<SignalState> { boolean enabled; boolean wifiEnabled; boolean airplaneModeEnabled; - int mobileSignalIconId; String signalContentDescription; int dataTypeIconId; String dataContentDescription; @@ -194,7 +192,6 @@ public class CellularTile extends QSTileImpl<SignalState> { return; } mInfo.enabled = qsIcon.visible; - mInfo.mobileSignalIconId = qsIcon.icon; mInfo.signalContentDescription = qsIcon.contentDescription; mInfo.dataTypeIconId = qsType; mInfo.dataContentDescription = typeContentDescription; @@ -211,7 +208,6 @@ public class CellularTile extends QSTileImpl<SignalState> { mInfo.noSim = show; if (mInfo.noSim) { // Make sure signal gets cleared out when no sims. - mInfo.mobileSignalIconId = 0; mInfo.dataTypeIconId = 0; // Show a No SIMs description to avoid emergency calls message. mInfo.enabled = true; 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 9cd79f84cb89..7224ae6a1e15 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 @@ public class DataUsageDetailView extends LinearLayout { 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 3c2e8973cd6e..ecbc4f7683b8 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.R; 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 @@ public class DndTile extends QSTileImpl<BooleanState> { @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 @@ public class DndTile extends QSTileImpl<BooleanState> { 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 @@ public class DndTile extends QSTileImpl<BooleanState> { @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 @@ public class DndTile extends QSTileImpl<BooleanState> { 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 @@ public class DndTile extends QSTileImpl<BooleanState> { 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 @@ public class DndTile extends QSTileImpl<BooleanState> { 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 @@ public class DndTile extends QSTileImpl<BooleanState> { 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 class DndTile extends QSTileImpl<BooleanState> { 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 @@ public class DndTile extends QSTileImpl<BooleanState> { @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); + } + 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 zmp; + return ""; } @Override @@ -313,6 +383,7 @@ public class DndTile extends QSTileImpl<BooleanState> { @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 b11b15a73093..6522e10e4dfa 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.provider.Settings; 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.plugins.qs.QSTile.BooleanState; 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 @@ public class LocationTile extends QSTileImpl<BooleanState> { } } - 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 c485a9ecbf6a..1e9a618c3324 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 @@ public class UserDetailItemView extends LinearLayout { @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 7d2d210727ba..5a23d3bf3207 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.internal.logging.nano.MetricsProto.MetricsEvent; 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 @@ public class WifiTile extends QSTileImpl<SignalState> { } @Override - protected DetailAdapter createDetailAdapter() { return new WifiDetailAdapter(); } + protected DetailAdapter createDetailAdapter() { + return new WifiDetailAdapter(); + } @Override public QSIconView createTileView(Context context) { @@ -125,10 +128,6 @@ public class WifiTile extends QSTileImpl<SignalState> { return; } showDetail(true); - if (!mState.value) { - mController.setWifiEnabled(true); - mState.value = true; - } } @Override @@ -234,15 +233,15 @@ public class WifiTile extends QSTileImpl<SignalState> { @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 @@ public class WifiTile extends QSTileImpl<SignalState> { 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 @@ public class WifiTile extends QSTileImpl<SignalState> { 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 @@ public class WifiTile extends QSTileImpl<SignalState> { 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 @@ public class WifiTile extends QSTileImpl<SignalState> { 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 f0a9bc3f80be..143d934dd002 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 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD // 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/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index 397b78dbd281..ccebd7ceec32 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -82,7 +82,6 @@ import com.android.internal.os.BackgroundThread; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.R; import com.android.systemui.pip.tv.PipMenuActivity; -import com.android.systemui.pip.tv.PipOnboardingActivity; import com.android.systemui.recents.Recents; import com.android.systemui.recents.RecentsDebugFlags; import com.android.systemui.recents.RecentsImpl; @@ -113,7 +112,6 @@ public class SystemServicesProxy { final static List<String> sRecentsBlacklist; static { sRecentsBlacklist = new ArrayList<>(); - sRecentsBlacklist.add(PipOnboardingActivity.class.getName()); sRecentsBlacklist.add(PipMenuActivity.class.getName()); } 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 b8be5800764a..e34987b1d47a 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 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks @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 311f8ffe258f..ae922fcc218e 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 @@ public class TaskViewHeader extends FrameLayout 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/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java index 7d847a3ea111..6918a6309ae1 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 @@ public class BrightnessDialog extends Activity { 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 afe89ec2a9ac..5b234e9c5576 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 @@ public class ToggleSliderView extends RelativeLayout implements ToggleSlider { 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 c48ecdbe838a..da56e62f3c6e 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 @@ public class DividerView extends FrameLayout implements OnTouchListener, @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 d4997ead8292..469f3ad45c56 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 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView @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 9176f57c35cc..677642e53d6e 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 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mIsColorized = mStatusBarNotification.getNotification().isColorized(); mShowingPublicInitialized = false; updateNotificationColor(); + if (mMenuRow != null) { + mMenuRow.onNotificationUpdated(); + } if (mIsSummaryWithChildren) { mChildrenContainer.recreateNotificationHeader(mExpandClickListener); mChildrenContainer.onNotificationUpdated(); @@ -760,7 +763,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } 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 @@ public class ExpandableNotificationRow extends ActivatableNotificationView 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 507b66524c0b..5377deef337e 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 @@ public class KeyboardShortcutAppItemLayout extends RelativeLayout { @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 b4b1cd3409f6..7928575df4d4 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 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G 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 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G 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 bb82b602afbb..fee24b7b7645 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 com.android.systemui.statusbar.stack.NotificationStackScrollLayout; 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 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl 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 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl 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 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl @Override public MenuItem getLongpressMenuItem(Context context) { - return mMenuItems.get(NOTIFICATION_INFO_INDEX); + return mInfoItem; } @Override @@ -120,14 +126,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl @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 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl 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; @@ -273,6 +306,10 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl } private void snapBack(View animView, float velocity) { + if (mFadeAnimator != null) { + mFadeAnimator.cancel(); + } + mHandler.removeCallbacks(mCheckForDrag); mMenuSnappedTo = false; mSnapping = true; mSwipeHelper.snap(animView, 0 /* leftTarget */, velocity); @@ -495,24 +532,24 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl // 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 51345c20abe1..b134fc542776 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 @@ public class NotificationShelf extends ActivatableNotificationView implements @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 0de3e0244fa4..4a3f112f0406 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 @@ public class NotificationSnooze extends LinearLayout 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 @@ public class NotificationSnooze extends LinearLayout } 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 c5e1438c272e..dc254f9fdc1e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -42,6 +42,7 @@ import android.widget.LinearLayout; import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.statusbar.phone.SignalDrawable; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.policy.DarkIconDispatcher; import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver; @@ -177,22 +178,22 @@ public class SignalClusterView extends LinearLayout implements NetworkController 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); - mWifiActivityIn = (ImageView) findViewById(R.id.wifi_in); - mWifiActivityOut= (ImageView) findViewById(R.id.wifi_out); - 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(); } @@ -327,15 +328,6 @@ public class SignalClusterView extends LinearLayout implements NetworkController if (hasCorrectSubs(subs)) { return; } - // Clear out all old subIds. - for (PhoneState state : mPhoneStates) { - if (state.mMobile != null) { - state.maybeStopAnimatableDrawable(state.mMobile); - } - if (state.mMobileDark != null) { - state.maybeStopAnimatableDrawable(state.mMobileDark); - } - } mPhoneStates.clear(); if (mMobileSignalGroup != null) { mMobileSignalGroup.removeAllViews(); @@ -428,16 +420,6 @@ public class SignalClusterView extends LinearLayout implements NetworkController } for (PhoneState state : mPhoneStates) { - if (state.mMobile != null) { - state.maybeStopAnimatableDrawable(state.mMobile); - state.mMobile.setImageDrawable(null); - state.mLastMobileStrengthId = -1; - } - if (state.mMobileDark != null) { - state.maybeStopAnimatableDrawable(state.mMobileDark); - state.mMobileDark.setImageDrawable(null); - state.mLastMobileStrengthId = -1; - } if (state.mMobileType != null) { state.mMobileType.setImageDrawable(null); state.mLastMobileTypeId = -1; @@ -654,7 +636,6 @@ public class SignalClusterView extends LinearLayout implements NetworkController private int mMobileStrengthId = 0, mMobileTypeId = 0; private int mLastMobileStrengthId = -1; private int mLastMobileTypeId = -1; - private int mLastMobileActivityId = -1; private boolean mIsMobileTypeIconWide; private String mMobileDescription, mMobileTypeDescription; @@ -681,13 +662,18 @@ public class SignalClusterView extends LinearLayout implements NetworkController mMobileRoaming = root.findViewById(R.id.mobile_roaming); mMobileActivityIn = root.findViewById(R.id.mobile_in); mMobileActivityOut = root.findViewById(R.id.mobile_out); + // TODO: Remove the 2 instances because now the drawable can handle darkness. + mMobile.setImageDrawable(new SignalDrawable(mMobile.getContext())); + SignalDrawable drawable = new SignalDrawable(mMobileDark.getContext()); + drawable.setDarkIntensity(1); + mMobileDark.setImageDrawable(drawable); } public boolean apply(boolean isSecondaryIcon) { if (mMobileVisible && !mIsAirplaneMode) { if (mLastMobileStrengthId != mMobileStrengthId) { - updateAnimatableIcon(mMobile, mMobileStrengthId); - updateAnimatableIcon(mMobileDark, mMobileStrengthId); + mMobile.getDrawable().setLevel(mMobileStrengthId); + mMobileDark.getDrawable().setLevel(mMobileStrengthId); mLastMobileStrengthId = mMobileStrengthId; } @@ -724,49 +710,6 @@ public class SignalClusterView extends LinearLayout implements NetworkController return mMobileVisible; } - private void updateAnimatableIcon(ImageView view, int resId) { - maybeStopAnimatableDrawable(view); - setIconForView(view, resId); - maybeStartAnimatableDrawable(view); - } - - private void maybeStopAnimatableDrawable(ImageView view) { - Drawable drawable = view.getDrawable(); - - // Check if the icon has been scaled. If it has retrieve the actual drawable out of the - // wrapper. - if (drawable instanceof ScalingDrawableWrapper) { - drawable = ((ScalingDrawableWrapper) drawable).getDrawable(); - } - - if (drawable instanceof Animatable) { - Animatable ad = (Animatable) drawable; - if (ad.isRunning()) { - ad.stop(); - } - } - } - - private void maybeStartAnimatableDrawable(ImageView view) { - Drawable drawable = view.getDrawable(); - - // Check if the icon has been scaled. If it has retrieve the actual drawable out of the - // wrapper. - if (drawable instanceof ScalingDrawableWrapper) { - drawable = ((ScalingDrawableWrapper) drawable).getDrawable(); - } - - if (drawable instanceof Animatable) { - Animatable ad = (Animatable) drawable; - if (ad instanceof AnimatedVectorDrawable) { - ((AnimatedVectorDrawable) ad).forceAnimationOnUI(); - } - if (!ad.isRunning()) { - ad.start(); - } - } - } - public void populateAccessibilityEvent(AccessibilityEvent event) { if (mMobileVisible && mMobileGroup != null && mMobileGroup.getContentDescription() != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 92bfae9e3f5c..ec15d10ac351 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -499,12 +499,18 @@ public class StatusBarIconView extends AnimatedImageView { } private void setColorInternal(int color) { - if (color != NO_COLOR) { - setImageTintList(ColorStateList.valueOf(color)); + mCurrentSetColor = color; + updateIconColor(); + } + + private void updateIconColor() { + if (mCurrentSetColor != NO_COLOR) { + setImageTintList(ColorStateList.valueOf(NotificationUtils.interpolateColors( + mCurrentSetColor, Color.WHITE, mDarkAmount))); } else { setImageTintList(null); + mDozer.updateGrayscale(this, mDarkAmount); } - mCurrentSetColor = color; } public void setIconColor(int iconColor, boolean animate) { @@ -669,10 +675,10 @@ public class StatusBarIconView extends AnimatedImageView { } public void setDark(boolean dark, boolean fade, long delay) { - mDozer.setImageDark(this, dark, fade, delay, mIconColor == NO_COLOR); mDozer.setIntensityDark(f -> { mDarkAmount = f; updateDecorColor(); + updateIconColor(); }, dark, fade, delay); } 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 d530759c7d3d..6cbbd6cd1f18 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 @@ class CarNavigationBarView extends NavigationBarView { @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 f46fc6769b17..2de358f1c292 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 @@ public class CarNavigationButton extends RelativeLayout { @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/car/ConnectedDeviceSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java index 67f8426586ea..677fa81a12cd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java @@ -11,6 +11,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.telephony.SignalStrength; import android.util.Log; import android.util.TypedValue; import android.view.View; @@ -18,6 +19,7 @@ import android.widget.ImageView; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.statusbar.ScalingDrawableWrapper; +import com.android.systemui.statusbar.phone.SignalDrawable; import com.android.systemui.statusbar.policy.BluetoothController; import static com.android.systemui.statusbar.phone.StatusBar.DEBUG; @@ -47,12 +49,12 @@ public class ConnectedDeviceSignalController extends BroadcastReceiver implement * Note that the icon is the same for 0 and 1. */ private static final int[] SIGNAL_STRENGTH_ICONS = { - R.drawable.stat_sys_signal_0_fully, - R.drawable.stat_sys_signal_0_fully, - R.drawable.stat_sys_signal_1_fully, - R.drawable.stat_sys_signal_2_fully, - R.drawable.stat_sys_signal_3_fully, - R.drawable.stat_sys_signal_4_fully, + 0, + 0, + 1, + 2, + 3, + 4, }; private static final int INVALID_SIGNAL = -1; @@ -65,6 +67,7 @@ public class ConnectedDeviceSignalController extends BroadcastReceiver implement private final ImageView mNetworkSignalView; private final float mIconScaleFactor; + private final SignalDrawable mSignalDrawable; private BluetoothHeadsetClient mBluetoothHeadsetClient; @@ -79,6 +82,9 @@ public class ConnectedDeviceSignalController extends BroadcastReceiver implement TypedValue typedValue = new TypedValue(); context.getResources().getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true); mIconScaleFactor = typedValue.getFloat(); + mSignalDrawable = new SignalDrawable(mNetworkSignalView.getContext()); + mNetworkSignalView.setImageDrawable( + new ScalingDrawableWrapper(mSignalDrawable, mIconScaleFactor)); if (mAdapter == null) { return; @@ -187,14 +193,12 @@ public class ConnectedDeviceSignalController extends BroadcastReceiver implement } } - private void setNetworkSignalIcon(int iconId) { + private void setNetworkSignalIcon(int level) { // Setting the icon on a child view of mSignalView, so toggle this container visible. mSignalsView.setVisibility(View.VISIBLE); - // Using mNetworkSignalView's context to get the Drawable in order to preserve the theme. - Drawable icon = mNetworkSignalView.getContext().getDrawable(iconId); - - mNetworkSignalView.setImageDrawable(new ScalingDrawableWrapper(icon, mIconScaleFactor)); + mSignalDrawable.setLevel(SignalDrawable.getState(level, + SignalStrength.NUM_SIGNAL_STRENGTH_BINS, false)); mNetworkSignalView.setVisibility(View.VISIBLE); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java index d592c5f5b7f3..0b3b3cb671e5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java @@ -35,8 +35,7 @@ public class NotificationDozeHelper { startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { - updateGrayscaleMatrix((float) animation.getAnimatedValue()); - target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix)); + updateGrayscale(target, (float) animation.getAnimatedValue()); } }, dark, delay, new AnimatorListenerAdapter() { @Override @@ -49,8 +48,12 @@ public class NotificationDozeHelper { } public void updateGrayscale(ImageView target, boolean dark) { - if (dark) { - updateGrayscaleMatrix(1f); + updateGrayscale(target, dark ? 1 : 0); + } + + public void updateGrayscale(ImageView target, float darkAmount) { + if (darkAmount > 0) { + updateGrayscaleMatrix(darkAmount); target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix)); } else { target.setColorFilter(null); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java index be162667751b..dd997493bb09 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java @@ -23,6 +23,7 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.ViewStub; import android.widget.LinearLayout; import com.android.systemui.Dependency; @@ -36,6 +37,7 @@ import com.android.systemui.statusbar.policy.DarkIconDispatcher; import com.android.systemui.statusbar.policy.EncryptionHelper; import com.android.systemui.statusbar.policy.KeyguardMonitor; import com.android.systemui.statusbar.policy.NetworkController; +import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; /** * Contains the collapsed status bar and handles hiding/showing based on disable flags @@ -56,6 +58,13 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue private DarkIconManager mDarkIconManager; private SignalClusterView mSignalClusterView; + private SignalCallback mSignalCallback = new SignalCallback() { + @Override + public void setIsAirplaneMode(NetworkController.IconState icon) { + mStatusBarComponent.recomputeDisableFlags(true /* animate */); + } + }; + @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -84,6 +93,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mSignalClusterView); // Default to showing until we know otherwise. showSystemIconArea(false); + initEmergencyCryptkeeperText(); } @Override @@ -109,6 +119,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue super.onDestroyView(); Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mSignalClusterView); Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager); + if (mNetworkController.hasEmergencyCryptKeeperText()) { + mNetworkController.removeCallback(mSignalCallback); + } } public void initNotificationIconArea(NotificationIconAreaController @@ -233,4 +246,17 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue .start(); } } + + private void initEmergencyCryptkeeperText() { + View emergencyViewStub = mStatusBar.findViewById(R.id.emergency_cryptkeeper_text); + if (mNetworkController.hasEmergencyCryptKeeperText()) { + if (emergencyViewStub != null) { + ((ViewStub) emergencyViewStub).inflate(); + } + mNetworkController.addCallback(mSignalCallback); + } else if (emergencyViewStub != null) { + ViewGroup parent = (ViewGroup) emergencyViewStub.getParent(); + parent.removeView(emergencyViewStub); + } + } } 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 a44493488cf6..c4996193dd2a 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 @@ public class DemoStatusIcons extends LinearLayout implements DemoMode { } 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 c3f8d9711b9c..40776ea92db7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java @@ -158,6 +158,10 @@ public class DozeParameters { return sPickupSubtypePerformsProxMatcher.isIn(subType); } + public int getPulseVisibleDurationExtended() { + return 2 * getPulseVisibleDuration(); + } + /** * Parses a spec of the form `1,2,3,!5,*`. The resulting object will match numbers that are diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java index b78f7482b9f3..c5f23c5e066a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java @@ -30,6 +30,7 @@ import com.android.keyguard.KeyguardStatusView; import com.android.systemui.Interpolators; import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; +import com.android.systemui.doze.DozeTriggers; /** * Controller which handles all the doze animations of the scrims. @@ -43,8 +44,6 @@ public class DozeScrimController { private final ScrimController mScrimController; private final Context mContext; - private final View mStackScroller; - private final NotificationPanelView mNotificationPanelView; private boolean mDozing; private DozeHost.PulseCallback mPulseCallback; @@ -53,24 +52,22 @@ public class DozeScrimController { private Animator mBehindAnimator; private float mInFrontTarget; private float mBehindTarget; + private boolean mDozingAborted; - public DozeScrimController(ScrimController scrimController, Context context, - View stackScroller, NotificationPanelView notificationPanelView) { + public DozeScrimController(ScrimController scrimController, Context context) { mContext = context; - mStackScroller = stackScroller; mScrimController = scrimController; mDozeParameters = new DozeParameters(context); - mNotificationPanelView = notificationPanelView; } public void setDozing(boolean dozing, boolean animate) { if (mDozing == dozing) return; mDozing = dozing; if (mDozing) { + mDozingAborted = false; abortAnimations(); mScrimController.setDozeBehindAlpha(1f); mScrimController.setDozeInFrontAlpha(mDozeParameters.getAlwaysOn() ? 0f : 1f); - mNotificationPanelView.setDark(true); } else { cancelPulsing(); if (animate) { @@ -85,8 +82,6 @@ public class DozeScrimController { mScrimController.setDozeBehindAlpha(0f); mScrimController.setDozeInFrontAlpha(0f); } - // TODO: animate - mNotificationPanelView.setDark(false); } } @@ -116,10 +111,19 @@ public class DozeScrimController { cancelPulsing(); if (mDozing) { mScrimController.setDozeBehindAlpha(1f); - mScrimController.setDozeInFrontAlpha(1f); + mScrimController.setDozeInFrontAlpha( + mDozeParameters.getAlwaysOn() && !mDozingAborted ? 0f : 1f); } } + /** + * Aborts dozing immediately. + */ + public void abortDoze() { + mDozingAborted = true; + abortPulsing(); + } + public void onScreenTurnedOn() { if (isPulsing()) { final boolean pickupOrDoubleTap = mPulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP @@ -139,12 +143,17 @@ public class DozeScrimController { return mDozing; } + public void extendPulse() { + mHandler.removeCallbacks(mPulseOut); + } + private void cancelPulsing() { if (DEBUG) Log.d(TAG, "Cancel pulsing"); if (mPulseCallback != null) { mHandler.removeCallbacks(mPulseIn); mHandler.removeCallbacks(mPulseOut); + mHandler.removeCallbacks(mPulseOutExtended); pulseFinished(); } } @@ -271,12 +280,23 @@ public class DozeScrimController { if (DEBUG) Log.d(TAG, "Pulse in finished, mDozing=" + mDozing); if (!mDozing) return; mHandler.postDelayed(mPulseOut, mDozeParameters.getPulseVisibleDuration()); + mHandler.postDelayed(mPulseOutExtended, + mDozeParameters.getPulseVisibleDurationExtended()); + } + }; + + private final Runnable mPulseOutExtended = new Runnable() { + @Override + public void run() { + mHandler.removeCallbacks(mPulseOut); + mPulseOut.run(); } }; private final Runnable mPulseOut = new Runnable() { @Override public void run() { + mHandler.removeCallbacks(mPulseOutExtended); if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing); if (!mDozing) return; startScrimAnimation(true /* inFront */, mDozeParameters.getAlwaysOn() ? 0 : 1, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java index 2bb3cbc31ceb..92069142a61f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java @@ -221,7 +221,7 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback { case MODE_WAKE_AND_UNLOCK: Trace.beginSection("MODE_WAKE_AND_UNLOCK"); mStatusBarWindowManager.setStatusBarFocusable(false); - mDozeScrimController.abortPulsing(); + mDozeScrimController.abortDoze(); mKeyguardViewMediator.onWakeAndUnlocking(); mScrimController.setWakeAndUnlocking(); if (mStatusBar.getNavigationBarView() != null) { 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 9a49d67d70d6..41a60e24e700 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 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL 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 1f03024fb781..fa404b599601 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.WindowManager.LayoutParams; 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.recents.Recents; 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 @@ public class NavigationBarFragment extends Fragment implements Callbacks { 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 class NavigationBarFragment extends Fragment implements Callbacks { 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 @@ public class NavigationBarFragment extends Fragment implements Callbacks { 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 @@ public class NavigationBarFragment extends Fragment implements Callbacks { 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 307a8c7b16dc..f1b449891529 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 @@ public class NotificationPanelView extends PanelView implements @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 @@ public class NotificationPanelView extends PanelView implements 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 53ec8c5048ad..5910557b539b 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; 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 @@ import com.android.systemui.util.NotificationChannels; * 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 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, 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 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, 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 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, 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 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, 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 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, 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 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, 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 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, 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 4dc593b856e6..916b603f54fa 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 @@ public class PhoneStatusBarView extends PanelBar { @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/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index dadb749af2d0..67d5b6a2959e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -57,6 +57,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, private static final int TAG_KEY_ANIM_TARGET = R.id.scrim_target; private static final int TAG_START_ALPHA = R.id.scrim_alpha_start; private static final int TAG_END_ALPHA = R.id.scrim_alpha_end; + private static final float NOT_INITIALIZED = -1; private final LightBarController mLightBarController; protected final ScrimView mScrimBehind; @@ -87,9 +88,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, private boolean mDozing; private float mDozeInFrontAlpha; private float mDozeBehindAlpha; - private float mCurrentInFrontAlpha; - private float mCurrentBehindAlpha; - private float mCurrentHeadsUpAlpha = 1; + private float mCurrentInFrontAlpha = NOT_INITIALIZED; + private float mCurrentBehindAlpha = NOT_INITIALIZED; + private float mCurrentHeadsUpAlpha = NOT_INITIALIZED; private int mPinnedHeadsUpCount; private float mTopHeadsUpDragAmount; private View mDraggedHeadsUpView; @@ -111,6 +112,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, mScrimBehindAlpha = context.getResources().getFloat(R.dimen.scrim_behind_alpha); updateHeadsUpScrim(false); + updateScrims(); } public void setKeyguardShowing(boolean showing) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java new file mode 100644 index 000000000000..a9eb20ba3a57 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package com.android.systemui.statusbar.phone; + +import android.animation.ArgbEvaluator; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.Paint.Style; +import android.graphics.Path; +import android.graphics.Path.Direction; +import android.graphics.Path.FillType; +import android.graphics.Path.Op; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.util.Log; + +import com.android.settingslib.R; +import com.android.settingslib.Utils; + +public class SignalDrawable extends Drawable { + + private static final String TAG = "SignalDrawable"; + + private static final int NUM_DOTS = 3; + + private static final float VIEWPORT = 24f; + private static final float PAD = 2f / VIEWPORT; + private static final float CUT_OUT = 7.9f / VIEWPORT; + + private static final float DOT_SIZE = 3f / VIEWPORT; + private static final float DOT_PADDING = 1f / VIEWPORT; + private static final float DOT_CUT_WIDTH = (DOT_SIZE * 3) + (DOT_PADDING * 5); + private static final float DOT_CUT_HEIGHT = (DOT_SIZE * 1) + (DOT_PADDING * 1); + + private static final float[] FIT = {2.26f, -3.02f, 1.76f}; + + // All of these are masks to push all of the drawable state into one int for easy callbacks + // and flow through sysui. + private static final int LEVEL_MASK = 0xff; + private static final int NUM_LEVEL_SHIFT = 8; + private static final int NUM_LEVEL_MASK = 0xff << NUM_LEVEL_SHIFT; + private static final int STATE_SHIFT = 16; + private static final int STATE_MASK = 0xff << STATE_SHIFT; + private static final int STATE_NONE = 0; + private static final int STATE_EMPTY = 1; + private static final int STATE_CUT = 2; + private static final int STATE_CARRIER_CHANGE = 3; + + private static final long DOT_DELAY = 1000; + + private static float[][] X_PATH = new float[][]{ + {21.9f / VIEWPORT, 17.0f / VIEWPORT}, + {-1.1f / VIEWPORT, -1.1f / VIEWPORT}, + {-1.9f / VIEWPORT, 1.9f / VIEWPORT}, + {-1.9f / VIEWPORT, -1.9f / VIEWPORT}, + {-1.1f / VIEWPORT, 1.1f / VIEWPORT}, + {1.9f / VIEWPORT, 1.9f / VIEWPORT}, + {-1.9f / VIEWPORT, 1.9f / VIEWPORT}, + {1.1f / VIEWPORT, 1.1f / VIEWPORT}, + {1.9f / VIEWPORT, -1.9f / VIEWPORT}, + {1.9f / VIEWPORT, 1.9f / VIEWPORT}, + {1.1f / VIEWPORT, -1.1f / VIEWPORT}, + {-1.9f / VIEWPORT, -1.9f / VIEWPORT}, + }; + + private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint mForegroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final int mDarkModeBackgroundColor; + private final int mDarkModeFillColor; + private final int mLightModeBackgroundColor; + private final int mLightModeFillColor; + private final Path mFullPath = new Path(); + private final Path mForegroundPath = new Path(); + private final Path mXPath = new Path(); + private final int mIntrinsicSize; + private final Handler mHandler; + private float mOldDarkIntensity = -1; + private float mNumLevels = 1; + private int mLevel; + private int mState; + private boolean mVisible; + private boolean mAnimating; + private int mCurrentDot; + + public SignalDrawable(Context context) { + mDarkModeBackgroundColor = + Utils.getDefaultColor(context, R.color.dark_mode_icon_color_dual_tone_background); + mDarkModeFillColor = + Utils.getDefaultColor(context, R.color.dark_mode_icon_color_dual_tone_fill); + mLightModeBackgroundColor = + Utils.getDefaultColor(context, R.color.light_mode_icon_color_dual_tone_background); + mLightModeFillColor = + Utils.getDefaultColor(context, R.color.light_mode_icon_color_dual_tone_fill); + mIntrinsicSize = context.getResources().getDimensionPixelSize(R.dimen.signal_icon_size); + mHandler = new Handler(); + setDarkIntensity(0); + } + + @Override + public int getIntrinsicWidth() { + return mIntrinsicSize; + } + + @Override + public int getIntrinsicHeight() { + return mIntrinsicSize; + } + + public void setNumLevels(int levels) { + if (levels == mNumLevels) return; + mNumLevels = levels; + invalidateSelf(); + } + + private void setSignalState(int state) { + if (state == mState) return; + mState = state; + updateAnimation(); + invalidateSelf(); + } + + private void updateAnimation() { + boolean shouldAnimate = (mState == STATE_CARRIER_CHANGE) && mVisible; + if (shouldAnimate == mAnimating) return; + mAnimating = shouldAnimate; + if (shouldAnimate) { + mChangeDot.run(); + } else { + mHandler.removeCallbacks(mChangeDot); + } + } + + @Override + protected boolean onLevelChange(int state) { + setNumLevels(getNumLevels(state)); + setSignalState(getState(state)); + int level = getLevel(state); + if (level != mLevel) { + mLevel = level; + invalidateSelf(); + } + return true; + } + + public void setDarkIntensity(float darkIntensity) { + if (darkIntensity == mOldDarkIntensity) { + return; + } + mPaint.setColor(getBackgroundColor(darkIntensity)); + mForegroundPaint.setColor(getFillColor(darkIntensity)); + mOldDarkIntensity = darkIntensity; + invalidateSelf(); + } + + private int getFillColor(float darkIntensity) { + return getColorForDarkIntensity( + darkIntensity, mLightModeFillColor, mDarkModeFillColor); + } + + private int getBackgroundColor(float darkIntensity) { + return getColorForDarkIntensity( + darkIntensity, mLightModeBackgroundColor, mDarkModeBackgroundColor); + } + + private int getColorForDarkIntensity(float darkIntensity, int lightColor, int darkColor) { + return (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor); + } + + @Override + protected void onBoundsChange(Rect bounds) { + super.onBoundsChange(bounds); + invalidateSelf(); + } + + @Override + public void draw(@NonNull Canvas canvas) { + mFullPath.reset(); + mFullPath.setFillType(FillType.WINDING); + float width = getBounds().width(); + float height = getBounds().height(); + float padding = (PAD * width); + mFullPath.moveTo(width - padding, height - padding); + mFullPath.lineTo(width - padding, padding); + mFullPath.lineTo(padding, height - padding); + mFullPath.lineTo(width - padding, height - padding); + + if (mState == STATE_CARRIER_CHANGE) { + float cutWidth = (DOT_CUT_WIDTH * width); + float cutHeight = (DOT_CUT_HEIGHT * width); + float dotSize = (DOT_SIZE * height); + float dotPadding = (DOT_PADDING * height); + + mFullPath.moveTo(width - padding, height - padding); + mFullPath.rLineTo(-cutWidth, 0); + mFullPath.rLineTo(0, -cutHeight); + mFullPath.rLineTo(cutWidth, 0); + mFullPath.rLineTo(0, cutHeight); + float dotSpacing = dotPadding * 2 + dotSize; + float x = width - padding - dotSize; + float y = height - padding - dotSize; + mForegroundPath.reset(); + drawDot(mFullPath, mForegroundPath, x, y, dotSize, 2); + drawDot(mFullPath, mForegroundPath, x - dotSpacing, y, dotSize, 1); + drawDot(mFullPath, mForegroundPath, x - dotSpacing * 2, y, dotSize, 0); + } else if (mState == STATE_CUT) { + float cut = (CUT_OUT * width); + mFullPath.moveTo(width - padding, height - padding); + mFullPath.rLineTo(-cut, 0); + mFullPath.rLineTo(0, -cut); + mFullPath.rLineTo(cut, 0); + mFullPath.rLineTo(0, cut); + } + + mPaint.setStyle(mState == STATE_EMPTY ? Style.STROKE : Style.FILL); + mForegroundPaint.setStyle(mState == STATE_EMPTY ? Style.STROKE : Style.FILL); + + if (mState != STATE_CARRIER_CHANGE) { + mForegroundPath.reset(); + int sigWidth = Math.round(calcFit(mLevel / (mNumLevels - 1)) * (width - 2 * padding)); + mForegroundPath.addRect(padding, padding, padding + sigWidth, height - padding, + Direction.CW); + mForegroundPath.op(mFullPath, Op.INTERSECT); + } + + canvas.drawPath(mFullPath, mPaint); + canvas.drawPath(mForegroundPath, mForegroundPaint); + if (mState == STATE_CUT) { + mXPath.reset(); + mXPath.moveTo(X_PATH[0][0] * width, X_PATH[0][1] * height); + for (int i = 1; i < X_PATH.length; i++) { + mXPath.rLineTo(X_PATH[i][0] * width, X_PATH[i][1] * height); + } + canvas.drawPath(mXPath, mForegroundPaint); + } + } + + private void drawDot(Path fullPath, Path foregroundPath, float x, float y, float dotSize, + int i) { + Path p = (i == mCurrentDot) ? foregroundPath : fullPath; + p.addRect(x, y, x + dotSize, y + dotSize, Direction.CW); + } + + // This is a fit line based on previous values of provided in assets, but if + // you look at the a plot of this actual fit, it makes a lot of sense, what it does + // is compress the areas that are very visually easy to see changes (the middle sections) + // and spread out the sections that are hard to see (each end of the icon). + // The current fit is cubic, but pretty easy to change the way the code is written (just add + // terms to the end of FIT). + private float calcFit(float v) { + float ret = 0; + float t = v; + for (int i = 0; i < FIT.length; i++) { + ret += FIT[i] * t; + t *= v; + } + return ret; + } + + @Override + public int getAlpha() { + return mPaint.getAlpha(); + } + + @Override + public void setAlpha(@IntRange(from = 0, to = 255) int alpha) { + mPaint.setAlpha(alpha); + mForegroundPaint.setAlpha(alpha); + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + mPaint.setColorFilter(colorFilter); + mForegroundPaint.setColorFilter(colorFilter); + } + + @Override + public int getOpacity() { + return 255; + } + + @Override + public boolean setVisible(boolean visible, boolean restart) { + mVisible = visible; + updateAnimation(); + return super.setVisible(visible, restart); + } + + private final Runnable mChangeDot = new Runnable() { + @Override + public void run() { + if (++mCurrentDot == NUM_DOTS) { + mCurrentDot = 0; + } + invalidateSelf(); + mHandler.postDelayed(mChangeDot, DOT_DELAY); + } + }; + + public static int getLevel(int fullState) { + return fullState & LEVEL_MASK; + } + + public static int getState(int fullState) { + return (fullState & STATE_MASK) >> STATE_SHIFT; + } + + public static int getNumLevels(int fullState) { + return (fullState & NUM_LEVEL_MASK) >> NUM_LEVEL_SHIFT; + } + + public static int getState(int level, int numLevels, boolean cutOut) { + return ((cutOut ? STATE_CUT : 0) << STATE_SHIFT) + | (numLevels << NUM_LEVEL_SHIFT) + | level; + } + + public static int getCarrierChangeState(int numLevels) { + return (STATE_CARRIER_CHANGE << STATE_SHIFT) | (numLevels << NUM_LEVEL_SHIFT); + } + + public static int getEmptyState(int numLevels) { + return (STATE_EMPTY << STATE_SHIFT) | (numLevels << NUM_LEVEL_SHIFT); + } +} 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 9304de52a6be..f0d38b2e3d3c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -1114,14 +1114,11 @@ public class StatusBar extends SystemUI implements DemoMode, } mHeadsUpManager.addListener(mScrimController); mStackScroller.setScrimController(mScrimController); - mDozeScrimController = new DozeScrimController(mScrimController, context, mStackScroller, - mNotificationPanel); + mDozeScrimController = new DozeScrimController(mScrimController, context); // Other icons mVolumeComponent = getComponent(VolumeComponent.class); - initEmergencyCryptkeeperText(); - mKeyguardBottomArea.setStatusBar(this); mKeyguardBottomArea.setUserSetupComplete(mUserSetup); if (UserManager.get(mContext).isUserSwitcherEnabled()) { @@ -1231,24 +1228,6 @@ public class StatusBar extends SystemUI implements DemoMode, }); } - private void initEmergencyCryptkeeperText() { - View emergencyViewStub = mStatusBarWindow.findViewById(R.id.emergency_cryptkeeper_text); - if (mNetworkController.hasEmergencyCryptKeeperText()) { - if (emergencyViewStub != null) { - ((ViewStub) emergencyViewStub).inflate(); - } - mNetworkController.addCallback(new NetworkController.SignalCallback() { - @Override - public void setIsAirplaneMode(NetworkController.IconState icon) { - recomputeDisableFlags(true /* animate */); - } - }); - } else if (emergencyViewStub != null) { - ViewGroup parent = (ViewGroup) emergencyViewStub.getParent(); - parent.removeView(emergencyViewStub); - } - } - /** * Returns the {@link android.view.View.OnTouchListener} that will be invoked when the * background window of the status bar is clicked. @@ -4332,6 +4311,7 @@ public class StatusBar extends SystemUI implements DemoMode, mStackScroller.setDark(mDozing, animate, mWakeUpTouchLocation); mScrimController.setDozing(mDozing); mKeyguardIndicationController.setDozing(mDozing); + mNotificationPanel.setDark(mDozing); // Immediately abort the dozing from the doze scrim controller in case of wake-and-unlock // for pulsing so the Keyguard fade-out animation scrim can take over. @@ -4958,6 +4938,7 @@ public class StatusBar extends SystemUI implements DemoMode, mDozing = mDozingRequested && mState == StatusBarState.KEYGUARD || mFingerprintUnlockController.getMode() == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING; + mStatusBarWindowManager.setDozing(mDozing); updateDozingState(); Trace.endSection(); } @@ -5065,6 +5046,16 @@ public class StatusBar extends SystemUI implements DemoMode, StatusBar.this.startPendingIntentDismissingKeyguard(intent); } + @Override + public void abortPulsing() { + mDozeScrimController.abortPulsing(); + } + + @Override + public void extendPulse() { + mDozeScrimController.extendPulse(); + } + } // Begin Extra BaseStatusBar methods. @@ -6369,17 +6360,10 @@ public class StatusBar extends SystemUI implements DemoMode, .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/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java index deb0070ccbc0..0326e4025a79 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java @@ -118,7 +118,7 @@ public class StatusBarWindowManager implements RemoteInputController.Callback, D mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; } - if (state.keyguardShowing && !state.backdropShowing) { + if (state.keyguardShowing && !state.backdropShowing && !state.dozing) { mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; } else { mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; @@ -357,6 +357,11 @@ public class StatusBarWindowManager implements RemoteInputController.Callback, D apply(mCurrentState); } + public void setDozing(boolean dozing) { + mCurrentState.dozing = dozing; + apply(mCurrentState); + } + public void setBarHeight(int barHeight) { mBarHeight = barHeight; apply(mCurrentState); @@ -404,6 +409,7 @@ public class StatusBarWindowManager implements RemoteInputController.Callback, D boolean remoteInputActive; boolean forcePluginOpen; + boolean dozing; private boolean isKeyguardShowingAndNotOccluded() { return keyguardShowing && !keyguardOccluded; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java index 1848d4ea438b..1a09d75be632 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -255,6 +255,9 @@ public class StatusBarWindowView extends FrameLayout { if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) { mStackScrollLayout.closeControlsIfOutsideTouch(ev); } + if (mService.isDozing()) { + mService.mDozeScrimController.extendPulse(); + } return super.dispatchTouchEvent(ev); } 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 000000000000..dfa5cbdd3e12 --- /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 9a5f1b8cbc63..8e8a285f7d45 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 cc61605a5aa6..3f5f5a0ed5ae 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 @@ import java.util.List; * 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 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio 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 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio // 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 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio 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 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio 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 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio 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 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio 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/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index 91acf0488999..67b5596e34c9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -36,6 +36,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.cdma.EriInfo; import com.android.systemui.R; +import com.android.systemui.statusbar.phone.SignalDrawable; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config; @@ -233,6 +234,29 @@ public class MobileSignalController extends SignalController< mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC); } + private int getNumLevels() { + return SignalStrength.NUM_SIGNAL_STRENGTH_BINS; + } + + @Override + public int getCurrentIconId() { + if (mCurrentState.iconGroup == TelephonyIcons.CARRIER_NETWORK_CHANGE) { + return SignalDrawable.getCarrierChangeState(getNumLevels()); + } else if (mCurrentState.connected) { + return SignalDrawable.getState(mCurrentState.level, getNumLevels(), + mCurrentState.inetCondition == 0); + } else if (mCurrentState.enabled) { + return SignalDrawable.getEmptyState(getNumLevels()); + } else { + return 0; + } + } + + @Override + public int getQsCurrentIconId() { + return getCurrentIconId(); + } + @Override public void notifyListeners(SignalCallback callback) { MobileIconGroup icons = getIcons(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index bc3eec9795f7..c21f444d0bf3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -32,6 +32,7 @@ import android.os.Handler; import android.os.Looper; import android.provider.Settings; import android.telephony.ServiceState; +import android.telephony.SignalStrength; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; @@ -872,11 +873,11 @@ public class NetworkControllerImpl extends BroadcastReceiver if (args.containsKey("roam")) { controller.getState().roaming = "show".equals(args.getString("roam")); } - int[][] icons = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH; String level = args.getString("level"); if (level != null) { controller.getState().level = level.equals("null") ? -1 - : Math.min(Integer.parseInt(level), icons[0].length - 1); + : Math.min(Integer.parseInt(level), + SignalStrength.NUM_SIGNAL_STRENGTH_BINS); controller.getState().connected = controller.getState().level >= 0; } String activity = args.getString("activity"); 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 784f25e25a56..37b0de400c9e 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 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene 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 faa1a28ace8b..9f6157492a38 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 @@ public class SplitClockView extends LinearLayout { @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/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java index 6b2361e64da0..aaa0568a72cd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java @@ -20,196 +20,20 @@ import com.android.systemui.R; import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup; class TelephonyIcons { - //***** Signal strength icons - - static final int TELEPHONY_NUM_LEVELS = 5; - - //GSM/UMTS - static final int TELEPHONY_NO_NETWORK = R.drawable.stat_sys_signal_null; - - static final int[][] TELEPHONY_SIGNAL_STRENGTH = { - { R.drawable.stat_sys_signal_0, - R.drawable.stat_sys_signal_1, - R.drawable.stat_sys_signal_2, - R.drawable.stat_sys_signal_3, - R.drawable.stat_sys_signal_4 }, - { R.drawable.stat_sys_signal_0_fully, - R.drawable.stat_sys_signal_1_fully, - R.drawable.stat_sys_signal_2_fully, - R.drawable.stat_sys_signal_3_fully, - R.drawable.stat_sys_signal_4_fully } - }; - - static final int QS_TELEPHONY_NO_NETWORK = R.drawable.ic_qs_signal_no_signal; - - static final int[][] QS_TELEPHONY_SIGNAL_STRENGTH = { - { R.drawable.ic_qs_signal_0, - R.drawable.ic_qs_signal_1, - R.drawable.ic_qs_signal_2, - R.drawable.ic_qs_signal_3, - R.drawable.ic_qs_signal_4 }, - { R.drawable.ic_qs_signal_full_0, - R.drawable.ic_qs_signal_full_1, - R.drawable.ic_qs_signal_full_2, - R.drawable.ic_qs_signal_full_3, - R.drawable.ic_qs_signal_full_4 } - }; - - static final int[][] TELEPHONY_SIGNAL_STRENGTH_ROAMING = { - { R.drawable.stat_sys_signal_0, - R.drawable.stat_sys_signal_1, - R.drawable.stat_sys_signal_2, - R.drawable.stat_sys_signal_3, - R.drawable.stat_sys_signal_4 }, - { R.drawable.stat_sys_signal_0_fully, - R.drawable.stat_sys_signal_1_fully, - R.drawable.stat_sys_signal_2_fully, - R.drawable.stat_sys_signal_3_fully, - R.drawable.stat_sys_signal_4_fully } - }; - - //CarrierNetworkChange - static final int[][] TELEPHONY_CARRIER_NETWORK_CHANGE = { - { R.drawable.stat_sys_signal_carrier_network_change_animation, - R.drawable.stat_sys_signal_carrier_network_change_animation, - R.drawable.stat_sys_signal_carrier_network_change_animation, - R.drawable.stat_sys_signal_carrier_network_change_animation, - R.drawable.stat_sys_signal_carrier_network_change_animation }, - { R.drawable.stat_sys_signal_carrier_network_change_animation, - R.drawable.stat_sys_signal_carrier_network_change_animation, - R.drawable.stat_sys_signal_carrier_network_change_animation, - R.drawable.stat_sys_signal_carrier_network_change_animation, - R.drawable.stat_sys_signal_carrier_network_change_animation } - }; - - static final int[][] QS_TELEPHONY_CARRIER_NETWORK_CHANGE = { - { R.drawable.ic_qs_signal_carrier_network_change_animation, - R.drawable.ic_qs_signal_carrier_network_change_animation, - R.drawable.ic_qs_signal_carrier_network_change_animation, - R.drawable.ic_qs_signal_carrier_network_change_animation, - R.drawable.ic_qs_signal_carrier_network_change_animation }, - { R.drawable.ic_qs_signal_carrier_network_change_animation, - R.drawable.ic_qs_signal_carrier_network_change_animation, - R.drawable.ic_qs_signal_carrier_network_change_animation, - R.drawable.ic_qs_signal_carrier_network_change_animation, - R.drawable.ic_qs_signal_carrier_network_change_animation } - }; - //***** Data connection icons - //GSM/UMTS - static final int[][] DATA_G = { - { R.drawable.stat_sys_data_fully_connected_g, - R.drawable.stat_sys_data_fully_connected_g, - R.drawable.stat_sys_data_fully_connected_g, - R.drawable.stat_sys_data_fully_connected_g }, - { R.drawable.stat_sys_data_fully_connected_g, - R.drawable.stat_sys_data_fully_connected_g, - R.drawable.stat_sys_data_fully_connected_g, - R.drawable.stat_sys_data_fully_connected_g } - }; - static final int QS_DATA_G = R.drawable.ic_qs_signal_g; - - static final int[][] DATA_3G = { - { R.drawable.stat_sys_data_fully_connected_3g, - R.drawable.stat_sys_data_fully_connected_3g, - R.drawable.stat_sys_data_fully_connected_3g, - R.drawable.stat_sys_data_fully_connected_3g }, - { R.drawable.stat_sys_data_fully_connected_3g, - R.drawable.stat_sys_data_fully_connected_3g, - R.drawable.stat_sys_data_fully_connected_3g, - R.drawable.stat_sys_data_fully_connected_3g } - }; - static final int QS_DATA_3G = R.drawable.ic_qs_signal_3g; - - static final int[][] DATA_E = { - { R.drawable.stat_sys_data_fully_connected_e, - R.drawable.stat_sys_data_fully_connected_e, - R.drawable.stat_sys_data_fully_connected_e, - R.drawable.stat_sys_data_fully_connected_e }, - { R.drawable.stat_sys_data_fully_connected_e, - R.drawable.stat_sys_data_fully_connected_e, - R.drawable.stat_sys_data_fully_connected_e, - R.drawable.stat_sys_data_fully_connected_e } - }; - static final int QS_DATA_E = R.drawable.ic_qs_signal_e; - - //3.5G - static final int[][] DATA_H = { - { R.drawable.stat_sys_data_fully_connected_h, - R.drawable.stat_sys_data_fully_connected_h, - R.drawable.stat_sys_data_fully_connected_h, - R.drawable.stat_sys_data_fully_connected_h }, - { R.drawable.stat_sys_data_fully_connected_h, - R.drawable.stat_sys_data_fully_connected_h, - R.drawable.stat_sys_data_fully_connected_h, - R.drawable.stat_sys_data_fully_connected_h } - }; - static final int QS_DATA_H = R.drawable.ic_qs_signal_h; - - //CDMA - // Use 3G icons for EVDO data and 1x icons for 1XRTT data - static final int[][] DATA_1X = { - { R.drawable.stat_sys_data_fully_connected_1x, - R.drawable.stat_sys_data_fully_connected_1x, - R.drawable.stat_sys_data_fully_connected_1x, - R.drawable.stat_sys_data_fully_connected_1x }, - { R.drawable.stat_sys_data_fully_connected_1x, - R.drawable.stat_sys_data_fully_connected_1x, - R.drawable.stat_sys_data_fully_connected_1x, - R.drawable.stat_sys_data_fully_connected_1x } - }; - static final int QS_DATA_1X = R.drawable.ic_qs_signal_1x; - - // LTE and eHRPD - static final int[][] DATA_4G = { - { R.drawable.stat_sys_data_fully_connected_4g, - R.drawable.stat_sys_data_fully_connected_4g, - R.drawable.stat_sys_data_fully_connected_4g, - R.drawable.stat_sys_data_fully_connected_4g }, - { R.drawable.stat_sys_data_fully_connected_4g, - R.drawable.stat_sys_data_fully_connected_4g, - R.drawable.stat_sys_data_fully_connected_4g, - R.drawable.stat_sys_data_fully_connected_4g } - }; - static final int QS_DATA_4G = R.drawable.ic_qs_signal_4g; - - static final int[][] DATA_4G_PLUS = { - { R.drawable.stat_sys_data_fully_connected_4g_plus, - R.drawable.stat_sys_data_fully_connected_4g_plus, - R.drawable.stat_sys_data_fully_connected_4g_plus, - R.drawable.stat_sys_data_fully_connected_4g_plus }, - { R.drawable.stat_sys_data_fully_connected_4g_plus, - R.drawable.stat_sys_data_fully_connected_4g_plus, - R.drawable.stat_sys_data_fully_connected_4g_plus, - R.drawable.stat_sys_data_fully_connected_4g_plus } - }; - static final int QS_DATA_4G_PLUS = R.drawable.ic_qs_signal_4g_plus; - - // LTE branded "LTE" - static final int[][] DATA_LTE = { - { R.drawable.stat_sys_data_fully_connected_lte, - R.drawable.stat_sys_data_fully_connected_lte, - R.drawable.stat_sys_data_fully_connected_lte, - R.drawable.stat_sys_data_fully_connected_lte }, - { R.drawable.stat_sys_data_fully_connected_lte, - R.drawable.stat_sys_data_fully_connected_lte, - R.drawable.stat_sys_data_fully_connected_lte, - R.drawable.stat_sys_data_fully_connected_lte } - }; - static final int QS_DATA_LTE = R.drawable.ic_qs_signal_lte; static final int QS_DATA_LTE_PLUS = R.drawable.ic_qs_signal_lte_plus; static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode; - static final int ROAMING_ICON = R.drawable.stat_sys_roaming; + static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte; static final int ICON_LTE_PLUS = R.drawable.stat_sys_data_fully_connected_lte_plus; static final int ICON_G = R.drawable.stat_sys_data_fully_connected_g; @@ -219,29 +43,19 @@ class TelephonyIcons { static final int ICON_4G = R.drawable.stat_sys_data_fully_connected_4g; static final int ICON_4G_PLUS = R.drawable.stat_sys_data_fully_connected_4g_plus; static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x; - static final int ICON_CARRIER_NETWORK_CHANGE = - R.drawable.stat_sys_signal_carrier_network_change_animation; static final int ICON_DATA_DISABLED = R.drawable.stat_sys_data_disabled; - static final int QS_ICON_LTE = R.drawable.ic_qs_signal_lte; - static final int QS_ICON_3G = R.drawable.ic_qs_signal_3g; - static final int QS_ICON_4G = R.drawable.ic_qs_signal_4g; - static final int QS_ICON_4G_PLUS = R.drawable.ic_qs_signal_4g_plus; - static final int QS_ICON_1X = R.drawable.ic_qs_signal_1x; - static final int QS_ICON_CARRIER_NETWORK_CHANGE = - R.drawable.ic_qs_signal_carrier_network_change_animation; - static final int QS_ICON_DATA_DISABLED = R.drawable.ic_qs_data_disabled; static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup( "CARRIER_NETWORK_CHANGE", - TelephonyIcons.TELEPHONY_CARRIER_NETWORK_CHANGE, - TelephonyIcons.QS_TELEPHONY_CARRIER_NETWORK_CHANGE, + null, + null, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, 0, 0, - TelephonyIcons.ICON_CARRIER_NETWORK_CHANGE, - TelephonyIcons.QS_ICON_CARRIER_NETWORK_CHANGE, + 0, + 0, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], R.string.accessibility_carrier_network_change_mode, 0, @@ -251,12 +65,12 @@ class TelephonyIcons { static final MobileIconGroup THREE_G = new MobileIconGroup( "3G", - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + null, + null, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, 0, 0, - TelephonyIcons.TELEPHONY_NO_NETWORK, - TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + 0, + 0, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], R.string.accessibility_data_connection_3g, TelephonyIcons.ICON_3G, @@ -266,36 +80,36 @@ class TelephonyIcons { static final MobileIconGroup WFC = new MobileIconGroup( "WFC", - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + null, + null, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, 0, 0, - TelephonyIcons.TELEPHONY_NO_NETWORK, - TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + 0, + 0, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], 0, 0, false, 0 ); static final MobileIconGroup UNKNOWN = new MobileIconGroup( "Unknown", - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + null, + null, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, 0, 0, - TelephonyIcons.TELEPHONY_NO_NETWORK, - TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + 0, + 0, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], 0, 0, false, 0 ); static final MobileIconGroup E = new MobileIconGroup( "E", - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + null, + null, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, 0, 0, - TelephonyIcons.TELEPHONY_NO_NETWORK, - TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + 0, + 0, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], R.string.accessibility_data_connection_edge, TelephonyIcons.ICON_E, @@ -305,12 +119,12 @@ class TelephonyIcons { static final MobileIconGroup ONE_X = new MobileIconGroup( "1X", - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + null, + null, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, 0, 0, - TelephonyIcons.TELEPHONY_NO_NETWORK, - TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + 0, + 0, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], R.string.accessibility_data_connection_cdma, TelephonyIcons.ICON_1X, @@ -320,12 +134,12 @@ class TelephonyIcons { static final MobileIconGroup G = new MobileIconGroup( "G", - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + null, + null, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, 0, 0, - TelephonyIcons.TELEPHONY_NO_NETWORK, - TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + 0, + 0, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], R.string.accessibility_data_connection_gprs, TelephonyIcons.ICON_G, @@ -335,12 +149,12 @@ class TelephonyIcons { static final MobileIconGroup H = new MobileIconGroup( "H", - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + null, + null, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, 0, 0, - TelephonyIcons.TELEPHONY_NO_NETWORK, - TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + 0, + 0, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], R.string.accessibility_data_connection_3_5g, TelephonyIcons.ICON_H, @@ -350,12 +164,12 @@ class TelephonyIcons { static final MobileIconGroup FOUR_G = new MobileIconGroup( "4G", - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + null, + null, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, 0, 0, - TelephonyIcons.TELEPHONY_NO_NETWORK, - TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + 0, + 0, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], R.string.accessibility_data_connection_4g, TelephonyIcons.ICON_4G, @@ -365,12 +179,12 @@ class TelephonyIcons { static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup( "4G+", - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + null, + null, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, 0,0, - TelephonyIcons.TELEPHONY_NO_NETWORK, - TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + 0, + 0, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], R.string.accessibility_data_connection_4g_plus, TelephonyIcons.ICON_4G_PLUS, @@ -380,12 +194,12 @@ class TelephonyIcons { static final MobileIconGroup LTE = new MobileIconGroup( "LTE", - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + null, + null, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, 0, 0, - TelephonyIcons.TELEPHONY_NO_NETWORK, - TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + 0, + 0, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], R.string.accessibility_data_connection_lte, TelephonyIcons.ICON_LTE, @@ -395,12 +209,12 @@ class TelephonyIcons { static final MobileIconGroup LTE_PLUS = new MobileIconGroup( "LTE+", - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + null, + null, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, 0, 0, - TelephonyIcons.TELEPHONY_NO_NETWORK, - TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + 0, + 0, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], R.string.accessibility_data_connection_lte_plus, TelephonyIcons.ICON_LTE_PLUS, @@ -410,12 +224,12 @@ class TelephonyIcons { static final MobileIconGroup DATA_DISABLED = new MobileIconGroup( "DataDisabled", - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH, + null, + null, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, 0, 0, - TelephonyIcons.TELEPHONY_NO_NETWORK, - TelephonyIcons.QS_TELEPHONY_NO_NETWORK, + 0, + 0, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], R.string.accessibility_cell_data_off, TelephonyIcons.ICON_DATA_DISABLED, 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 ba91ffd04c0e..b5db78d128ff 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 @@ public class StackScrollAlgorithm { 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 @@ public class StackScrollAlgorithm { } 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 cfe16ddbe9df..c3a53dedd0cf 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 @@ public class StorageNotification extends SystemUI { .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 4e4832c5f33a..10b6ff5cdfdc 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 @@ public class ZenFooter extends LinearLayout { @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 98e89e46964f..f7dfc0a771db 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; 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.View; 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.MetricsLogger; 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.GregorianCalendar; 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 class ZenModePanel extends LinearLayout { 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 @@ public class ZenModePanel extends LinearLayout { 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 @@ public class ZenModePanel extends LinearLayout { } 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 @@ public class ZenModePanel extends LinearLayout { 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 @@ public class ZenModePanel extends LinearLayout { protected void onAttachedToWindow() { super.onAttachedToWindow(); if (DEBUG) Log.d(mTag, "onAttachedToWindow"); + setExpanded(true); mAttached = true; mAttachedZen = getSelectedZen(-1); mSessionZen = mAttachedZen; @@ -246,6 +308,7 @@ public class ZenModePanel extends LinearLayout { protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (DEBUG) Log.d(mTag, "onDetachedFromWindow"); + setExpanded(false); checkForAttachedZenChange(); mAttached = false; mAttachedZen = -1; @@ -285,7 +348,7 @@ public class ZenModePanel extends LinearLayout { if (expanded == mExpanded) return; if (DEBUG) Log.d(mTag, "setExpanded " + expanded); mExpanded = expanded; - if (mExpanded && isShown()) { + if (mExpanded) { ensureSelection(); } updateWidgets(); @@ -317,10 +380,10 @@ public class ZenModePanel extends LinearLayout { 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 @@ public class ZenModePanel extends LinearLayout { 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 @@ public class ZenModePanel extends LinearLayout { 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 @@ public class ZenModePanel extends LinearLayout { } } // 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 @@ public class ZenModePanel extends LinearLayout { 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 6b47ada8fea7..e1f56a47e641 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 @@ public class BatteryMeterDrawableTest extends SysuiTestCase { @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 @@ public class BatteryMeterDrawableTest extends SysuiTestCase { @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 @@ public class BatteryMeterDrawableTest extends SysuiTestCase { @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 @@ public class BatteryMeterDrawableTest extends SysuiTestCase { 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 @@ public class BatteryMeterDrawableTest extends SysuiTestCase { 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 000000000000..1b5d4a4cb9cd --- /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 2bb7f3b2b36d..66385a1dfb01 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 com.android.systemui.SysuiTestCase; 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 @@ public class NotificationInfoTest extends SysuiTestCase { 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 efb9fea4f895..9249df662daf 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 class NotificationMenuRowTest extends LeakCheckedTest { 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 e7cdcb541ee4..53d842a01ed2 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.SysuiBaseFragmentTest; 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 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest { 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/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index 19b4b173c42d..505e1d8346fd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -31,6 +31,7 @@ import android.telephony.TelephonyManager; import android.util.Log; import com.android.internal.telephony.cdma.EriInfo; import com.android.settingslib.net.DataUsageController; +import com.android.systemui.statusbar.phone.SignalDrawable; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; @@ -66,12 +67,10 @@ import static org.mockito.Mockito.when; public class NetworkControllerBaseTest extends SysuiTestCase { private static final String TAG = "NetworkControllerBaseTest"; protected static final int DEFAULT_LEVEL = 2; - protected static final int DEFAULT_SIGNAL_STRENGTH = - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][DEFAULT_LEVEL]; - protected static final int DEFAULT_QS_SIGNAL_STRENGTH = - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[1][DEFAULT_LEVEL]; + protected static final int DEFAULT_SIGNAL_STRENGTH = DEFAULT_LEVEL; + protected static final int DEFAULT_QS_SIGNAL_STRENGTH = DEFAULT_LEVEL; protected static final int DEFAULT_ICON = TelephonyIcons.ICON_3G; - protected static final int DEFAULT_QS_ICON = TelephonyIcons.QS_ICON_3G; + protected static final int DEFAULT_QS_ICON = TelephonyIcons.QS_DATA_3G; protected NetworkControllerImpl mNetworkController; protected MobileSignalController mMobileSignalController; @@ -315,8 +314,10 @@ public class NetworkControllerBaseTest extends SysuiTestCase { typeIconArg.capture(), dataInArg.capture(), dataOutArg.capture(), anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean()); IconState iconState = iconArg.getValue(); + int state = SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS, + false); assertEquals("Visibility in, quick settings", visible, iconState.visible); - assertEquals("Signal icon in, quick settings", icon, iconState.icon); + assertEquals("Signal icon in, quick settings", state, iconState.icon); assertEquals("Data icon in, quick settings", typeIcon, (int) typeIconArg.getValue()); assertEquals("Data direction in, in quick settings", dataIn, (boolean) dataInArg.getValue()); @@ -330,6 +331,11 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon, boolean roaming) { + verifyLastMobileDataIndicators(visible, icon, typeIcon, roaming, true); + } + + protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon, + boolean roaming, boolean inet) { ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class); ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class); @@ -342,7 +348,9 @@ public class NetworkControllerBaseTest extends SysuiTestCase { anyInt(), eq(roaming)); IconState iconState = iconArg.getValue(); - assertEquals("Signal icon in status bar", icon, iconState.icon); + int state = icon == -1 ? 0 + : SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS, !inet); + assertEquals("Signal icon in status bar", state, iconState.icon); assertEquals("Data icon in status bar", typeIcon, (int) typeIconArg.getValue()); assertEquals("Visibility in status bar", visible, iconState.visible); } @@ -367,13 +375,15 @@ public class NetworkControllerBaseTest extends SysuiTestCase { IconState iconState = iconArg.getValue(); + int state = SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS, + false); assertEquals("Data icon in status bar", typeIcon, (int) typeIconArg.getValue()); - assertEquals("Signal icon in status bar", icon, iconState.icon); + assertEquals("Signal icon in status bar", state, iconState.icon); assertEquals("Visibility in status bar", visible, iconState.visible); iconState = qsIconArg.getValue(); assertEquals("Visibility in quick settings", qsVisible, iconState.visible); - assertEquals("Signal icon in quick settings", qsIcon, iconState.icon); + assertEquals("Signal icon in quick settings", state, iconState.icon); assertEquals("Data icon in quick settings", qsTypeIcon, (int) qsTypeIconArg.getValue()); assertEquals("Data direction in in quick settings", dataIn, (boolean) dataInArg.getValue()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java index e47f75066dce..dfe00f95fe4d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java @@ -24,7 +24,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { public void test3gDataIcon() { setupDefaultSignal(); - verifyDataIndicators(TelephonyIcons.DATA_3G[1][0 /* No direction */], + verifyDataIndicators(TelephonyIcons.ICON_3G, TelephonyIcons.QS_DATA_3G); } @@ -34,7 +34,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { updateDataConnectionState(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_GSM); - verifyDataIndicators(TelephonyIcons.DATA_G[1][0 /* No direction */], + verifyDataIndicators(TelephonyIcons.ICON_G, TelephonyIcons.QS_DATA_G); } @@ -44,7 +44,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { updateDataConnectionState(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_CDMA); - verifyDataIndicators(TelephonyIcons.DATA_1X[1][0 /* No direction */], + verifyDataIndicators(TelephonyIcons.ICON_1X, TelephonyIcons.QS_DATA_1X); } @@ -54,7 +54,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { updateDataConnectionState(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_EDGE); - verifyDataIndicators(TelephonyIcons.DATA_E[1][0 /* No direction */], + verifyDataIndicators(TelephonyIcons.ICON_E, TelephonyIcons.QS_DATA_E); } @@ -64,7 +64,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { updateDataConnectionState(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); - verifyDataIndicators(TelephonyIcons.DATA_LTE[1][0 /* No direction */], + verifyDataIndicators(TelephonyIcons.ICON_LTE, TelephonyIcons.QS_DATA_LTE); } @@ -74,7 +74,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { updateDataConnectionState(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_HSPA); - verifyDataIndicators(TelephonyIcons.DATA_H[1][0 /* No direction */], + verifyDataIndicators(TelephonyIcons.ICON_H, TelephonyIcons.QS_DATA_H); } @@ -103,7 +103,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { updateDataConnectionState(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); - verifyDataIndicators(TelephonyIcons.DATA_4G[1][0 /* No direction */], + verifyDataIndicators(TelephonyIcons.ICON_4G, TelephonyIcons.QS_DATA_4G); } @@ -147,7 +147,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { // the after work. mNetworkController.handleConfigurationChanged(); - verifyDataIndicators(TelephonyIcons.DATA_4G[1][0 /* No direction */], + verifyDataIndicators(TelephonyIcons.ICON_4G, TelephonyIcons.QS_DATA_4G); } @@ -157,13 +157,13 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { updateDataConnectionState(TelephonyManager.DATA_CONNECTED, TelephonyManager.NETWORK_TYPE_LTE); - verifyDataIndicators(TelephonyIcons.DATA_LTE[1][0 /* No direction */], + verifyDataIndicators(TelephonyIcons.ICON_LTE, TelephonyIcons.QS_DATA_LTE); when(mServiceState.getDataNetworkType()) .thenReturn(TelephonyManager.NETWORK_TYPE_HSPA); updateServiceState(); - verifyDataIndicators(TelephonyIcons.DATA_H[1][0 /* No direction */], + verifyDataIndicators(TelephonyIcons.ICON_H, TelephonyIcons.QS_DATA_H); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java index 1555856c1875..1627925ae1bc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java @@ -30,6 +30,7 @@ import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.TelephonyIntents; import com.android.settingslib.net.DataUsageController; import com.android.systemui.R; +import com.android.systemui.statusbar.phone.SignalDrawable; import org.junit.Test; import org.junit.runner.RunWith; @@ -60,7 +61,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { mMockSubDefaults, mock(DeviceProvisionedController.class)); setupNetworkController(); - verifyLastMobileDataIndicators(false, 0, 0); + verifyLastMobileDataIndicators(false, -1, 0); } @Test @@ -132,45 +133,45 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { @Test public void testSignalStrength() { - for (int testStrength = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; - testStrength <= SignalStrength.SIGNAL_STRENGTH_GREAT; testStrength++) { + for (int testStrength = 0; + testStrength < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; testStrength++) { setupDefaultSignal(); setLevel(testStrength); verifyLastMobileDataIndicators(true, - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][testStrength], DEFAULT_ICON); + testStrength, DEFAULT_ICON); // Verify low inet number indexing. setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, true); verifyLastMobileDataIndicators(true, - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[0][testStrength], DEFAULT_ICON); + testStrength, DEFAULT_ICON, false, false); } } @Test public void testCdmaSignalStrength() { - for (int testStrength = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; - testStrength <= SignalStrength.SIGNAL_STRENGTH_GREAT; testStrength++) { + for (int testStrength = 0; + testStrength < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; testStrength++) { setupDefaultSignal(); setCdma(); setLevel(testStrength); verifyLastMobileDataIndicators(true, - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][testStrength], - TelephonyIcons.DATA_1X[1][0 /* No direction */]); + testStrength, + TelephonyIcons.ICON_1X); } } @Test public void testSignalRoaming() { - for (int testStrength = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; - testStrength <= SignalStrength.SIGNAL_STRENGTH_GREAT; testStrength++) { + for (int testStrength = 0; + testStrength < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; testStrength++) { setupDefaultSignal(); setGsmRoaming(true); setLevel(testStrength); verifyLastMobileDataIndicators(true, - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[1][testStrength], + testStrength, DEFAULT_ICON, true); } } @@ -185,8 +186,8 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { setLevel(testStrength); verifyLastMobileDataIndicators(true, - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[1][testStrength], - TelephonyIcons.DATA_1X[1][0 /* No direction */], true); + testStrength, + TelephonyIcons.ICON_1X, true); } } @@ -198,7 +199,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { setLevel(testStrength); verifyLastQsMobileDataIndicators(true, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[1][testStrength], + testStrength, DEFAULT_QS_ICON, false, false); } } @@ -212,8 +213,8 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { setLevel(testStrength); verifyLastQsMobileDataIndicators(true, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[1][testStrength], - TelephonyIcons.QS_ICON_1X, false, false); + testStrength, + TelephonyIcons.QS_DATA_1X, false, false); } } @@ -223,7 +224,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { setConnectivity(mMobileSignalController.mTransportType, false, false); setConnectivity(NetworkCapabilities.TRANSPORT_WIFI, true, true); - verifyLastMobileDataIndicators(true, TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][2], 0); + verifyLastMobileDataIndicators(true, DEFAULT_LEVEL, 0); } // Some tests of actual NetworkController code, just internals not display stuff @@ -418,7 +419,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { updateDataActivity(TelephonyManager.DATA_ACTIVITY_IN); verifyLastQsMobileDataIndicators(true /* visible */, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[1][DEFAULT_LEVEL] /* icon */, + DEFAULT_LEVEL /* icon */, DEFAULT_QS_ICON /* typeIcon */, true /* dataIn */, false /* dataOut */); @@ -432,11 +433,10 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { updateDataActivity(TelephonyManager.DATA_ACTIVITY_OUT); verifyLastQsMobileDataIndicators(true /* visible */, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[1][DEFAULT_LEVEL] /* icon */, + DEFAULT_LEVEL /* icon */, DEFAULT_QS_ICON /* typeIcon */, false /* dataIn */, true /* dataOut */); - } @Test @@ -446,7 +446,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { updateDataActivity(TelephonyManager.DATA_ACTIVITY_INOUT); verifyLastQsMobileDataIndicators(true /* visible */, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[1][DEFAULT_LEVEL] /* icon */, + DEFAULT_LEVEL /* icon */, DEFAULT_QS_ICON /* typeIcon */, true /* dataIn */, true /* dataOut */); @@ -460,7 +460,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { updateDataActivity(TelephonyManager.DATA_ACTIVITY_NONE); verifyLastQsMobileDataIndicators(true /* visible */, - TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[1][DEFAULT_LEVEL] /* icon */, + DEFAULT_LEVEL /* icon */, DEFAULT_QS_ICON /* typeIcon */, false /* dataIn */, false /* dataOut */); @@ -476,7 +476,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { // Verify baseline verifyLastMobileDataIndicators(true /* visible */, - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][strength] /* strengthIcon */, + strength /* strengthIcon */, DEFAULT_ICON /* typeIcon */); // API call is made @@ -484,7 +484,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { // Carrier network change is true, show special indicator verifyLastMobileDataIndicators(true /* visible */, - TelephonyIcons.TELEPHONY_CARRIER_NETWORK_CHANGE[0][0] /* strengthIcon */, + SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS), 0 /* typeIcon */); // Revert back @@ -492,7 +492,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { // Verify back in previous state verifyLastMobileDataIndicators(true /* visible */, - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][strength] /* strengthIcon */, + strength /* strengthIcon */, DEFAULT_ICON /* typeIcon */); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java index 483a8371b85b..73fa5aa180bf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java @@ -218,7 +218,7 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { setConnectivity(NetworkCapabilities.TRANSPORT_WIFI, true, true); setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false); verifyLastMobileDataIndicators(true, - TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[1][DEFAULT_LEVEL], + DEFAULT_LEVEL, 0, true); } 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 29d7f1ca85bc..838a2739f0b0 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 @@ package com.android.systemui.utils.leaks; 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 78fd174313b7..63b6a11c71ef 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 @@ public class ClientTest extends Activity { 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 @@ public class ClientTest extends Activity { 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 @@ public class ClientTest extends Activity { 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 a319beb6bbe9..f878b4d11f72 100644 --- a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java +++ b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java @@ -88,7 +88,7 @@ public class WallpaperCropActivity extends Activity { 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 579c54cd311e..f56cbdda734b 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -3906,6 +3906,11 @@ message MetricsEvent { // 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 c4a28313ed0a..65cc17eec6bd 100644 --- a/proto/src/system_messages.proto +++ b/proto/src/system_messages.proto @@ -173,6 +173,9 @@ message SystemMessage { // 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 b7ed3314ef1c..27d230b5737b 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 @@ public class NetworkActivity extends Activity { 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 @@ public class NetworkActivity extends Activity { 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 44525434c545..a4c891b46011 100644 --- a/services/Android.mk +++ b/services/Android.mk @@ -40,8 +40,8 @@ services := \ # 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 cb6d4df355b1..000394155ff1 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { 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 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } 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/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 63bf373316e1..57ef6d01a96b 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -48,6 +48,7 @@ import android.os.UserManager; import android.provider.Settings; import android.service.autofill.AutofillService; import android.service.autofill.AutofillServiceInfo; +import android.service.autofill.FillRequest; import android.service.autofill.IAutoFillService; import android.text.TextUtils; import android.util.LocalLog; @@ -169,7 +170,8 @@ final class AutofillManagerServiceImpl { structure.sanitizeForParceling(true); // TODO(b/33197203): Need to pipe the bundle - session.mRemoteFillService.onFillRequest(structure, null, session.mFlags); + FillRequest request = new FillRequest(structure, null, session.mFlags); + session.mRemoteFillService.onFillRequest(request); } }; diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java index dd520ac43a80..3badcfcb61cd 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java @@ -20,12 +20,10 @@ import static com.android.server.autofill.Helper.DEBUG; import android.annotation.NonNull; import android.annotation.Nullable; -import android.app.assist.AssistStructure; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.Bundle; import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.ICancellationSignal; @@ -33,10 +31,12 @@ import android.os.Message; import android.os.RemoteException; import android.os.UserHandle; import android.service.autofill.AutofillService; +import android.service.autofill.FillRequest; import android.service.autofill.FillResponse; import android.service.autofill.IAutoFillService; import android.service.autofill.IFillCallback; import android.service.autofill.ISaveCallback; +import android.service.autofill.SaveRequest; import android.text.format.DateUtils; import android.util.Slog; @@ -88,7 +88,7 @@ final class RemoteFillService implements DeathRecipient { public interface FillServiceCallbacks { void onFillRequestSuccess(@Nullable FillResponse response, - @NonNull String servicePackageName); + @NonNull String servicePackageName, int requestId); void onFillRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName); void onSaveRequestSuccess(@NonNull String servicePackageName); @@ -134,17 +134,16 @@ final class RemoteFillService implements DeathRecipient { mCallbacks.onServiceDied(this); } - public void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle extras, - int flags) { + public void onFillRequest(@NonNull FillRequest request) { cancelScheduledUnbind(); - final PendingFillRequest request = new PendingFillRequest(structure, extras, this, flags); - mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, request).sendToTarget(); + final PendingFillRequest pendingRequest = new PendingFillRequest(request, this); + mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, pendingRequest).sendToTarget(); } - public void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle extras) { + public void onSaveRequest(@NonNull SaveRequest request) { cancelScheduledUnbind(); - final PendingSaveRequest request = new PendingSaveRequest(structure, extras, this); - mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, request).sendToTarget(); + final PendingSaveRequest pendingRequest = new PendingSaveRequest(request, this); + mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, pendingRequest).sendToTarget(); } // Note: we are dumping without a lock held so this is a bit racy but @@ -253,10 +252,11 @@ final class RemoteFillService implements DeathRecipient { } private void dispatchOnFillRequestSuccess(PendingRequest pendingRequest, - FillResponse response) { + FillResponse response, int requestId) { mHandler.getHandler().post(() -> { if (handleResponseCallbackCommon(pendingRequest)) { - mCallbacks.onFillRequestSuccess(response, mComponentName.getPackageName()); + mCallbacks.onFillRequestSuccess(response, mComponentName.getPackageName(), + requestId); } }); } @@ -392,18 +392,13 @@ final class RemoteFillService implements DeathRecipient { private static final class PendingFillRequest extends PendingRequest { private final Object mLock = new Object(); private final WeakReference<RemoteFillService> mWeakService; - private final AssistStructure mStructure; - private final Bundle mExtras; + private final FillRequest mRequest; private final IFillCallback mCallback; private ICancellationSignal mCancellation; private boolean mCancelled; - private int mFlags; - public PendingFillRequest(AssistStructure structure, - Bundle extras, RemoteFillService service, int flags) { - mStructure = structure; - mExtras = extras; - mFlags = flags; + public PendingFillRequest(FillRequest request, RemoteFillService service) { + mRequest = request; mWeakService = new WeakReference<>(service); mCallback = new IFillCallback.Stub() { @Override @@ -425,11 +420,11 @@ final class RemoteFillService implements DeathRecipient { } @Override - public void onSuccess(FillResponse response) { + public void onSuccess(FillResponse response, int requestId) { RemoteFillService remoteService = mWeakService.get(); if (remoteService != null) { remoteService.dispatchOnFillRequestSuccess( - PendingFillRequest.this, response); + PendingFillRequest.this, response, requestId); } } @@ -449,8 +444,7 @@ final class RemoteFillService implements DeathRecipient { RemoteFillService remoteService = mWeakService.get(); if (remoteService != null) { try { - remoteService.mAutoFillService.onFillRequest(mStructure, - mExtras, mCallback, mFlags); + remoteService.mAutoFillService.onFillRequest(mRequest, mCallback); } catch (RemoteException e) { Slog.e(LOG_TAG, "Error calling on fill request", e); cancel(); @@ -481,14 +475,12 @@ final class RemoteFillService implements DeathRecipient { private static final class PendingSaveRequest extends PendingRequest { private final WeakReference<RemoteFillService> mWeakService; - private final AssistStructure mStructure; - private final Bundle mExtras; + private final SaveRequest mRequest; private final ISaveCallback mCallback; - public PendingSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle extras, + public PendingSaveRequest(@NonNull SaveRequest request, @NonNull RemoteFillService service) { - mStructure = structure; - mExtras = extras; + mRequest = request; mWeakService = new WeakReference<>(service); mCallback = new ISaveCallback.Stub() { @Override @@ -516,7 +508,7 @@ final class RemoteFillService implements DeathRecipient { final RemoteFillService service = mWeakService.get(); if (service != null) { try { - service.mAutoFillService.onSaveRequest(mStructure, mExtras, mCallback); + service.mAutoFillService.onSaveRequest(mRequest, mCallback); } catch (RemoteException e) { Slog.e(LOG_TAG, "Error calling on save request", e); } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 67c2314cac35..5feb81db4a0b 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -44,11 +44,15 @@ import android.os.Parcelable; import android.os.RemoteException; import android.service.autofill.AutofillService; import android.service.autofill.Dataset; +import android.service.autofill.FillContext; +import android.service.autofill.FillRequest; import android.service.autofill.FillResponse; import android.service.autofill.SaveInfo; +import android.service.autofill.SaveRequest; import android.util.ArrayMap; import android.util.DebugUtils; import android.util.Slog; +import android.util.SparseArray; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; @@ -125,7 +129,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState RemoteFillService mRemoteFillService; @GuardedBy("mLock") - private ArrayList<FillResponse> mResponses; + private SparseArray<FillResponse> mResponses; /** * Response that requires a service authentitcation request. @@ -156,7 +160,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * and used on subsequent {@code onFillRequest()} and {@code onSaveRequest()} calls. */ @GuardedBy("mLock") - private Bundle mExtras; + private Bundle mClientState; /** * Flags used to start the session. @@ -222,7 +226,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // FillServiceCallbacks @Override public void onFillRequestSuccess(@Nullable FillResponse response, - @NonNull String servicePackageName) { + @NonNull String servicePackageName, int requestId) { if (response == null) { if ((mFlags & FLAG_MANUAL_REQUEST) != 0) { getUiForShowing().showError(R.string.autofill_error_cannot_autofill); @@ -243,7 +247,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // TODO(b/33197203 , b/35707731): make sure it's ignored if there is one already mResponseWaitingAuth = response; } - processResponseLocked(response); + processResponseLocked(response, requestId); } final LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST)) @@ -343,9 +347,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (id.equals(mCurrentViewId)) { try { final ViewState view = mViewStates.get(id); - mClient.requestShowFillUi(mWindowToken, id, width, height, - view.getVirtualBounds(), - presenter); + mClient.requestShowFillUi(this.id, mWindowToken, id, width, height, + view.getVirtualBounds(), presenter); } catch (RemoteException e) { Slog.e(TAG, "Error requesting to show fill UI", e); } @@ -363,13 +366,30 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState public void requestHideFillUi(AutofillId id) { synchronized (mLock) { try { - mClient.requestHideFillUi(mWindowToken, id); + mClient.requestHideFillUi(this.id, mWindowToken, id); } catch (RemoteException e) { Slog.e(TAG, "Error requesting to hide fill UI", e); } } } + // 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(); @@ -378,12 +398,18 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState AutofillManager.EXTRA_AUTHENTICATION_RESULT); if (result instanceof FillResponse) { mMetricsLogger.action(MetricsEvent.AUTOFILL_AUTHENTICATED, mPackageName); + final int requestIndex = mResponses.indexOfValue(mResponseWaitingAuth); mResponseWaitingAuth = null; - processResponseLocked((FillResponse) result); + if (requestIndex >= 0) { + final int requestId = mResponses.keyAt(requestIndex); + processResponseLocked((FillResponse) result, requestId); + } else { + Slog.e(TAG, "Error cannot find id for auth response"); + } } else if (result instanceof Dataset) { final Dataset dataset = (Dataset) result; for (int i = 0; i < mResponses.size(); i++) { - final FillResponse response = mResponses.get(i); + final FillResponse response = mResponses.valueAt(i); final int index = response.getDatasets().indexOf(mDatasetWaitingAuth); if (index >= 0) { response.getDatasets().set(index, dataset); @@ -424,12 +450,18 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return true; } - final FillResponse response = mResponses.get(mResponses.size() - 1); + final int lastResponseIdx = getLastResponseIndex(); + if (lastResponseIdx < 0) { + Slog.d(TAG, "showSaveLocked(): mResponses=" + mResponses + + ", mViewStates=" + mViewStates); + return true; + } + final FillResponse response = mResponses.valueAt(lastResponseIdx); final SaveInfo saveInfo = response.getSaveInfo(); if (DEBUG) { - Slog.d(TAG, - "showSaveLocked(): mResponses=" + mResponses + ", mViewStates=" + mViewStates); + Slog.d(TAG, "showSaveLocked(): mResponses=" + mResponses + + ", mViewStates=" + mViewStates); } /* @@ -556,7 +588,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mStructure.dump(); } - mRemoteFillService.onSaveRequest(mStructure, mExtras); + // TODO(b/33197203): Implement partitioning properly + final int lastResponseIdx = getLastResponseIndex(); + final int requestId = mResponses.keyAt(lastResponseIdx); + final FillContext fillContext = new FillContext(requestId, mStructure); + final ArrayList fillContexts = new ArrayList(1); + fillContexts.add(fillContext); + + final SaveRequest saveRequest = new SaveRequest(fillContexts, mClientState); + mRemoteFillService.onSaveRequest(saveRequest); } void updateLocked(AutofillId id, Rect virtualBounds, AutofillValue value, int flags) { @@ -569,7 +609,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } 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); @@ -670,7 +710,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState overlay.focused = id.equals(viewState.id); node.setAutofillOverlay(overlay); } - mRemoteFillService.onFillRequest(mStructure, mExtras, 0); + + FillRequest request = new FillRequest(mStructure, mClientState, 0); + mRemoteFillService.onFillRequest(request); return newViewState; } @@ -699,7 +741,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } if (!mHasCallback) return; try { - mClient.notifyNoFillUi(mWindowToken, mCurrentViewId); + mClient.notifyNoFillUi(id, mWindowToken, mCurrentViewId); } catch (RemoteException e) { Slog.e(TAG, "Error notifying client no fill UI: windowToken=" + mWindowToken + " id=" + mCurrentViewId, e); @@ -707,17 +749,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } - private void processResponseLocked(FillResponse response) { + private void processResponseLocked(FillResponse response, int requestId) { if (DEBUG) { Slog.d(TAG, "processResponseLocked(mCurrentViewId=" + mCurrentViewId + "):" + response); } if (mResponses == null) { - mResponses = new ArrayList<>(4); + mResponses = new SparseArray<>(4); } - mResponses.add(response); + mResponses.put(requestId, response); if (response != null) { - mExtras = response.getExtras(); + mClientState = response.getClientState(); } setViewStatesLocked(response, ViewState.STATE_FILLABLE); @@ -835,7 +877,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private void startAuthentication(IntentSender intent, Intent fillInIntent) { try { synchronized (mLock) { - mClient.authenticate(intent, fillInIntent); + mClient.authenticate(id, intent, fillInIntent); } } catch (RemoteException e) { Slog.e(TAG, "Error launching auth intent", e); @@ -868,7 +910,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } pw.print(prefix); pw.print("mHasCallback: "); pw.println(mHasCallback); - pw.print(prefix); pw.print("mExtras: "); pw.println(Helper.bundleToString(mExtras)); + pw.print(prefix); pw.print("mClientState: "); pw.println( + Helper.bundleToString(mClientState)); mRemoteFillService.dump(prefix, pw); } @@ -878,7 +921,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (DEBUG) { Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset); } - mClient.autofill(mWindowToken, dataset.getFieldIds(), dataset.getFieldValues()); + mClient.autofill(id, mWindowToken, dataset.getFieldIds(), dataset.getFieldValues()); setViewStatesLocked(null, dataset, ViewState.STATE_AUTOFILLED); } catch (RemoteException e) { Slog.w(TAG, "Error autofilling activity: " + e); @@ -945,4 +988,20 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState destroyLocked(); mService.removeSessionLocked(id); } + + private int getLastResponseIndex() { + // The response ids are monotonically increasing so + // we just find the largest id which is the last. We + // do not rely on the internal ordering in sparse + // array to avoid - wow this stopped working!? + int lastResponseIdx = -1; + int lastResponseId = -1; + final int responseCount = mResponses.size(); + for (int i = 0; i < responseCount; i++) { + if (mResponses.keyAt(i) > lastResponseId) { + lastResponseIdx = i; + } + } + return lastResponseIdx; + } } 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 64dee584165e..ab6a3a7cd78b 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.Dataset; 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 @@ import java.io.PrintWriter; 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 @@ public final class AutoFillUI { 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 @@ public final class AutoFillUI { void requestShowFillUi(AutofillId id, int width, int height, IAutofillWindowPresenter presenter); void requestHideFillUi(AutofillId id); + void startIntentSender(IntentSender intentSender); } public AutoFillUI(@NonNull Context context) { @@ -164,7 +161,8 @@ public final class AutoFillUI { log.setType(MetricsProto.MetricsEvent.TYPE_DETAIL); hideFillUiUiThread(); if (mCallback != null) { - mCallback.authenticate(response.getAuthentication(), response.getExtras()); + mCallback.authenticate(response.getAuthentication(), + response.getClientState()); } } @@ -205,6 +203,13 @@ public final class AutoFillUI { mCallback.requestHideFillUi(focusedId); } } + + @Override + public void startIntentSender(IntentSender intentSender) { + if (mCallback != null) { + mCallback.startIntentSender(intentSender); + } + } }); }); } @@ -273,22 +278,11 @@ public final class AutoFillUI { 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 b69d1dc3d97c..b68e3b1e2543 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 @@ package com.android.server.autofill.ui; 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 @@ final class FillUi { void requestShowFillUi(int width, int height, IAutofillWindowPresenter windowPresenter); void requestHideFillUi(); + void startIntentSender(IntentSender intentSender); } private final @NonNull AutofillWindowPresenter mWindowPresenter = @@ -69,7 +73,6 @@ final class FillUi { private final @Nullable ArrayAdapter<ViewItem> mAdapter; private @Nullable String mFilterText; - private final String mAccessibilityTitle; private int mContentWidth; private int mContentHeight; @@ -81,7 +84,20 @@ final class FillUi { @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 class FillUi { 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 class FillUi { 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 class FillUi { } }; - 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 @@ final class FillUi { } 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 @@ final class FillUi { } else { mListView.setVerticalScrollBarEnabled(false); } + if (mAdapter.getCount() != oldCount) { + mListView.requestLayout(); + } } }); } @@ -312,7 +332,8 @@ final class FillUi { 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 @@ final class FillUi { 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/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index d647c635cbb2..aa5083dfeb15 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -798,6 +798,19 @@ public class BackupManagerService { return ((app.flags & ApplicationInfo.FLAG_STOPPED) != 0); } + // We also avoid backups of 'disabled' apps + private static boolean appIsDisabled(ApplicationInfo app, PackageManager pm) { + switch (pm.getApplicationEnabledSetting(app.packageName)) { + case PackageManager.COMPONENT_ENABLED_STATE_DISABLED: + case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER: + case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED: + return true; + + default: + return false; + } + } + /* does *not* check overall backup eligibility policy! */ private static boolean appGetsFullBackup(PackageInfo pkg) { if (pkg.applicationInfo.backupAgentName != null) { @@ -10774,7 +10787,8 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); if (!appIsEligibleForBackup(packageInfo.applicationInfo) || - appIsStopped(packageInfo.applicationInfo)) { + appIsStopped(packageInfo.applicationInfo) || + appIsDisabled(packageInfo.applicationInfo, mPackageManager)) { return false; } IBackupTransport transport = mTransportManager.getCurrentTransportBinder(); diff --git a/services/core/Android.mk b/services/core/Android.mk index 8003d21d165e..f89647897d09 100644 --- a/services/core/Android.mk +++ b/services/core/Android.mk @@ -20,17 +20,17 @@ LOCAL_AIDL_INCLUDES += \ 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/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java index dcf6fd718722..1a5ec61a1510 100644 --- a/services/core/java/com/android/server/AppOpsService.java +++ b/services/core/java/com/android/server/AppOpsService.java @@ -416,6 +416,29 @@ public class AppOpsService extends IAppOpsService.Stub { 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 @@ public class AppOpsService extends IAppOpsService.Stub { } } + @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 @@ public class AppOpsService extends IAppOpsService.Stub { int op; int mode; int packageUid; + int nonpackageUid; Shell(IAppOpsService iface, AppOpsService internal) { mInterface = iface; @@ -1790,15 +1835,59 @@ public class AppOpsService extends IAppOpsService.Stub { 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 @@ public class AppOpsService extends IAppOpsService.Stub { 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 @@ public class AppOpsService extends IAppOpsService.Stub { 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 @@ public class AppOpsService extends IAppOpsService.Stub { 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/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 50c0a124fb8a..d5adf4856d47 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -55,6 +55,7 @@ import android.net.LinkProperties.CompareResult; import android.net.Network; import android.net.NetworkAgent; import android.net.NetworkCapabilities; +import android.net.MatchAllNetworkSpecifier; import android.net.NetworkConfig; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; @@ -89,7 +90,6 @@ import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.SystemClock; -import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -203,6 +203,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS private final int mReleasePendingIntentDelayMs; + private MockableSystemProperties mSystemProperties; + private Tethering mTethering; private final PermissionMonitor mPermissionMonitor; @@ -675,6 +677,8 @@ public class ConnectivityService extends IConnectivityManager.Stub IpConnectivityLog logger) { if (DBG) log("ConnectivityService starting up"); + mSystemProperties = getSystemProperties(); + mMetricsLog = logger; mDefaultRequest = createInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST); NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest, new Binder()); @@ -692,7 +696,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000); - mLingerDelayMs = SystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS); + mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS); mContext = checkNotNull(context, "missing Context"); mNetd = checkNotNull(netManager, "missing INetworkManagementService"); @@ -722,7 +726,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1]; // TODO: What is the "correct" way to do determine if this is a wifi only device? - boolean wifiOnly = SystemProperties.getBoolean("ro.radio.noril", false); + boolean wifiOnly = mSystemProperties.getBoolean("ro.radio.noril", false); log("wifiOnly=" + wifiOnly); String[] naStrings = context.getResources().getStringArray( com.android.internal.R.array.networkAttributes); @@ -775,8 +779,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - mTestMode = SystemProperties.get("cm.test.mode").equals("true") - && SystemProperties.get("ro.build.type").equals("eng"); + mTestMode = mSystemProperties.get("cm.test.mode").equals("true") + && mSystemProperties.get("ro.build.type").equals("eng"); mTethering = new Tethering(mContext, mNetd, statsService, mPolicyManager, IoThread.get().getLooper(), new MockableSystemProperties()); @@ -1732,8 +1736,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // Overridden for testing purposes to avoid writing to SystemProperties. @VisibleForTesting - protected int getDefaultTcpRwnd() { - return SystemProperties.getInt(DEFAULT_TCP_RWND_KEY, 0); + protected MockableSystemProperties getSystemProperties() { + return new MockableSystemProperties(); } private void updateTcpBufferSizes(NetworkAgentInfo nai) { @@ -1771,10 +1775,11 @@ public class ConnectivityService extends IConnectivityManager.Stub } Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.TCP_DEFAULT_INIT_RWND, getDefaultTcpRwnd()); + Settings.Global.TCP_DEFAULT_INIT_RWND, + mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)); final String sysctlKey = "sys.sysctl.tcp_def_init_rwnd"; if (rwndValue != 0) { - SystemProperties.set(sysctlKey, rwndValue.toString()); + mSystemProperties.set(sysctlKey, rwndValue.toString()); } } @@ -1798,7 +1803,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public int getRestoreDefaultNetworkDelay(int networkType) { - String restoreDefaultNetworkDelayStr = SystemProperties.get( + String restoreDefaultNetworkDelayStr = mSystemProperties.get( NETWORK_RESTORE_DELAY_PROP_NAME); if(restoreDefaultNetworkDelayStr != null && restoreDefaultNetworkDelayStr.length() != 0) { @@ -2965,7 +2970,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public boolean isTetheringSupported() { enforceTetherAccessPermission(); - int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1); + int defaultVal = (mSystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1); boolean tetherEnabledInSettings = (Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.TETHER_SUPPORTED, defaultVal) != 0) && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING); @@ -4044,11 +4049,8 @@ public class ConnectivityService extends IConnectivityManager.Stub throw new IllegalArgumentException("Bad timeout specified"); } - if (NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER - .equals(networkCapabilities.getNetworkSpecifier())) { - throw new IllegalArgumentException("Invalid network specifier - must not be '" - + NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER + "'"); - } + MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier( + networkCapabilities.getNetworkSpecifier()); NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType, nextNetworkRequestId(), type); @@ -4117,6 +4119,9 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceMeteredApnPolicy(networkCapabilities); ensureRequestableCapabilities(networkCapabilities); + MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier( + networkCapabilities.getNetworkSpecifier()); + NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.REQUEST); NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation); @@ -4178,6 +4183,9 @@ public class ConnectivityService extends IConnectivityManager.Stub nc.addCapability(NET_CAPABILITY_FOREGROUND); } + MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier( + networkCapabilities.getNetworkSpecifier()); + NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.LISTEN); NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder); @@ -4195,6 +4203,9 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceAccessPermission(); } + MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier( + networkCapabilities.getNetworkSpecifier()); + NetworkRequest networkRequest = new NetworkRequest( new NetworkCapabilities(networkCapabilities), TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.LISTEN); @@ -4466,17 +4477,24 @@ public class ConnectivityService extends IConnectivityManager.Stub int last = 0; for (InetAddress dns : dnses) { ++last; - String key = "net.dns" + last; - String value = dns.getHostAddress(); - SystemProperties.set(key, value); + setNetDnsProperty(last, dns.getHostAddress()); } for (int i = last + 1; i <= mNumDnsEntries; ++i) { - String key = "net.dns" + i; - SystemProperties.set(key, ""); + setNetDnsProperty(i, ""); } mNumDnsEntries = last; } + private void setNetDnsProperty(int which, String value) { + final String key = "net.dns" + which; + // Log and forget errors setting unsupported properties. + try { + mSystemProperties.set(key, value); + } catch (Exception e) { + Log.e(TAG, "Error setting unsupported net.dns property: ", e); + } + } + private String getNetworkPermission(NetworkCapabilities nc) { // TODO: make these permission strings AIDL constants instead. if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) { diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index f0720f326e15..9e054c3e761c 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -146,6 +146,9 @@ public class LocationManagerService extends ILocationManager.Stub { // 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 @@ public class LocationManagerService extends ILocationManager.Stub { } }; mActivityManager.addOnUidImportanceListener(uidImportanceListener, - ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE); + FOREGROUND_IMPORTANCE_CUTOFF); mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); updateUserProfiles(mCurrentUserId); @@ -452,7 +455,7 @@ public class LocationManagerService extends ILocationManager.Stub { } 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 9218c25a9860..d25b3cc68221 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.TimeoutException; 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 @@ public class NetworkScoreService extends INetworkScoreService.Stub { 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 class NetworkScoreService extends INetworkScoreService.Stub { } 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 @@ public class NetworkScoreService extends INetworkScoreService.Stub { 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 @@ public class NetworkScoreService extends INetworkScoreService.Stub { 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 @@ public class NetworkScoreService extends INetworkScoreService.Stub { 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 class NetworkScoreService extends INetworkScoreService.Stub { public boolean isCallerActiveScorer(int callingUid) { synchronized (mServiceConnectionLock) { return mServiceConnection != null - && mServiceConnection.mAppData.packageUid == callingUid; + && mServiceConnection.getAppData().packageUid == callingUid; } } @@ -720,7 +725,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { if (isCallerSystemProcess(getCallingUid()) || callerCanRequestScores()) { synchronized (mServiceConnectionLock) { if (mServiceConnection != null) { - return mServiceConnection.mAppData; + return mServiceConnection.getAppData(); } } } else { @@ -1020,7 +1025,9 @@ public class NetworkScoreService extends INetworkScoreService.Stub { 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 @@ public class NetworkScoreService extends INetworkScoreService.Stub { 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 @@ public class NetworkScoreService extends INetworkScoreService.Stub { 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 @@ public class NetworkScoreService extends INetworkScoreService.Stub { 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 000000000000..03f82a8e5d8e --- /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 5f585cc799c9..eb58e4c54246 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 @@ public class AccountManagerService 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 @@ public class AccountManagerService notifyPackage(packageToVisibility.getKey(), accounts); } } + sendAccountRemovedBroadcast(accounts.userId); } else { ArrayList<String> accountNames = accountNamesByType.get(account.type); if (accountNames == null) { @@ -1971,6 +1978,7 @@ public class AccountManagerService sendNotificationAccountUpdated(resultAccount, accounts); sendAccountsChangedBroadcast(accounts.userId); + sendAccountRemovedBroadcast(accounts.userId); } } return resultAccount; @@ -2206,6 +2214,7 @@ public class AccountManagerService // 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 7dd75df5252a..c77820b4de3a 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 @@ public final class ActiveServices { 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 @@ public final class ActiveServices { // 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); - } - } finally { - Binder.restoreCallingIdentity(token); + // 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); } } diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index df250b19beba..55ee18335410 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 @@ import java.io.PrintWriter; */ 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 @@ final class ActivityManagerConstants extends ContentObserver { // 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 @@ final class ActivityManagerConstants extends ContentObserver { 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 35654d76dee5..6b0a73b25e71 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_GROUP_TOP_APP; 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub // 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 @@ public class ActivityManagerService extends IActivityManager.Stub } 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 @@ public class ActivityManagerService extends IActivityManager.Stub } 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 @@ public class ActivityManagerService extends IActivityManager.Stub } 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 @@ public class ActivityManagerService extends IActivityManager.Stub } return rec; } - rec.canceled = true; + makeIntentSenderCanceledLocked(rec); mIntentSenderRecords.remove(key); } if (noCreate) { @@ -7516,7 +7538,7 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub } 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 @@ public class ActivityManagerService extends IActivityManager.Stub } @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 @@ public class ActivityManagerService extends IActivityManager.Stub // 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub // 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 @@ public class ActivityManagerService extends IActivityManager.Stub // 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub } @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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 @@ public class ActivityManagerService extends IActivityManager.Stub Slog.w(TAG, "markAsSentFromNotification(): not a PendingIntentRecord: " + target); return; } - ((PendingIntentRecord) target).setWhitelistDuration(duration); + ((PendingIntentRecord) target).setWhitelistDurationLocked(duration); } @Override @@ -23761,24 +23855,6 @@ public class ActivityManagerService extends IActivityManager.Stub } @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(); @@ -23809,6 +23885,15 @@ public class ActivityManagerService extends IActivityManager.Stub } } + @Override + public long getActivityStartInitiatedTime(IBinder token) { + final ActivityRecord r = ActivityRecord.forTokenLocked(token); + if (r != null) { + return r.mStartInitiatedTimeMs; + } + return 0; + } + void updateApplicationInfoLocked(@NonNull List<String> packagesToUpdate, int userId) { final PackageManagerInternal packageManager = getPackageManagerInternalLocked(); final boolean updateFrameworkRes = packagesToUpdate.contains("android"); diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 04c2af5af339..0fcf3e66debe 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 @@ final class ActivityManagerShellCommand extends ShellCommand { 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 95d715860e4e..17c7dde11726 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -341,6 +341,12 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo private final Rect mBounds = new Rect(); /** + * Denotes the timestamp at which this activity start was last initiated in the + * {@link SystemClock#uptimeMillis()} time base. + */ + long mStartInitiatedTimeMs; + + /** * Temp configs used in {@link #ensureActivityConfigurationLocked(int, boolean)} */ private final Configuration mTmpConfig1 = new Configuration(); @@ -423,11 +429,11 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo pw.print("\""); pw.print(" primaryColor="); pw.println(Integer.toHexString(taskDescription.getPrimaryColor())); - pw.print(" backgroundColor="); + pw.print(prefix + " backgroundColor="); pw.println(Integer.toHexString(taskDescription.getBackgroundColor())); - pw.print(" statusBarColor="); + pw.print(prefix + " statusBarColor="); pw.println(Integer.toHexString(taskDescription.getStatusBarColor())); - pw.print(" navigationBarColor="); + pw.print(prefix + " navigationBarColor="); pw.println(Integer.toHexString(taskDescription.getNavigationBarColor())); } if (iconFilename == null && taskDescription.getIcon() != null) { @@ -498,6 +504,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo pw.print(" forceNewConfig="); pw.println(forceNewConfig); pw.print(prefix); pw.print("mActivityType="); pw.println(activityTypeToString(mActivityType)); + pw.print(prefix); pw.print("mStartInitiatedTimeMs="); + TimeUtils.formatDuration(mStartInitiatedTimeMs, now, pw); if (requestedVrComponent != null) { pw.print(prefix); pw.print("requestedVrComponent="); @@ -1163,10 +1171,13 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } /** + * @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; @@ -1177,17 +1188,24 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo 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, @@ -1561,8 +1579,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true; } - void notifyAppResumed(boolean wasStopped, boolean allowSavedSurface) { - mWindowContainerController.notifyAppResumed(wasStopped, allowSavedSurface); + void notifyAppResumed(boolean wasStopped) { + mWindowContainerController.notifyAppResumed(wasStopped); } void notifyUnknownVisibilityLaunched() { @@ -2112,7 +2130,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo 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; } @@ -2552,7 +2571,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo preserveWindowOnDeferredRelaunch = false; } - boolean isProcessRunning() { + private boolean isProcessRunning() { ProcessRecord proc = app; if (proc == null) { proc = service.mProcessNames.get(processName, info.applicationInfo.uid); @@ -2560,6 +2579,26 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo 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 f551a445e773..4c84d98d468a 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -65,7 +65,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NA import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; -import static com.android.server.am.ActivityStack.ActivityState.STOPPED; import static com.android.server.am.ActivityStackSupervisor.FindTaskResult; import static com.android.server.am.ActivityStackSupervisor.ON_TOP; import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY; @@ -117,6 +116,7 @@ import android.util.Slog; 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; @@ -231,9 +231,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // 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. @@ -645,9 +646,13 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } 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; } } @@ -1167,8 +1172,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); - // TODO(b/37244415): This just wrong. We should also be moving PAUSED activities to - // the stopped state when we are sleeping. if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED || r.state == ActivityState.PAUSED || r.state == ActivityState.PAUSING) { r.setSleeping(true); @@ -1324,7 +1327,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai + (timeout ? " (due to timeout)" : " (pause complete)")); mService.mWindowManager.deferSurfaceLayout(); try { - completePauseLocked(true, null); + completePauseLocked(true /* resumeNext */, null /* resumingActivity */); } finally { mService.mWindowManager.continueSurfaceLayout(); } @@ -1803,15 +1806,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Skipping: already visible at " + r); - if (r.state == STOPPED) { - // In this case the activity is visible, but in the stopped state. - // This sometimes happens if the activity is behind the lockscreen. - // Restart the activity to the paused or resumed state since we want - // it to be in the visible state now. - makeVisibleAndRestartIfNeeded(starting, configChanges, isTop, - resumeNextActivity, r); - } - if (r.handleAlreadyVisible()) { resumeNextActivity = false; } @@ -2001,10 +1995,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // 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); @@ -2023,6 +2017,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // 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 @@ -2030,7 +2025,18 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // 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 */); } @@ -2198,8 +2204,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai 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; @@ -2531,26 +2539,14 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } - 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, @@ -3985,6 +3981,18 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai 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); @@ -5044,14 +5052,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai * {@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); } @@ -5083,6 +5083,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai 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 88de8a5fcbed..4d16e33ad81c 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.util.ArrayUtils; 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; @@ -1477,12 +1478,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D stack.minimalResumeActivityLocked(r); } else { // This activity is not starting in the resumed state... which should look like we asked - // it to resume+pause (but remain visible), and it has done so and reported back the + // it to pause+stop (but remain visible), and it has done so and reported back the // current icicle and other state. if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r + " (starting in paused state)"); r.state = PAUSED; - r.stopped = false; } // Launch the new version setup screen if needed. We do this -after- @@ -2493,11 +2493,21 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } 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 { @@ -2858,12 +2868,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D 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(); @@ -2933,6 +2943,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D 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 */); @@ -3090,7 +3105,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } mGoingToSleepActivities.clear(); - ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); } void activitySleptLocked(ActivityRecord r) { diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java index cafc4f0ecc96..b91c7b1726f3 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 @@ class ActivityStartInterceptor { 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/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 56594d3fdf48..8f1c20330e53 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -244,6 +244,7 @@ class ActivityStarter { ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask) { + final long activityStartTime = SystemClock.uptimeMillis(); int err = ActivityManager.START_SUCCESS; ProcessRecord callerApp = null; @@ -478,6 +479,7 @@ class ActivityStarter { callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, mSupervisor, container, options, sourceRecord); + r.mStartInitiatedTimeMs = activityStartTime; if (outActivity != null) { outActivity[0] = r; } @@ -1029,6 +1031,7 @@ class ActivityStarter { // so make sure the task now has the identity of the new intent. top.getTask().setIntent(mStartActivity); } + top.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs; ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask()); top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage); @@ -1052,6 +1055,7 @@ class ActivityStarter { setTaskFromIntentActivity(reusedActivity); if (!mAddingToTask && mReuseTask == null) { + reusedActivity.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs; // We didn't do anything... but it was needed (a.k.a., client don't use that // intent!) And for paranoia, make sure we have correctly resumed the top activity. resumeTargetStackIfNeeded(); @@ -1084,6 +1088,7 @@ class ActivityStarter { || mLaunchSingleTop || mLaunchSingleTask); if (dontStart) { ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask()); + top.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs; // For paranoia, make sure we have correctly resumed the top activity. topStack.mLastPausedActivity = null; if (mDoResume) { @@ -1664,6 +1669,7 @@ class ActivityStarter { // desires. if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop) && intentActivity.realActivity.equals(mStartActivity.realActivity)) { + intentActivity.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs; ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, intentActivity.getTask()); if (intentActivity.frontOfTask) { diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java index 646f6ce0653a..02ec07561f4f 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 @@ final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListen @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 @@ final class AppErrorDialog extends BaseErrorDialog implements View.OnClickListen 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 9e297255c2f9..a3a67784fadc 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 @@ final class AppNotRespondingDialog extends BaseErrorDialog implements View.OnCli @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 dd3d4e0d1be2..baa71d708caa 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 @@ public final class BroadcastQueue { .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 @@ public final class BroadcastQueue { || (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 4a87941af8b9..c2f1890699a8 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 @@ public class HealthStatsBatteryStatsWriter { /** * 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 @@ public class HealthStatsBatteryStatsWriter { 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 f05bfb6174d3..c697f2876c65 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.content.Intent; 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 @@ final class PendingIntentRecord extends IIntentSender.Stub { boolean sent = false; boolean canceled = false; private long whitelistDuration = 0; + private RemoteCallbackList<IResultReceiver> mCancelCallbacks; String stringName; String lastTagPrefix; @@ -191,11 +194,31 @@ final class PendingIntentRecord extends IIntentSender.Stub { 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 @@ final class PendingIntentRecord extends IIntentSender.Stub { 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 @@ final class PendingIntentRecord extends IIntentSender.Stub { 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 394e902ec27e..cd9c42c7c643 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 android.graphics.Rect; 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 @@ import java.util.List; /** * 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 @@ class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> { 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 c7f20b9ff904..f8a4d4b21414 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 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta // 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); diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index c11f5316f769..268724283351 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.media.AudioManager.RINGER_MODE_VIBRATE; 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 @@ public class AudioService extends IAudioService.Stub 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 @@ public class AudioService extends IAudioService.Stub } 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 @@ public class AudioService extends IAudioService.Stub return devices; } - public String getSettingNameForDevice(int device) { - String name = mVolumeIndexSettingName; - String suffix = AudioSystem.getOutputDeviceName(device); + public @Nullable String getSettingNameForDevice(int device) { + if (!hasValidSettingsName()) { + return null; + } + final String suffix = AudioSystem.getOutputDeviceName(device); if (suffix.isEmpty()) { - return name; + return mVolumeIndexSettingName; } - return name + "_" + suffix; + return mVolumeIndexSettingName + "_" + suffix; + } + + private boolean hasValidSettingsName() { + return (mVolumeIndexSettingName != null && !mVolumeIndexSettingName.isEmpty()); } public void readSettings() { @@ -4033,13 +4048,18 @@ public class AudioService extends IAudioService.Stub 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 @@ public class AudioService extends IAudioService.Stub 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 @@ public class AudioService extends IAudioService.Stub 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 51aa4f8a834a..9eda9294031e 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 @@ public final class PlaybackActivityMonitor .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 ad66faa8cf04..5dee91de0e77 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_ETHERNET; 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.DefaultNetworkEvent; 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.RaEvent; 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 @@ final public class IpConnectivityEventBuilder { } 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 @@ final public class IpConnectivityEventBuilder { 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 @@ final public class IpConnectivityEventBuilder { 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 @@ final public class IpConnectivityEventBuilder { 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 da56a07d2396..475d786aedd1 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 @@ final public class IpConnectivityMetrics extends SystemService { @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/MockableSystemProperties.java b/services/core/java/com/android/server/connectivity/MockableSystemProperties.java index 4f68652d412c..77b86d8e4355 100644 --- a/services/core/java/com/android/server/connectivity/MockableSystemProperties.java +++ b/services/core/java/com/android/server/connectivity/MockableSystemProperties.java @@ -19,7 +19,20 @@ package com.android.server.connectivity; import android.os.SystemProperties; public class MockableSystemProperties { + + public String get(String key) { + return SystemProperties.get(key); + } + + public int getInt(String key, int def) { + return SystemProperties.getInt(key, def); + } + public boolean getBoolean(String key, boolean def) { return SystemProperties.getBoolean(key, def); } + + public void set(String key, String value) { + SystemProperties.set(key, value); + } } diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java index 7b9c60ca6ef3..214cfced8a3e 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 @@ package com.android.server.connectivity; 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.net.metrics.IpConnectivityLog; 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 @@ public class NetdEventListenerService extends INetdEventListener.Stub { 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 @@ public class NetdEventListenerService extends INetdEventListener.Stub { 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 SparseArray<DnsEvent> mDnsEvents = new SparseArray<>(); @GuardedBy("this") - private final SortedMap<Integer, DnsEventBatch> mEventBatches = new TreeMap<>(); + 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 class NetdEventListenerService extends INetdEventListener.Stub { } 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 @@ public class NetdEventListenerService extends INetdEventListener.Stub { 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 @@ public class NetdEventListenerService extends INetdEventListener.Stub { 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 class NetdEventListenerService extends INetdEventListener.Stub { } 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 class NetdEventListenerService extends INetdEventListener.Stub { } 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 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(); } - private ConnectStats makeConnectStats() { - return new ConnectStats(mConnectTb, CONNECT_LATENCY_MAXIMUM_RECORDS); + 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 d5918585b60d..d3c74e6d755a 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.InetAddress; 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { // 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { } } - 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { // 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 @@ public class NetworkMonitor extends StateMachine { // 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 @@ public class NetworkMonitor extends StateMachine { } 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 @@ public class NetworkMonitor extends StateMachine { 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 @@ public class NetworkMonitor extends StateMachine { } 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/AuthenticationClient.java b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java index 552f0d1f8b17..fe498135feba 100644 --- a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java +++ b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java @@ -36,6 +36,7 @@ public abstract class AuthenticationClient extends ClientMonitor { public abstract boolean handleFailedAttempt(); public abstract void resetFailedAttempts(); + private boolean mAlreadyCancelled; public AuthenticationClient(Context context, long halDeviceId, IBinder token, IFingerprintServiceReceiver receiver, int targetUserId, int groupId, long opId, @@ -129,6 +130,10 @@ public abstract class AuthenticationClient extends ClientMonitor { @Override public int stop(boolean initiatedByClient) { + if (mAlreadyCancelled) { + Slog.w(TAG, "stopAuthentication: already cancelled!"); + return 0; + } IBiometricsFingerprint daemon = getFingerprintDaemon(); if (daemon == null) { Slog.w(TAG, "stopAuthentication: no fingerprint HAL!"); @@ -145,6 +150,7 @@ public abstract class AuthenticationClient extends ClientMonitor { Slog.e(TAG, "stopAuthentication failed", e); return ERROR_ESRCH; } + mAlreadyCancelled = true; return 0; // success } diff --git a/services/core/java/com/android/server/fingerprint/EnumerateClient.java b/services/core/java/com/android/server/fingerprint/EnumerateClient.java index 34f245f19d12..1b8b89c8bc37 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 abstract class EnumerateClient extends ClientMonitor { 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 @@ public abstract class EnumerateClient extends ClientMonitor { @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 85f7056ba1ad..9b984c1c8ea7 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.HashMap; 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 @@ import java.util.concurrent.CopyOnWriteArrayList; 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 @@ public class FingerprintService extends SystemService implements IHwBinder.Death 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 @@ public class FingerprintService extends SystemService implements IHwBinder.Death + (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 @@ public class FingerprintService extends SystemService implements IHwBinder.Death 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 @@ public class FingerprintService extends SystemService implements IHwBinder.Death // 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 @@ public class FingerprintService extends SystemService implements IHwBinder.Death } } + 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 @@ public class FingerprintService extends SystemService implements IHwBinder.Death } 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 @@ public class FingerprintService extends SystemService implements IHwBinder.Death void handleUserSwitching(int userId) { updateActiveGroup(userId, null); + doFingerprintCleanup(userId); } private void removeClient(ClientMonitor client) { @@ -431,7 +533,15 @@ public class FingerprintService extends SystemService implements IHwBinder.Death 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 @@ public class FingerprintService extends SystemService implements IHwBinder.Death } 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 @@ public class FingerprintService extends SystemService implements IHwBinder.Death 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 @@ public class FingerprintService extends SystemService implements IHwBinder.Death 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 000000000000..f4d2596c85bf --- /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 000000000000..19f61feac1f4 --- /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 ab1b97284998..6610634c6759 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 @@ public abstract class RemovalClient extends ClientMonitor { @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 655abd73e6ad..34ba753b3daa 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 @@ public interface JobCompletedListener { * 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 cd3ba4c8b1f3..d01de3c9157d 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.JobParameters; 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 @@ public final class JobSchedulerService extends com.android.server.SystemService 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 @@ public final class JobSchedulerService extends com.android.server.SystemService } } 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 @@ public final class JobSchedulerService extends com.android.server.SystemService } // 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 @@ public final class JobSchedulerService extends com.android.server.SystemService } 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 @@ public final class JobSchedulerService extends com.android.server.SystemService } } - 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 @@ public final class JobSchedulerService extends com.android.server.SystemService * {@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 @@ public final class JobSchedulerService extends com.android.server.SystemService * 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 @@ public final class JobSchedulerService extends com.android.server.SystemService * * @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 @@ public final class JobSchedulerService extends com.android.server.SystemService 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 @@ public final class JobSchedulerService extends com.android.server.SystemService * @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 @@ public final class JobSchedulerService extends com.android.server.SystemService // 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 @@ public final class JobSchedulerService extends com.android.server.SystemService if (job.hasIdleConstraint()) { idleCount++; } - if (job.hasConnectivityConstraint() || job.hasUnmeteredConstraint() - || job.hasNotRoamingConstraint()) { + if (job.hasConnectivityConstraint()) { connectivityCount++; } if (job.hasChargingConstraint()) { @@ -1410,7 +1411,7 @@ public final class JobSchedulerService extends com.android.server.SystemService Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs."); } assignJobsToContextsLocked(); - reportActive(); + reportActiveLocked(); } } } @@ -1698,7 +1699,37 @@ public final class JobSchedulerService extends com.android.server.SystemService 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 @@ public final class JobSchedulerService extends com.android.server.SystemService 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 728ed72d2151..c7ef0e26971f 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.JobInfo; 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 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne 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 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne mParams = null; mExecutionStartTimeElapsed = 0L; mVerb = VERB_FINISHED; - removeOpTimeOut(); + removeOpTimeOutLocked(); return false; } try { @@ -297,6 +297,38 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne 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 class JobServiceContext extends IJobCallback.Stub implements ServiceConne 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 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne } } + 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 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne } 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 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne handleCancelH(); return; } - scheduleOpTimeOut(); + scheduleOpTimeOutLocked(); break; default: Slog.e(TAG, "Handling started job but job wasn't starting! Was " @@ -587,7 +640,7 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne * 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 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne } 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 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne 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 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne * 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 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne } - 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 c0264df9c66c..2e6cd3febd2d 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 @@ public class JobStore { */ 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 @@ public class JobStore { 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 @@ public class JobStore { 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 b458d8b72ade..5ebcc93cda09 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 @@ public class ConnectivityController extends StateController implements @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 @@ public class ConnectivityController extends StateController implements @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 @@ public class ConnectivityController extends StateController implements && 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 @@ public class ConnectivityController extends StateController implements + " for " + jobStatus + ": usable=" + connectionUsable + " connected=" + connected + " validated=" + validated + + " metered=" + metered + " unmetered=" + unmetered + " notRoaming=" + notRoaming); } @@ -244,9 +245,10 @@ public class ConnectivityController extends StateController implements 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 5d209fc14b5c..29f0e2c3b957 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 @@ public class ContentObserverController extends StateController { && 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 @@ public class ContentObserverController extends StateController { } @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 d27d0e582cc5..e8cc078b7eb1 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 @@ package com.android.server.job.controllers; 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.Slog; import android.util.TimeUtils; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.Arrays; /** @@ -66,6 +68,11 @@ public final class JobStatus { 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 final class JobStatus { 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 @@ public final class JobStatus { this.numFailures = numFailures; int requiredConstraints = job.getConstraintFlags(); - if (job.getNetworkType() == JobInfo.NETWORK_TYPE_ANY) { - requiredConstraints |= CONSTRAINT_CONNECTIVITY; - } - if (job.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED) { - requiredConstraints |= CONSTRAINT_UNMETERED; - } - if (job.getNetworkType() == JobInfo.NETWORK_TYPE_NOT_ROAMING) { - requiredConstraints |= CONSTRAINT_NOT_ROAMING; + + 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 (earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME) { requiredConstraints |= CONSTRAINT_TIMING_DELAY; } @@ -256,7 +284,59 @@ public final class JobStatus { 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 final class JobStatus { } } - 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 final class JobStatus { } } - public boolean isPrepared() { + public boolean isPreparedLocked() { return prepared; } @@ -405,15 +485,24 @@ public final class JobStatus { 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 @@ public final class JobStatus { 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 @@ public final class JobStatus { } } } + 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 1721fb9ac3fc..497faab8b3b4 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 @@ public abstract class StateController { /** * 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/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java index b0d8adcc122e..2f82915a459b 100644 --- a/services/core/java/com/android/server/media/MediaSessionStack.java +++ b/services/core/java/com/android/server/media/MediaSessionStack.java @@ -23,6 +23,7 @@ import android.os.Debug; import android.os.UserHandle; import android.util.IntArray; import android.util.Log; +import android.util.SparseArray; import java.io.PrintWriter; import java.util.ArrayList; @@ -38,7 +39,7 @@ class MediaSessionStack { private static final String TAG = "MediaSessionStack"; /** - * Listens the change in the media button session. + * Listen the change in the media button session. */ interface OnMediaButtonSessionChangedListener { /** @@ -85,7 +86,12 @@ class MediaSessionStack { private MediaSessionRecord mCachedDefault; private MediaSessionRecord mCachedVolumeDefault; - private ArrayList<MediaSessionRecord> mCachedActiveList; + + /** + * Cache the result of the {@link #getActiveSessions} per user. + */ + private final SparseArray<ArrayList<MediaSessionRecord>> mCachedActiveLists = + new SparseArray<>(); MediaSessionStack(AudioPlaybackMonitor monitor, OnMediaButtonSessionChangedListener listener) { mAudioPlaybackMonitor = monitor; @@ -99,7 +105,7 @@ class MediaSessionStack { */ public void addSession(MediaSessionRecord record) { mSessions.add(record); - clearCache(); + clearCache(record.getUserId()); // Update the media button session. // The added session could be the session from the package with the audio playback. @@ -119,7 +125,7 @@ class MediaSessionStack { // in the media button session app. onMediaSessionChangeInMediaButtonSessionApp(); } - clearCache(); + clearCache(record.getUserId()); } /** @@ -140,7 +146,7 @@ class MediaSessionStack { if (shouldUpdatePriority(oldState, newState)) { mSessions.remove(record); mSessions.add(0, record); - clearCache(); + clearCache(record.getUserId()); } else if (!MediaSession.isActiveState(newState)) { // Just clear the volume cache when a state goes inactive mCachedVolumeDefault = null; @@ -163,7 +169,7 @@ class MediaSessionStack { public void onSessionStateChange(MediaSessionRecord record) { // For now just clear the cache. Eventually we'll selectively clear // depending on what changed. - clearCache(); + clearCache(record.getUserId()); } /** @@ -245,14 +251,17 @@ class MediaSessionStack { * Get the current priority sorted list of active sessions. The most * important session is at index 0 and the least important at size - 1. * - * @param userId The user to check. + * @param userId The user to check. It can be {@link UserHandle#USER_ALL} to get all sessions + * for all users in this {@link MediaSessionStack}. * @return All the active sessions in priority order. */ public ArrayList<MediaSessionRecord> getActiveSessions(int userId) { - if (mCachedActiveList == null) { - mCachedActiveList = getPriorityList(true, userId); + ArrayList<MediaSessionRecord> cachedActiveList = mCachedActiveLists.get(userId); + if (cachedActiveList == null) { + cachedActiveList = getPriorityList(true, userId); + mCachedActiveLists.put(userId, cachedActiveList); } - return mCachedActiveList; + return cachedActiveList; } /** @@ -382,9 +391,12 @@ class MediaSessionStack { return false; } - private void clearCache() { + private void clearCache(int userId) { mCachedDefault = null; mCachedVolumeDefault = null; - mCachedActiveList = null; + mCachedActiveLists.remove(userId); + // mCachedActiveLists may also include the list of sessions for UserHandle.USER_ALL, + // so they also need to be cleared. + mCachedActiveLists.remove(UserHandle.USER_ALL); } } diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 2e499f175650..9157c4e8f2ca 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // 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 2fab2887c28e..c28fb67d6c2d 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 class ConditionProviders extends ManagedServices { 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 0774779a4cf2..90e9b927a4c7 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 @@ abstract public class ManagedServices { // 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 public class ManagedServices { 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 d6c89a41dc32..63647ffa2193 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.BroadcastReceiver; 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 @@ public class NotificationComparator @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 @@ public class NotificationComparator 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 @@ public class NotificationComparator if (record.getImportance() < NotificationManager.IMPORTANCE_LOW) { return false; } - // TODO: add whitelist return isCall(record) || isMediaNotification(record); } @@ -153,8 +147,7 @@ public class NotificationComparator } 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 d6e82319d180..f334ba41bdf1 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 @@ package com.android.server.notification; 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.PendingIntent; 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.Looper; 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.MetricsLogger; 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 @@ public class NotificationManagerService extends SystemService { Vibrator mVibrator; private WindowManagerInternal mWindowManagerInternal; private AlarmManager mAlarmManager; + private ICompanionDeviceManager mCompanionManager; final IBinder mForegroundToken = new Binder(); private Handler mHandler; @@ -1004,7 +1014,8 @@ public class NotificationManagerService extends SystemService { // 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 @@ public class NotificationManagerService extends SystemService { 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 @@ public class NotificationManagerService extends SystemService { @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 @@ public class NotificationManagerService extends SystemService { 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 @@ public class NotificationManagerService extends SystemService { } 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 @@ public class NotificationManagerService extends SystemService { && 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); } } } @@ -1626,6 +1647,8 @@ public class NotificationManagerService extends SystemService { 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(); } @@ -1639,6 +1662,9 @@ public class NotificationManagerService extends SystemService { 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(); } @@ -1674,12 +1700,16 @@ public class NotificationManagerService extends SystemService { @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(); } @@ -1692,16 +1722,28 @@ public class NotificationManagerService extends SystemService { } @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 @@ -1709,7 +1751,7 @@ public class NotificationManagerService extends SystemService { NotificationChannel channel) { enforceSystemOrSystemUI("Caller not system or systemui"); Preconditions.checkNotNull(channel); - updateNotificationChannelInt(pkg, uid, channel); + updateNotificationChannelInt(pkg, uid, channel, false); } @Override @@ -2646,6 +2688,47 @@ public class NotificationManagerService extends SystemService { 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) { @@ -2988,32 +3071,34 @@ public class NotificationManagerService extends SystemService { public void removeForegroundServiceFlagFromNotification(String pkg, int notificationId, int userId) { checkCallerIsSystem(); - synchronized (mNotificationLock) { - mHandler.post(new Runnable() { - @Override - public void run() { - NotificationRecord r = - findNotificationLocked(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 */); - 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); } }; @@ -4445,11 +4530,11 @@ public class NotificationManagerService extends SystemService { return (appid == Process.SYSTEM_UID || appid == Process.PHONE_UID || uid == 0); } - private boolean isCallerSystem() { + protected boolean isCallerSystem() { return isUidSystem(Binder.getCallingUid()); } - protected void checkCallerIsSystem() { + private void checkCallerIsSystem() { if (isCallerSystem()) { return; } @@ -4578,6 +4663,38 @@ public class NotificationManagerService extends SystemService { 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; @@ -4664,10 +4781,9 @@ public class NotificationManagerService extends SystemService { 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; @@ -4703,7 +4819,7 @@ public class NotificationManagerService extends SystemService { 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 @@ -4724,7 +4840,7 @@ public class NotificationManagerService extends SystemService { } public boolean isEnabled() { - return !mServices.isEmpty(); + return !getServices().isEmpty(); } } @@ -4804,7 +4920,7 @@ public class NotificationManagerService extends SystemService { // 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. @@ -4843,7 +4959,7 @@ public class NotificationManagerService extends SystemService { // 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; } @@ -4861,7 +4977,7 @@ public class NotificationManagerService extends SystemService { * 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; } @@ -4876,7 +4992,7 @@ public class NotificationManagerService extends SystemService { } public void notifyListenerHintsChangedLocked(final int hints) { - for (final ManagedServiceInfo serviceInfo : mServices) { + for (final ManagedServiceInfo serviceInfo : getServices()) { if (!serviceInfo.isEnabledForCurrentProfiles()) { continue; } @@ -4890,7 +5006,7 @@ public class NotificationManagerService extends SystemService { } public void notifyInterruptionFilterChanged(final int interruptionFilter) { - for (final ManagedServiceInfo serviceInfo : mServices) { + for (final ManagedServiceInfo serviceInfo : getServices()) { if (!serviceInfo.isEnabledForCurrentProfiles()) { continue; } @@ -4903,6 +5019,50 @@ public class NotificationManagerService extends SystemService { } } + 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; @@ -4957,13 +5117,35 @@ public class NotificationManagerService extends SystemService { } } + 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 b043230e55df..b48fd5c75574 100644 --- a/services/core/java/com/android/server/notification/NotificationRecord.java +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -172,7 +172,7 @@ public final class NotificationRecord { final boolean useDefaultSound = (n.defaults & Notification.DEFAULT_SOUND) != 0; if (useDefaultSound) { sound = Settings.System.DEFAULT_NOTIFICATION_URI; - } else if (n.sound != null) { + } else { sound = n.sound; } } @@ -376,7 +376,20 @@ public final class NotificationRecord { 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 b789d5cd602e..221b2bb0886a 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 @@ public class RankingHelper implements RankingConfig { 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 @@ public class RankingHelper implements RankingConfig { 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 @@ public class RankingHelper implements RankingConfig { 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)); - } - 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)); + 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; } - out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(r.showBadge)); + 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)); - if (!forBackup) { - out.attribute(null, ATT_UID, Integer.toString(r.uid)); - } + if (!forBackup) { + out.attribute(null, ATT_UID, Integer.toString(r.uid)); + } - for (NotificationChannelGroup group : r.groups.values()) { - group.writeXml(out); - } + for (NotificationChannelGroup group : r.groups.values()) { + group.writeXml(out); + } - for (NotificationChannel channel : r.channels.values()) { - if (!forBackup || (forBackup && !channel.isDeleted())) { - channel.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_PACKAGE); + } } } out.endTag(null, TAG_RANKING); @@ -570,10 +577,6 @@ public class RankingHelper implements RankingConfig { 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 @@ public class RankingHelper implements RankingConfig { 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 @@ public class RankingHelper implements RankingConfig { 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 @@ public class RankingHelper implements RankingConfig { 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 @@ public class RankingHelper implements RankingConfig { } 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)); - } - 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()); + 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 } - } catch (JSONException e) { - // pass + records.put(record); } - records.put(record); } } try { @@ -944,15 +951,18 @@ public class RankingHelper implements RankingConfig { } 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 @@ public class RankingHelper implements RankingConfig { 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 @@ public class RankingHelper implements RankingConfig { 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 @@ public class RankingHelper implements RankingConfig { 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 818c3ad9728b..0e1f48507423 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.FileOutputStream; 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; @@ -754,12 +755,17 @@ public final class OverlayManagerService extends SystemService { // 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); @@ -767,13 +773,6 @@ public final class OverlayManagerService extends SystemService { } } - 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 { diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index b2036741efcb..5196c66f8ab4 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -109,6 +109,10 @@ final class OverlayManagerServiceImpl { 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 { diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java index 72979f69a47d..2f837932d76f 100644 --- a/services/core/java/com/android/server/om/OverlayManagerSettings.java +++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java @@ -16,11 +16,15 @@ package com.android.server.om; +import static com.android.server.om.OverlayManagerService.DEBUG; +import static com.android.server.om.OverlayManagerService.TAG; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.om.OverlayInfo; import android.util.AndroidRuntimeException; import android.util.ArrayMap; +import android.util.Slog; import android.util.Xml; import com.android.internal.util.FastXmlSerializer; @@ -185,6 +189,10 @@ final class OverlayManagerSettings { for (int i = 0; i < mItems.size(); i++) { final SettingsItem item = mItems.get(i); 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--; diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java index 498181b5179e..7b865429d0d7 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 class OtaDexoptService extends IOtaDexopt.Stub { 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 @@ public class OtaDexoptService extends IOtaDexopt.Stub { 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 @@ public class OtaDexoptService extends IOtaDexopt.Stub { 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 @@ public class OtaDexoptService extends IOtaDexopt.Stub { // 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 71f700cb6060..e79f46b4f3be 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.app.IntentForwarderActivity.FORWARD_INTENT_TO 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.PermissionGroupInfo; 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; @@ -222,6 +220,7 @@ import android.text.format.DateUtils; 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; @@ -273,7 +272,6 @@ import com.android.server.SystemConfig; 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; @@ -299,7 +297,6 @@ import java.io.ByteArrayOutputStream; 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; @@ -1836,6 +1833,10 @@ public class PackageManagerService extends IPackageManager.Stub { 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*/, @@ -2726,15 +2727,18 @@ public class PackageManagerService extends IPackageManager.Stub { 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; } @@ -2755,6 +2759,7 @@ public class PackageManagerService extends IPackageManager.Stub { count++; } } + traceLog.traceEnd(); Slog.i(TAG, "Deferred reconcileAppsData finished " + count + " packages"); }, "prepareAppData"); @@ -5725,9 +5730,6 @@ public class PackageManagerService extends IPackageManager.Stub { 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; } @@ -6338,19 +6340,24 @@ public class PackageManagerService extends IPackageManager.Stub { 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); } @@ -7092,17 +7099,23 @@ public class PackageManagerService extends IPackageManager.Stub { // 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(); @@ -7189,6 +7202,7 @@ public class PackageManagerService extends IPackageManager.Stub { 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(); @@ -7202,9 +7216,33 @@ public class PackageManagerService extends IPackageManager.Stub { 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; } @@ -7213,17 +7251,67 @@ public class PackageManagerService extends IPackageManager.Stub { 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(); @@ -7555,17 +7643,38 @@ public class PackageManagerService extends IPackageManager.Stub { 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; } } @@ -12769,8 +12878,26 @@ public class PackageManagerService extends IPackageManager.Stub { 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; } @@ -13268,8 +13395,10 @@ public class PackageManagerService extends IPackageManager.Stub { // 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) { @@ -17775,8 +17904,8 @@ public class PackageManagerService extends IPackageManager.Stub { } } if (removedAppId >= 0) { - sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, 0, null, null, - broadcastUsers); + sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, + Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, null, null, broadcastUsers); } } } @@ -20179,14 +20308,14 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); public void onChange(boolean selfChange) { mEphemeralAppsDisabled = (Global.getInt(resolver, Global.ENABLE_EPHEMERAL_FEATURE, 1) == 0) || - (Secure.getInt(resolver, Secure.WEB_ACTION_ENABLED, 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.WEB_ACTION_ENABLED), false, co, UserHandle.USER_SYSTEM); + .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 @@ -23352,7 +23481,6 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); intent, resolvedType, flags, userId, callingUid, true /*includeInstantApps*/); } - @Override public void addIsolatedUid(int isolatedUid, int ownerUid) { synchronized (mPackages) { @@ -23508,4 +23636,10 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); public ComponentName getInstantAppResolverSettingsComponent() { return mInstantAppResolverSettingsComponent; } + + @Override + public ComponentName getInstantAppInstallerComponent() { + return mInstantAppInstallerActivity == null + ? null : mInstantAppInstallerActivity.getComponentName(); + } } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 95fb5af37b60..4f29bfa2829e 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.content.res.TypedArray; 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.accessibility.AccessibilityManager; 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 @@ public class PhoneWindowManager implements WindowManagerPolicy { + overrideConfig + " to starting window resId=" + resId); context = overrideContext; } + typedArray.recycle(); } final PhoneWindow win = new PhoneWindow(context); @@ -2868,6 +2871,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } params.setTitle("Splash Screen " + packageName); + addSplashscreenContent(win, context); + wm = (WindowManager) context.getSystemService(WINDOW_SERVICE); view = win.getDecorView(); @@ -2898,6 +2903,24 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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 @@ public class PhoneWindowManager implements WindowManagerPolicy { @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); diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index a60dae7c7914..cf597b052c10 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.PowerManagerInternal; 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 @@ public final class PowerManagerService extends SystemService } 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 000000000000..46115d8edd23 --- /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 8c317310fb6d..896977141702 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 @@ package com.android.server.search; 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.Context; 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.RemoteException; 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 @@ public class SearchManagerService extends ISearchManager.Stub { } } - 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 @@ public class SearchManagerService extends ISearchManager.Stub { @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 @@ public class SearchManagerService extends ISearchManager.Stub { 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 be91f48fb76f..25a0772efd7f 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 @@ public final class TvInputManagerService extends SystemService { } @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 @@ public final class TvInputManagerService extends SystemService { } @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 e26914e5293d..bde2111217f1 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 class AppWindowContainerController 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 @@ public class AppWindowContainerController 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 @@ public class AppWindowContainerController 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; @@ -612,13 +615,13 @@ public class AppWindowContainerController } } - 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 @@ public class AppWindowContainerController @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 a8664a5727ab..1fb34eb66d20 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 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree * 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 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree 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 2811145bcf5f..f41eed53cbca 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.AnimationUtils; import android.view.animation.Interpolator; import android.view.WindowManagerInternal; +import com.android.internal.annotations.VisibleForTesting; + /** * Enables animating bounds of objects. * @@ -103,7 +105,8 @@ public class BoundsAnimationController { 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 @@ public class BoundsAnimationController { 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 @@ public class BoundsAnimationController { // 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 class BoundsAnimationController { 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 @@ public class BoundsAnimationController { 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 @@ public class BoundsAnimationController { 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 class BoundsAnimationController { 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 @@ public class BoundsAnimationController { */ 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 @@ public class BoundsAnimationController { 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 @@ public class BoundsAnimationController { : 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 2f64cd42e668..182361015a05 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -125,6 +125,7 @@ import android.view.Surface; import android.view.SurfaceControl; import android.view.WindowManagerPolicy; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ToBooleanFunction; import com.android.internal.view.IInputMethodClient; @@ -1396,6 +1397,22 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return null; } + @VisibleForTesting + int getStackCount() { + return mTaskStackContainers.size(); + } + + @VisibleForTesting + int getStaskPosById(int stackId) { + for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { + final TaskStack stack = mTaskStackContainers.get(i); + if (stack.mStackId == stackId) { + return i; + } + } + return -1; + } + @Override void onConfigurationChanged(Configuration newParentConfig) { super.onConfigurationChanged(newParentConfig); @@ -1420,6 +1437,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo 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 @@ -3267,8 +3291,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo : requestedPosition >= topChildPosition; int targetPosition = requestedPosition; - if (toTop && isStackVisible(PINNED_STACK_ID) && stack.mStackId != PINNED_STACK_ID) { - // The pinned stack is always the top most stack (always-on-top) when it is visible. + if (toTop && stack.mStackId != PINNED_STACK_ID + && getStackById(PINNED_STACK_ID) != null) { + // The pinned stack is always the top most stack (always-on-top) when it is present. TaskStack topStack = mChildren.get(topChildPosition); if (topStack.mStackId != PINNED_STACK_ID) { throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren); diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java index 3ce61f027b4c..16848780fe47 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 @@ class PinnedStackController { void onConfigurationChanged() { reloadResources(); - notifyMovementBoundsChanged(false /* fromImeAdjustment */); } /** @@ -241,13 +240,31 @@ class PinnedStackController { } /** + * 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 @@ class PinnedStackController { notifyMovementBoundsChanged(false /* fromImeAdjustment */); outBounds.set(postChangeStackBounds); + return true; } /** @@ -371,7 +389,7 @@ class PinnedStackController { 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 0145454d5ce1..135832e619a4 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 @@ public class PinnedStackWindowController extends StackWindowController { 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 @@ public class PinnedStackWindowController extends StackWindowController { 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 @@ public class PinnedStackWindowController extends StackWindowController { } 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 @@ public class PinnedStackWindowController extends StackWindowController { /** * @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 @@ public class PinnedStackWindowController extends StackWindowController { } 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 000000000000..12b9c1f0c552 --- /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/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java index bf024cfdd7c3..b927e670bc28 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 @@ public class StackWindowController } } - /** 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 a55f9dfa2d60..c763c175687f 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 @@ public interface StackWindowListener extends WindowContainerListener { /** 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 b816d8199aa6..4262d124ed0a 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -184,7 +184,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU 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); @@ -195,7 +195,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU 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(); @@ -595,8 +595,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU * 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/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index 48b01f40fc65..fbb826d5cb48 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -162,12 +162,15 @@ class TaskSnapshotController { 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; } - final WindowState mainWindow = top.findMainWindow(); return new TaskSnapshot(buffer, top.getConfiguration().orientation, minRect(mainWindow.mContentInsets, mainWindow.mStableInsets), false /* reduced */, 1f /* scale */); diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 1a67ac73021d..d7c41d335b72 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 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye /** 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 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye // 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 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye 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 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye } /** - * 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 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye } /** - * @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 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye // 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 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye 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 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye 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 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye } } - @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) { + public boolean setPinnedStackSize(Rect bounds, Rect tempTaskBounds) { + if (mCancelCurrentBoundsAnimation) { + return false; } - return true; - } - public boolean setPinnedStackSize(Rect bounds, Rect tempTaskBounds) { try { mService.mActivityManager.resizePinnedStack(bounds, tempTaskBounds); } catch (RemoteException e) { @@ -1469,8 +1474,10 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye @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 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye @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 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye 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 efc2e117b02d..9f0248517e88 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 class TaskWindowContainerController } } - 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 @@ public class TaskWindowContainerController 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 0f4707e56164..0049585f5c52 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.SHELL_UID; 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.ParcelFileDescriptor; 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 8098eeaa3c11..0b96f3fbc1fc 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.PRIVATE_FLAG_WILL_NOT_REPL 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 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // 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 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP 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 a7f6db169594..fa353367c6e4 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 @@ class WindowStateAnimator { } // 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 @@ class WindowStateAnimator { 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 @@ class WindowStateAnimator { + "," + 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 adf4501e9714..edbdf8bc5ed9 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 @@ class WindowSurfaceController { } } - 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 @@ class WindowSurfaceController { 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 @@ class WindowSurfaceController { 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 f74512a00122..42a92327bd4e 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -981,6 +981,11 @@ public final class SystemServer { 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 @@ public final class SystemServer { 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 @@ public final class SystemServer { 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/print/java/com/android/server/print/CompanionDeviceManagerService.java b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java index d0dfc6cc4fe8..122a954b4d30 100644 --- a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java +++ b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java @@ -17,12 +17,15 @@ package com.android.server.print; +import static com.android.internal.util.CollectionUtils.size; import static com.android.internal.util.Preconditions.checkArgument; import static com.android.internal.util.Preconditions.checkNotNull; +import static com.android.internal.util.Preconditions.checkState; import android.Manifest; import android.annotation.CheckResult; import android.annotation.Nullable; +import android.app.PendingIntent; import android.companion.AssociationRequest; import android.companion.CompanionDeviceManager; import android.companion.ICompanionDeviceDiscoveryService; @@ -46,13 +49,18 @@ import android.os.Parcel; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; +import android.provider.Settings; +import android.provider.SettingsStringUtil.ComponentNameSet; +import android.text.BidiFormatter; import android.util.AtomicFile; import android.util.ExceptionUtils; +import android.util.Log; import android.util.Slog; import android.util.Xml; import com.android.internal.app.IAppOpsService; import com.android.internal.content.PackageMonitor; +import com.android.internal.notification.NotificationAccessConfirmationActivityContract; import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.server.FgThread; @@ -79,6 +87,7 @@ import java.util.function.Function; //TODO schedule stopScan on activity destroy(except if configuration change) //TODO on associate called again after configuration change -> replace old callback with new //TODO avoid leaking calling activity in IFindDeviceCallback (see PrintManager#print for example) +//TODO check user-feature present in manifest on API calls /** @hide */ public class CompanionDeviceManagerService extends SystemService implements Binder.DeathRecipient { @@ -140,10 +149,10 @@ public class CompanionDeviceManagerService extends SystemService implements Bind @Override public void binderDied() { - Handler.getMain().post(this::handleBinderDied); + Handler.getMain().post(this::cleanup); } - private void handleBinderDied() { + private void cleanup() { mServiceConnection = unbind(mServiceConnection); mFindDeviceCallback = unlinkToDeath(mFindDeviceCallback, this, 0); } @@ -207,7 +216,6 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } } - @Override public List<String> getAssociations(String callingPackage, int userId) throws RemoteException { @@ -217,12 +225,13 @@ public class CompanionDeviceManagerService extends SystemService implements Bind a -> a.deviceAddress); } + //TODO also revoke notification access @Override public void disassociate(String deviceMacAddress, String callingPackage) throws RemoteException { checkNotNull(deviceMacAddress); checkCallerIsSystemOr(callingPackage); - updateAssociations(associations -> ArrayUtils.remove(associations, + updateAssociations(associations -> CollectionUtils.remove(associations, new Association(getCallingUserId(), deviceMacAddress, callingPackage))); } @@ -237,11 +246,49 @@ public class CompanionDeviceManagerService extends SystemService implements Bind checkArgument(getCallingUserId() == userId, "Must be called by either same user or system"); - mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg); } + + @Override + public PendingIntent requestNotificationAccess(ComponentName component) + throws RemoteException { + String callingPackage = component.getPackageName(); + checkCanCallNotificationApi(callingPackage); + int userId = getCallingUserId(); + String packageTitle = BidiFormatter.getInstance().unicodeWrap( + getPackageInfo(callingPackage, userId) + .applicationInfo + .loadSafeLabel(getContext().getPackageManager()) + .toString()); + long identity = Binder.clearCallingIdentity(); + try { + return PendingIntent.getActivity(getContext(), + 0 /* request code */, + NotificationAccessConfirmationActivityContract.launcherIntent( + userId, component, packageTitle), + PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT + | PendingIntent.FLAG_CANCEL_CURRENT); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override + public boolean hasNotificationAccess(ComponentName component) throws RemoteException { + checkCanCallNotificationApi(component.getPackageName()); + String setting = Settings.Secure.getString(getContext().getContentResolver(), + Settings.Secure.ENABLED_NOTIFICATION_LISTENERS); + return new ComponentNameSet(setting).contains(component); + } + + private void checkCanCallNotificationApi(String callingPackage) throws RemoteException { + checkCallerIsSystemOr(callingPackage); + checkState(!ArrayUtils.isEmpty(readAllAssociations(getCallingUserId(), callingPackage)), + "App must have an association before calling this API"); + } } + private int getCallingUserId() { return UserHandle.getUserId(Binder.getCallingUid()); } @@ -263,7 +310,7 @@ public class CompanionDeviceManagerService extends SystemService implements Bind mFindDeviceCallback.asBinder().linkToDeath( CompanionDeviceManagerService.this, 0); } catch (RemoteException e) { - handleBinderDied(); + cleanup(); return; } try { @@ -291,10 +338,26 @@ public class CompanionDeviceManagerService extends SystemService implements Bind return new ICompanionDeviceDiscoveryServiceCallback.Stub() { @Override + public boolean onTransact(int code, Parcel data, Parcel reply, int flags) + throws RemoteException { + try { + return super.onTransact(code, data, reply, flags); + } catch (Throwable e) { + Slog.e(LOG_TAG, "Error during IPC", e); + throw ExceptionUtils.propagate(e, RemoteException.class); + } + } + + @Override public void onDeviceSelected(String packageName, int userId, String deviceAddress) { - //TODO unbind updateSpecialAccessPermissionForAssociatedPackage(packageName, userId); recordAssociation(packageName, deviceAddress); + cleanup(); + } + + @Override + public void onDeviceSelectionCancel() { + cleanup(); } }; } @@ -345,22 +408,29 @@ public class CompanionDeviceManagerService extends SystemService implements Bind } private void recordAssociation(String priviledgedPackage, String deviceAddress) { - updateAssociations((associations) -> ArrayUtils.add(associations, - new Association(getCallingUserId(), deviceAddress, priviledgedPackage))); + if (DEBUG) { + Log.i(LOG_TAG, "recordAssociation(priviledgedPackage = " + priviledgedPackage + + ", deviceAddress = " + deviceAddress + ")"); + } + int userId = getCallingUserId(); + updateAssociations(associations -> CollectionUtils.add(associations, + new Association(userId, deviceAddress, priviledgedPackage))); } - private void updateAssociations(Function<ArrayList<Association>, List<Association>> update) { + private void updateAssociations(Function<List<Association>, List<Association>> update) { updateAssociations(update, getCallingUserId()); } - private void updateAssociations(Function<ArrayList<Association>, List<Association>> update, + private void updateAssociations(Function<List<Association>, List<Association>> update, int userId) { final AtomicFile file = getStorageFileForUser(userId); synchronized (file) { - final ArrayList<Association> old = readAllAssociations(userId); - final List<Association> associations = update.apply(old); - if (Objects.equals(old, associations)) return; + List<Association> associations = readAllAssociations(userId); + final List<Association> old = CollectionUtils.copyOf(associations); + associations = update.apply(associations); + if (size(old) == size(associations)) return; + List<Association> finalAssociations = associations; file.write((out) -> { XmlSerializer xml = Xml.newSerializer(); try { @@ -369,8 +439,8 @@ public class CompanionDeviceManagerService extends SystemService implements Bind xml.startDocument(null, true); xml.startTag(null, XML_TAG_ASSOCIATIONS); - for (int i = 0; i < CollectionUtils.size(associations); i++) { - Association association = associations.get(i); + for (int i = 0; i < size(finalAssociations); i++) { + Association association = finalAssociations.get(i); xml.startTag(null, XML_TAG_ASSOCIATION) .attribute(null, XML_ATTR_PACKAGE, association.companionAppPackage) .attribute(null, XML_ATTR_DEVICE, association.deviceAddress) @@ -386,15 +456,6 @@ public class CompanionDeviceManagerService extends SystemService implements Bind }); } - - - //TODO Show dialog before recording notification access -// final SettingStringHelper setting = -// new SettingStringHelper( -// getContext().getContentResolver(), -// Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, -// getUserId()); -// setting.write(ColonDelimitedSet.OfStrings.add(setting.read(), priviledgedPackage)); } private AtomicFile getStorageFileForUser(int uid) { diff --git a/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java b/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java index d14f4eb33dc5..013eab8679a8 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 @@ public class UserInactivityCountdownDialog extends AlertDialog { @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/AndroidManifest.xml b/services/tests/notification/AndroidManifest.xml index cf050a89b0e6..99d9c7b87301 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 e28566931d23..d383aea5a679 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 @@ public class BuzzBeepBlinkTest { 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 176342be99fd..84945ab5acd3 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 @@ public class NotificationComparatorTest { private NotificationRecord mRecordContact; private NotificationRecord mRecordUrgent; private NotificationRecord mRecordCheater; + private NotificationRecord mRecordCheaterColorized; @Before @@ -174,6 +175,7 @@ public class NotificationComparatorTest { 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 @@ public class NotificationComparatorTest { 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 @@ public class NotificationComparatorTest { 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 d9214fae8d16..f666727ec1d1 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.Matchers.eq; 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,28 +38,33 @@ import static org.mockito.Mockito.when; 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; @@ -66,33 +76,47 @@ public class NotificationManagerServiceTest { private NotificationManagerService mNotificationManagerService; private INotificationManager mBinderService; private NotificationManagerInternal mInternalService; - private IPackageManager mPackageManager = mock(IPackageManager.class); - private final PackageManager mPackageManagerClient = mock(PackageManager.class); + @Mock + private IPackageManager mPackageManager; + @Mock + private PackageManager mPackageManagerClient; private Context mContext = InstrumentationRegistry.getTargetContext(); private final String PKG = mContext.getPackageName(); private TestableLooper mTestableLooper; - private final RankingHelper mRankingHelper = mock(RankingHelper.class); + @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 void checkCallerIsSystem() {} + protected boolean isCallerSystem() { + return true; + } + + @Override + protected ICompanionDeviceManager getCompanionManager() { + return null; + } } @Before - @Test @UiThreadTest public void setUp() throws Exception { + 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); @@ -100,15 +124,12 @@ public class NotificationManagerServiceTest { when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class)); // Use this testable looper. mTestableLooper = new TestableLooper(false); - // 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)); + 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, mockNotificationListeners); + mPackageManagerClient, mockLightsManager, mNotificationListeners, mCompanionMgr); // Tests call directly into the Binder. mBinderService = mNotificationManagerService.getBinderService(); @@ -419,4 +440,223 @@ public class NotificationManagerServiceTest { 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/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java index 946044d57e03..b2e6ef9f817f 100644 --- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java +++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java @@ -124,6 +124,9 @@ public class NotificationRecordTest { builder.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES); channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES); } + } else { + channel.setSound(null, null); + builder.setSound(null, null); } if (buzzy) { if (defaultVibration) { @@ -206,6 +209,18 @@ public class NotificationRecordTest { } @Test + public void testSound_noSound_preUpgrade() throws Exception { + // pre upgrade, default sound. + StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */, + false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */, + false /* lights */, false /*defaultLights */); + + NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel); + assertEquals(null, record.getSound()); + assertEquals(Notification.AUDIO_ATTRIBUTES_DEFAULT, record.getAudioAttributes()); + } + + @Test public void testSound_default_upgradeUsesChannel() throws Exception { channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES); // post upgrade, default sound. 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 885eb2ea235a..303054e77793 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 @@ public class RankingHelperTest { } @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 353199ab0b0b..985e5eaee256 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 android.net.NetworkScoreManager.CACHE_FILTER_NONE; 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.Matchers.isA; 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.ComponentName; 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.ArgumentCaptor; 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 @@ public class NetworkScoreServiceTest { @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 @@ public class NetworkScoreServiceTest { @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 @@ public class NetworkScoreServiceTest { 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 @@ public class NetworkScoreServiceTest { @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 @@ public class NetworkScoreServiceTest { @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 @@ public class NetworkScoreServiceTest { @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 @@ public class NetworkScoreServiceTest { }).when(mRecommendationProvider) .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class), anyInt()); + mNetworkScoreService.onUserUnlocked(0); final RecommendationResult result = mNetworkScoreService.requestRecommendation(mRecommendationRequest); @@ -357,7 +358,7 @@ public class NetworkScoreServiceTest { @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 @@ public class NetworkScoreServiceTest { @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 @@ public class NetworkScoreServiceTest { @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 @@ public class NetworkScoreServiceTest { @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 @@ public class NetworkScoreServiceTest { @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 @@ public class NetworkScoreServiceTest { 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 class NetworkScoreServiceTest { 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 @@ public class NetworkScoreServiceTest { 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 @@ public class NetworkScoreServiceTest { } } - // "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 @@ public class NetworkScoreServiceTest { 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 00f6273d14bf..20839c5f7a18 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 @@ public class AccountManagerServiceTest extends AndroidTestCase { @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 @@ public class AccountManagerServiceTest extends AndroidTestCase { updateBroadcastCounters(2); assertEquals(mVisibleAccountsChangedBroadcasts, 0); // broadcast was not sent assertEquals(mLoginAccountsChangedBroadcasts, 2); + assertEquals(mAccountRemovedBroadcasts, 0); } @SmallTest @@ -2533,9 +2535,10 @@ public class AccountManagerServiceTest extends AndroidTestCase { 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 @@ public class AccountManagerServiceTest extends AndroidTestCase { "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 @@ public class AccountManagerServiceTest extends AndroidTestCase { 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 000000000000..1d80b336becc --- /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 52405863e8fe..3bf0e5ff86aa 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 @@ package com.android.server.am; 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 @@ public class ActivityTestsBase { } 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 @@ public class ActivityTestsBase { 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 @@ public class ActivityTestsBase { 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 9861aa177135..cd39d8875692 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 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { 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 3c8bf206b8a6..d206407bae16 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 @@ public class AppWindowContainerControllerTests extends WindowTestsBase { 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 @@ public class AppWindowContainerControllerTests extends WindowTestsBase { 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 @@ public class AppWindowContainerControllerTests extends WindowTestsBase { // 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 000000000000..85dc7125e3cc --- /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/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java index 0270bb955988..837ce563d616 100644 --- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; @@ -289,6 +290,24 @@ public class DisplayContentTests extends WindowTestsBase { verifySizes(sDisplayContent, smallerWidth, smallerHeight, smallerDensity); } + /** + * This test enforces that the pinned stack is always kept as the top stack. + */ + @Test + public void testPinnedStackLocation() { + createStackControllerOnStackOnDisplay(PINNED_STACK_ID, sDisplayContent); + final int initialStackCount = sDisplayContent.getStackCount(); + // Ensure that the pinned stack was placed at the end + assertEquals(initialStackCount - 1, sDisplayContent.getStaskPosById(PINNED_STACK_ID)); + // By default, this should try to create a new stack on top + createTaskStackOnDisplay(sDisplayContent); + final int afterStackCount = sDisplayContent.getStackCount(); + // Make sure the stack count has increased + assertEquals(initialStackCount + 1, afterStackCount); + // Ensure that the pinned stack is still on top + assertEquals(afterStackCount - 1, sDisplayContent.getStaskPosById(PINNED_STACK_ID)); + } + private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth, int expectedBaseHeight, int expectedBaseDensity) { assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth); 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 1819c56735eb..98d20a2634ac 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 @@ public class TaskWindowContainerControllerTests extends WindowTestsBase { boolean gotException = false; try { - taskController.reparent(stackController1, 0); + taskController.reparent(stackController1, 0, false/* moveParents */); } catch (IllegalArgumentException e) { gotException = true; } @@ -100,14 +100,14 @@ public class TaskWindowContainerControllerTests extends WindowTestsBase { 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 @@ public class TaskWindowContainerControllerTests extends WindowTestsBase { (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/usb/Android.mk b/services/usb/Android.mk index f560e71ebe6a..f6d212bccd1c 100644 --- a/services/usb/Android.mk +++ b/services/usb/Android.mk @@ -8,7 +8,7 @@ LOCAL_SRC_FILES += \ $(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 01e36f57d1be..93cfd11b3d46 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 @@ class UsbProfileGroupSettingsManager { } @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 @@ class UsbProfileGroupSettingsManager { 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 @@ class UsbProfileGroupSettingsManager { 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 dc4b41c3d65a..6c4ced4326a2 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 @@ public class VoiceInteractionManagerService extends SystemService { 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 @@ public class VoiceInteractionManagerService extends SystemService { 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 1874d8d04723..0342da7aa6ef 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -112,20 +112,26 @@ public class TelecomManager { "android.telecom.action.CHANGE_PHONE_ACCOUNTS"; /** - * The {@link android.content.Intent} action used indicate that a new phone account was - * just registered. - * @hide + * {@link android.content.Intent} action used indicate that a new phone account was just + * registered. + * <p> + * The Intent {@link Intent#getExtras() extras} will contain {@link #EXTRA_PHONE_ACCOUNT_HANDLE} + * to indicate which {@link PhoneAccount} was registered. + * <p> + * Will only be sent to the default dialer app (see {@link #getDefaultDialerPackage()}). */ - @SystemApi public static final String ACTION_PHONE_ACCOUNT_REGISTERED = "android.telecom.action.PHONE_ACCOUNT_REGISTERED"; /** - * The {@link android.content.Intent} action used indicate that a phone account was - * just unregistered. - * @hide + * {@link android.content.Intent} action used indicate that a phone account was just + * unregistered. + * <p> + * The Intent {@link Intent#getExtras() extras} will contain {@link #EXTRA_PHONE_ACCOUNT_HANDLE} + * to indicate which {@link PhoneAccount} was unregistered. + * <p> + * Will only be sent to the default dialer app (see {@link #getDefaultDialerPackage()}). */ - @SystemApi public static final String ACTION_PHONE_ACCOUNT_UNREGISTERED = "android.telecom.action.PHONE_ACCOUNT_UNREGISTERED"; diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 77da89709d65..397aa0020d13 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -2710,19 +2710,12 @@ public class TelephonyManager { * @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 - } + } /** @@ -2734,19 +2727,11 @@ public class TelephonyManager { * @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; } @@ -3650,9 +3635,28 @@ public class TelephonyManager { * * @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); } /** @@ -3666,14 +3670,15 @@ public class TelephonyManager { * * @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) { } @@ -6458,5 +6463,33 @@ public class TelephonyManager { 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/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index db7e417cbcb5..dd08f67c9617 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -498,12 +498,6 @@ interface ITelephony { */ 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 @@ interface ITelephony { * * @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 @@ interface ITelephony { * @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/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java index 960a2d9fd726..20392e733599 100644 --- a/test-runner/src/android/test/mock/MockPackageManager.java +++ b/test-runner/src/android/test/mock/MockPackageManager.java @@ -1126,4 +1126,12 @@ public class MockPackageManager extends PackageManager { public ComponentName getInstantAppResolverSettingsComponent() { throw new UnsupportedOperationException(); } + + /** + * @hide + */ + @Override + public ComponentName getInstantAppInstallerComponent() { + throw new UnsupportedOperationException(); + } } 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 6fe2cfbcd8f4..fc1d47bcd20f 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 @@ public class SinkActivity extends Activity { 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 c59c95856efa..a2161028f9a6 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 @@ public class SourceActivity extends Activity { 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 64cdcf78fdcc..b381cbfbd0a9 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 000000000000..01fb6462fd95 --- /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 b8dd83039ed8..c11d2e48834a 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 000000000000..0683df6d649f --- /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 8dafac73403d..934bae03a560 100644 --- a/tests/AmSlam/Android.mk +++ b/tests/AmSlam/Android.mk @@ -21,7 +21,7 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files) 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 cce955e999f8..17fca091ac09 100644 --- a/tests/AmSlam/src/test/amslam/MainActivity.java +++ b/tests/AmSlam/src/test/amslam/MainActivity.java @@ -60,7 +60,7 @@ public class MainActivity extends Activity implements PongReceiver.PingPongRespo 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 b88a885efa43..f85e82deb0d6 100644 --- a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java +++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java @@ -75,7 +75,7 @@ public class BiDiTestActivity extends Activity { 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 1ed47230c6fc..8ccd4e2181ed 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 @@ public class AutomaticActivity extends CompareActivity { 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 8d8d9de1a249..0dec1de79a46 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 @@ abstract public class CompareActivity extends Activity { 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 78e360bdb831..723c46089d51 100644 --- a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java +++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java @@ -162,19 +162,19 @@ public class FrameworkPerfActivity extends Activity // 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 84e31aa8417e..83c27fb750e5 100644 --- a/tests/HugeBackup/src/com/android/hugebackup/HugeBackupActivity.java +++ b/tests/HugeBackup/src/com/android/hugebackup/HugeBackupActivity.java @@ -71,9 +71,9 @@ public class HugeBackupActivity extends Activity { 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 eb4e3fd00eee..492d158ec5ef 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 @@ public class DatePicker extends FrameLayout { 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 @@ public class DatePicker extends FrameLayout { 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 @@ public class DatePicker extends FrameLayout { 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 @@ public class DatePicker extends FrameLayout { } }); - 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 @@ public class DatePicker extends FrameLayout { /* 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 0defe924e6b3..134c2e045449 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 @@ public class ListActivity extends Activity { 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 5655adf878fe..262b0e93671b 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 @@ public class StackActivity extends Activity { 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 684d17944549..b5a5e025e757 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 @@ public class TransformsAndAnimationsActivity extends Activity { 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 ffb86893be73..deb8585a95f5 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 @@ public class TransparentListActivity extends Activity { 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 6d47d6c467e7..a261fb729a65 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 @@ public class ViewLayerInvalidationActivity extends Activity { 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 7168478c083c..07dc0a1b5df0 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 @@ public class ViewLayersActivity extends Activity { } 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 e65dd6331408..96cf43e48778 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 @@ public class ViewLayersActivity3 extends Activity { } 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 17f78af50edb..1f3f874744db 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 @@ public class ViewLayersActivity4 extends Activity { } 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 2dd7b6a99ce1..715da201458b 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 @@ public class ViewLayersActivity5 extends Activity { } 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 738801d8b285..9ae38119cac6 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 @@ public class ViewPropertyAlphaActivity extends Activity { 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 @@ public class ViewPropertyAlphaActivity extends Activity { } }); - 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 @@ public class ViewPropertyAlphaActivity extends Activity { 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 45e77edb03da..08979bce8f73 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 @@ public class ZOrderingActivity extends Activity { 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 292bbd22d0fc..6115fd5a0fd0 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 @@ public class AutoCompleteTextViewActivityLandscape extends Activity 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 570cb6bf8a06..253c50fe5810 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 @@ public class AutoCompleteTextViewActivityPortrait extends Activity 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 5aa0d4f35a21..51cdbb585659 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 @@ public class MainActivity extends Activity { 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 e3a9cf40b066..612c53e3e93c 100644 --- a/tests/LargeAssetTest/src/com/android/largeassettest/LargeAssetTest.java +++ b/tests/LargeAssetTest/src/com/android/largeassettest/LargeAssetTest.java @@ -43,8 +43,8 @@ public class LargeAssetTest extends Activity { 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 9f297aa13e90..c0091ad7b03f 100644 --- a/tests/LowStorageTest/src/com/android/lowstoragetest/LowStorageTest.java +++ b/tests/LowStorageTest/src/com/android/lowstoragetest/LowStorageTest.java @@ -52,9 +52,9 @@ public class LowStorageTest extends Activity { 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 @@ public class LowStorageTest extends Activity { 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 2ff3e2026cc0..85cc8fb046f2 100644 --- a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java +++ b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java @@ -68,16 +68,16 @@ public class OnePlayerActivity extends Activity { 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); - - final Button artPicker = (Button) findViewById(R.id.art_picker); + 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 = 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 ee4c8343d9e9..241206d8919b 100644 --- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java +++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java @@ -43,7 +43,7 @@ public class MainActivity extends Activity implements OnItemClickListener { 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 @@ public class MainActivity extends Activity implements OnItemClickListener { @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 892cbae50560..22fc6911f7df 100644 --- a/tests/RenderThreadTest/src/com/example/renderthread/SubActivity.java +++ b/tests/RenderThreadTest/src/com/example/renderthread/SubActivity.java @@ -39,7 +39,7 @@ public class SubActivity extends Activity { @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 4841bc59c794..c3c4cf556986 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 @@ public class SoundTriggerTestActivity extends Activity implements SoundTriggerTe 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 7c139742f54d..7632a6e3dfd6 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 @@ public class TouchLatencyActivity extends ActionBarActivity { 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 54c44e22d1b6..9985357d4577 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/ClippingText.java +++ b/tests/TransitionTests/src/com/android/transitiontests/ClippingText.java @@ -42,7 +42,7 @@ public class ClippingText extends Activity { 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 f687da37eedf..86ecf8e5f9f2 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/ContactsExpansion.java +++ b/tests/TransitionTests/src/com/android/transitiontests/ContactsExpansion.java @@ -49,7 +49,7 @@ public class ContactsExpansion extends Activity { 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 5bb0e77c08c9..0d41d647fe22 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/CrossFadeDemo.java +++ b/tests/TransitionTests/src/com/android/transitiontests/CrossFadeDemo.java @@ -38,7 +38,7 @@ public class CrossFadeDemo extends Activity { 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 1f278b9a6485..1fb732e19eb9 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/CrossfadeImage.java +++ b/tests/TransitionTests/src/com/android/transitiontests/CrossfadeImage.java @@ -41,10 +41,10 @@ public class CrossfadeImage extends Activity { 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 469ee8b28a9f..15d15351957e 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/CrossfadeMultiple.java +++ b/tests/TransitionTests/src/com/android/transitiontests/CrossfadeMultiple.java @@ -49,12 +49,12 @@ public class CrossfadeMultiple extends Activity { 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 d52ab1dc55ba..e1729045a42e 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/Demo0.java +++ b/tests/TransitionTests/src/com/android/transitiontests/Demo0.java @@ -35,7 +35,7 @@ public class Demo0 extends Activity { 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 5b5eb156bba0..e92dd039c428 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/Demo1.java +++ b/tests/TransitionTests/src/com/android/transitiontests/Demo1.java @@ -40,7 +40,7 @@ public class Demo1 extends Activity { 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 0f3257bbadad..c26723bc89e2 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/Demo2.java +++ b/tests/TransitionTests/src/com/android/transitiontests/Demo2.java @@ -38,7 +38,7 @@ public class Demo2 extends Activity { 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 0ffa1f534834..094ab97ddacb 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/Demo3.java +++ b/tests/TransitionTests/src/com/android/transitiontests/Demo3.java @@ -38,7 +38,7 @@ public class Demo3 extends Activity { 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 3aadbb0ae670..af67f26b3707 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/Demo4.java +++ b/tests/TransitionTests/src/com/android/transitiontests/Demo4.java @@ -38,7 +38,7 @@ public class Demo4 extends Activity { 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 c36abda081b3..f01a29d60293 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/Demo5.java +++ b/tests/TransitionTests/src/com/android/transitiontests/Demo5.java @@ -33,7 +33,7 @@ public class Demo5 extends Activity { 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 d497abe8d3d9..40bf975eb5a8 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/FadingHierarchy.java +++ b/tests/TransitionTests/src/com/android/transitiontests/FadingHierarchy.java @@ -34,11 +34,11 @@ public class FadingHierarchy extends Activity { 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 29fb868794f4..83073666d6a0 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/FadingTest.java +++ b/tests/TransitionTests/src/com/android/transitiontests/FadingTest.java @@ -43,13 +43,13 @@ public class FadingTest extends Activity { 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 a06ba8fb61d1..025e4e313738 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/InstanceTargets.java +++ b/tests/TransitionTests/src/com/android/transitiontests/InstanceTargets.java @@ -37,7 +37,7 @@ public class InstanceTargets extends Activity { 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 c26e93f95ed3..6186150d772a 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/InterruptionTest.java +++ b/tests/TransitionTests/src/com/android/transitiontests/InterruptionTest.java @@ -40,17 +40,17 @@ public class InterruptionTest extends Activity { 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 251bf24e8a39..45b8286f6d0b 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/ListViewAddRemove.java +++ b/tests/TransitionTests/src/com/android/transitiontests/ListViewAddRemove.java @@ -47,9 +47,9 @@ public class ListViewAddRemove extends Activity { 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 92bbb85edb52..96b018b9f8e0 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/LoginActivity.java +++ b/tests/TransitionTests/src/com/android/transitiontests/LoginActivity.java @@ -40,7 +40,7 @@ public class LoginActivity extends Activity { 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 ef8cd3709413..384762b206be 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/OverlayTest.java +++ b/tests/TransitionTests/src/com/android/transitiontests/OverlayTest.java @@ -32,12 +32,12 @@ public class OverlayTest extends Activity { 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 1ee862177e23..772ddc793334 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/Reparenting.java +++ b/tests/TransitionTests/src/com/android/transitiontests/Reparenting.java @@ -34,9 +34,9 @@ public class Reparenting extends Activity { 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 1aee258343c4..96d3ae1fb354 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/ResourceLoadingTest.java +++ b/tests/TransitionTests/src/com/android/transitiontests/ResourceLoadingTest.java @@ -39,7 +39,7 @@ public class ResourceLoadingTest extends Activity { 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 7504058d315b..7ee4b3e7aa25 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTargets.java +++ b/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTargets.java @@ -39,7 +39,7 @@ public class ScenesTestAutoTargets extends Activity { 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 23b28ec0fb2b..9333ea1c093b 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTransition.java +++ b/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTransition.java @@ -37,7 +37,7 @@ public class ScenesTestAutoTransition extends Activity { 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 ecf5ef349c25..a01f6382b154 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/ScenesTestv21.java +++ b/tests/TransitionTests/src/com/android/transitiontests/ScenesTestv21.java @@ -39,7 +39,7 @@ public class ScenesTestv21 extends Activity { 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 c550e92f62d6..5f4560cceb06 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/SequenceTest.java +++ b/tests/TransitionTests/src/com/android/transitiontests/SequenceTest.java @@ -41,12 +41,12 @@ public class SequenceTest extends Activity { 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 92b169ec9e1f..f478cb8630f5 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/SequenceTestSimple.java +++ b/tests/TransitionTests/src/com/android/transitiontests/SequenceTestSimple.java @@ -42,10 +42,10 @@ public class SequenceTestSimple extends Activity { 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 9b246adb08cb..8819c40bb27a 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/SurfaceAndTextureViews.java +++ b/tests/TransitionTests/src/com/android/transitiontests/SurfaceAndTextureViews.java @@ -48,8 +48,8 @@ public class SurfaceAndTextureViews extends Activity { 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 c8249561ef2b..b2b24bc22600 100644 --- a/tests/TransitionTests/src/com/android/transitiontests/UniqueIds.java +++ b/tests/TransitionTests/src/com/android/transitiontests/UniqueIds.java @@ -40,7 +40,7 @@ public class UniqueIds extends Activity { 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 0a069c269697..c212c4cbf61a 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 @@ public class ActivityTransition extends AppCompatActivity { 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 @@ public class ActivityTransition extends AppCompatActivity { 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 a654c6107134..a4d57e173bfa 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 @@ public class ActivityTransitionDetails extends AppCompatActivity { 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 e2bf8976a315..235e0e61b353 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 @@ public class BitmapUploadActivity extends AppCompatActivity { 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 7454124b5ed0..fee7480fa65e 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 @@ public class ClippedListActivity extends AppCompatActivity 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 @@ public class ClippedListActivity extends AppCompatActivity @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 1d68767b2db2..a54110454f7a 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 @@ public class NavigationDrawerActivity extends AppCompatActivity 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 e2a9bcb0d2af..e1df7d3e28ac 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 @@ public class RenderingJitter extends Activity { 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 2d9226ff4246..af8b846385b0 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 @@ public class UsbHostManagementActivity extends Activity 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 8de2f6b42840..47ca482b7771 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 @@ public class AnimatedVectorDrawableAttr extends Activity { 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 41058c9ba8a4..733f602f6c14 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 @@ public class StartVoiceInteractionActivity extends Activity implements View.OnCl 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 7880f6721193..63e11a75f73a 100644 --- a/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java +++ b/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java @@ -58,28 +58,28 @@ public class MainActivity extends Activity { 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/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index c562cb95ee31..6140a896b1a8 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -23,7 +23,12 @@ import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.NetworkCapabilities.*; +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; import android.app.NotificationManager; import android.app.PendingIntent; @@ -33,6 +38,7 @@ import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; import android.net.ConnectivityManager.PacketKeepalive; @@ -42,6 +48,7 @@ import android.net.INetworkStatsService; import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkProperties; +import android.net.MatchAllNetworkSpecifier; import android.net.Network; import android.net.NetworkAgent; import android.net.NetworkCapabilities; @@ -51,7 +58,9 @@ import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkMisc; import android.net.NetworkRequest; +import android.net.NetworkSpecifier; import android.net.RouteInfo; +import android.net.StringNetworkSpecifier; import android.net.metrics.IpConnectivityLog; import android.net.util.MultinetworkPolicyTracker; import android.os.ConditionVariable; @@ -64,24 +73,32 @@ import android.os.Message; import android.os.MessageQueue; import android.os.Messenger; import android.os.MessageQueue.IdleHandler; +import android.os.Parcel; +import android.os.Parcelable; import android.os.Process; import android.os.SystemClock; import android.provider.Settings; import android.test.AndroidTestCase; import android.test.mock.MockContentResolver; import android.test.suitebuilder.annotation.SmallTest; +import android.text.TextUtils; import android.util.Log; import android.util.LogPrinter; import com.android.internal.util.WakeupMessage; import com.android.internal.util.test.BroadcastInterceptingContext; import com.android.internal.util.test.FakeSettingsProvider; +import com.android.server.connectivity.MockableSystemProperties; import com.android.server.connectivity.NetworkAgentInfo; import com.android.server.connectivity.NetworkMonitor; import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult; import com.android.server.net.NetworkPinner; import com.android.server.net.NetworkPolicyManagerInternal; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; + import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; @@ -134,8 +151,19 @@ public class ConnectivityServiceTest extends AndroidTestCase { private class MockContext extends BroadcastInterceptingContext { private final MockContentResolver mContentResolver; + @Spy private Resources mResources; + MockContext(Context base) { super(base); + + mResources = spy(base.getResources()); + when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)). + thenReturn(new String[] { + "wifi,1,1,1,-1,true", + "mobile,0,0,0,-1,true", + "mobile_mms,2,0,2,60000,true", + }); + mContentResolver = new MockContentResolver(); mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); } @@ -151,6 +179,11 @@ public class ConnectivityServiceTest extends AndroidTestCase { public ContentResolver getContentResolver() { return mContentResolver; } + + @Override + public Resources getResources() { + return mResources; + } } /** @@ -319,6 +352,11 @@ public class ConnectivityServiceTest extends AndroidTestCase { mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); } + public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) { + mNetworkCapabilities.setNetworkSpecifier(networkSpecifier); + mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); + } + public void connectWithoutInternet() { mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); mNetworkAgent.sendNetworkInfo(mNetworkInfo); @@ -621,6 +659,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { private class WrappedConnectivityService extends ConnectivityService { public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker; private WrappedNetworkMonitor mLastCreatedNetworkMonitor; + private MockableSystemProperties mSystemProperties; public WrappedConnectivityService(Context context, INetworkManagementService netManager, INetworkStatsService statsService, INetworkPolicyManager policyManager, @@ -630,9 +669,13 @@ public class ConnectivityServiceTest extends AndroidTestCase { } @Override - protected int getDefaultTcpRwnd() { - // Prevent wrapped ConnectivityService from trying to write to SystemProperties. - return 0; + protected MockableSystemProperties getSystemProperties() { + // Minimal approach to overriding system properties: let most calls fall through to real + // device values, and only override ones values that are important to this test. + mSystemProperties = spy(new MockableSystemProperties()); + when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0); + when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false); + return mSystemProperties; } @Override @@ -805,6 +848,14 @@ public class ConnectivityServiceTest extends AndroidTestCase { return cv; } + public void testNetworkTypes() { + // Ensure that our mocks for the networkAttributes config variable work as expected. If they + // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types + // will fail. Failing here is much easier to debug. + assertTrue(mCm.isNetworkSupported(TYPE_WIFI)); + assertTrue(mCm.isNetworkSupported(TYPE_MOBILE)); + } + @SmallTest public void testLingering() throws Exception { verifyNoNetwork(); @@ -1819,34 +1870,130 @@ public class ConnectivityServiceTest extends AndroidTestCase { captivePortalCallback.assertNoCallback(); } + private NetworkRequest.Builder newWifiRequestBuilder() { + return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI); + } + @SmallTest - public void testInvalidNetworkSpecifier() { - boolean execptionCalled = true; + public void testNetworkSpecifier() { + NetworkRequest rEmpty1 = newWifiRequestBuilder().build(); + NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build(); + NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build(); + NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier( + (NetworkSpecifier) null).build(); + NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build(); + NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier( + new StringNetworkSpecifier("bar")).build(); + + TestNetworkCallback cEmpty1 = new TestNetworkCallback(); + TestNetworkCallback cEmpty2 = new TestNetworkCallback(); + TestNetworkCallback cEmpty3 = new TestNetworkCallback(); + TestNetworkCallback cEmpty4 = new TestNetworkCallback(); + TestNetworkCallback cFoo = new TestNetworkCallback(); + TestNetworkCallback cBar = new TestNetworkCallback(); + TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] { + cEmpty1, cEmpty2, cEmpty3 }; + + mCm.registerNetworkCallback(rEmpty1, cEmpty1); + mCm.registerNetworkCallback(rEmpty2, cEmpty2); + mCm.registerNetworkCallback(rEmpty3, cEmpty3); + mCm.registerNetworkCallback(rEmpty4, cEmpty4); + mCm.registerNetworkCallback(rFoo, cFoo); + mCm.registerNetworkCallback(rBar, cBar); + mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); + mWiFiNetworkAgent.connect(false); + cEmpty1.expectAvailableCallbacks(mWiFiNetworkAgent); + cEmpty2.expectAvailableCallbacks(mWiFiNetworkAgent); + cEmpty3.expectAvailableCallbacks(mWiFiNetworkAgent); + cEmpty4.expectAvailableCallbacks(mWiFiNetworkAgent); + assertNoCallbacks(cFoo, cBar); + + mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo")); + cFoo.expectAvailableCallbacks(mWiFiNetworkAgent); + for (TestNetworkCallback c: emptyCallbacks) { + c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); + } + cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); + cFoo.assertNoCallback(); + + mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar")); + cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); + cBar.expectAvailableCallbacks(mWiFiNetworkAgent); + for (TestNetworkCallback c: emptyCallbacks) { + c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); + } + cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); + cBar.assertNoCallback(); + + mWiFiNetworkAgent.setNetworkSpecifier(null); + cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); + for (TestNetworkCallback c: emptyCallbacks) { + c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); + } + + assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar); + } + + @SmallTest + public void testInvalidNetworkSpecifier() { try { NetworkRequest.Builder builder = new NetworkRequest.Builder(); - builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER); - execptionCalled = false; - } catch (IllegalArgumentException e) { - // do nothing - should get here + builder.setNetworkSpecifier(new MatchAllNetworkSpecifier()); + fail("NetworkRequest builder with MatchAllNetworkSpecifier"); + } catch (IllegalArgumentException expected) { + // expected } - assertTrue("NetworkRequest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER", - execptionCalled); - try { NetworkCapabilities networkCapabilities = new NetworkCapabilities(); networkCapabilities.addTransportType(TRANSPORT_WIFI) - .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER); + .setNetworkSpecifier(new MatchAllNetworkSpecifier()); mService.requestNetwork(networkCapabilities, null, 0, null, ConnectivityManager.TYPE_WIFI); - execptionCalled = false; - } catch (IllegalArgumentException e) { - // do nothing - should get here + fail("ConnectivityService requestNetwork with MatchAllNetworkSpecifier"); + } catch (IllegalArgumentException expected) { + // expected + } + + class NonParcelableSpecifier extends NetworkSpecifier { + public boolean satisfiedBy(NetworkSpecifier other) { return false; } + }; + class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable { + @Override public int describeContents() { return 0; } + @Override public void writeToParcel(Parcel p, int flags) {} } + NetworkRequest.Builder builder; - assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER", - execptionCalled); + builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET); + try { + builder.setNetworkSpecifier(new NonParcelableSpecifier()); + Parcel parcelW = Parcel.obtain(); + builder.build().writeToParcel(parcelW, 0); + fail("Parceling a non-parcelable specifier did not throw an exception"); + } catch (Exception e) { + // expected + } + + builder = new NetworkRequest.Builder().addTransportType(TRANSPORT_ETHERNET); + builder.setNetworkSpecifier(new ParcelableSpecifier()); + NetworkRequest nr = builder.build(); + assertNotNull(nr); + + try { + Parcel parcelW = Parcel.obtain(); + nr.writeToParcel(parcelW, 0); + byte[] bytes = parcelW.marshall(); + parcelW.recycle(); + + Parcel parcelR = Parcel.obtain(); + parcelR.unmarshall(bytes, 0, bytes.length); + parcelR.setDataPosition(0); + NetworkRequest rereadNr = NetworkRequest.CREATOR.createFromParcel(parcelR); + fail("Unparceling a non-framework NetworkSpecifier did not throw an exception"); + } catch (Exception e) { + // expected + } } @SmallTest diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java index d819b9642e0c..d11565abb917 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.NetworkEvent; 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 @@ public class IpConnectivityEventBuilderTest extends TestCase { 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 @@ public class IpConnectivityEventBuilderTest extends TestCase { " 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 @@ public class IpConnectivityEventBuilderTest extends TestCase { " 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 @@ public class IpConnectivityEventBuilderTest extends TestCase { " 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 @@ public class IpConnectivityEventBuilderTest extends TestCase { " 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 @@ public class IpConnectivityEventBuilderTest extends TestCase { " 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 @@ public class IpConnectivityEventBuilderTest extends TestCase { " 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 @@ public class IpConnectivityEventBuilderTest extends TestCase { " if_name: \"\"", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -190,7 +192,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { aBool(true), aBool(false)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -211,7 +213,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " transport_types: 3", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -223,7 +225,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { aString("SomeState"), anInt(192)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -237,7 +239,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " state_transition: \"SomeState\"", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -248,7 +250,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { 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 @@ public class IpConnectivityEventBuilderTest extends TestCase { " 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 @@ public class IpConnectivityEventBuilderTest extends TestCase { anInt(IpManagerEvent.PROVISIONING_OK), aLong(5678)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -340,7 +290,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " latency_ms: 5678", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -351,7 +301,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { 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 @@ public class IpConnectivityEventBuilderTest extends TestCase { " if_name: \"\"", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -377,7 +327,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { anInt(5), aLong(20410)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -393,7 +343,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " >", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -406,7 +356,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { anInt(ValidationProbeEvent.PROBE_HTTP), anInt(204)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -420,7 +370,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " probe_type: 1", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -436,7 +386,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { anInt(2048), anInt(3)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -454,7 +404,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " program_length: 2048", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -474,7 +424,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { anInt(3), anInt(2048)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -495,7 +445,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { " zero_lifetime_ras: 1", " >", ">", - "version: 2"); + "version: 2\n"); verifySerialization(want, ev); } @@ -511,7 +461,7 @@ public class IpConnectivityEventBuilderTest extends TestCase { aLong(1000), aLong(-1)); - String want = joinLines( + String want = String.join("\n", "dropped_events: 0", "events <", " if_name: \"\"", @@ -528,28 +478,20 @@ public class IpConnectivityEventBuilderTest extends TestCase { " 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 68786d0b4212..e01469b1825e 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.IpManagerEvent; 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.Collections; 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 @@ public class IpConnectivityMetricsTest extends TestCase { assertEventsEqual(expectedEvent(3), got.get(2)); } - @SmallTest + @Test public void testLoggingEventsWithMultipleCallers() throws Exception { IpConnectivityLog logger = new IpConnectivityLog(mMockService); @@ -91,7 +115,7 @@ public class IpConnectivityMetricsTest extends TestCase { }.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 @@ public class IpConnectivityMetricsTest extends TestCase { } } - @SmallTest + @Test public void testBufferFlushing() { String output1 = getdump("flush"); assertEquals("", output1); @@ -115,7 +139,7 @@ public class IpConnectivityMetricsTest extends TestCase { assertEquals("", output3); } - @SmallTest + @Test public void testRateLimiting() { final IpConnectivityLog logger = new IpConnectivityLog(mService.impl); final ApfProgramEvent ev = new ApfProgramEvent(); @@ -137,11 +161,19 @@ public class IpConnectivityMetricsTest extends TestCase { 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 @@ public class IpConnectivityMetricsTest extends TestCase { 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 @@ public class IpConnectivityMetricsTest extends TestCase { " 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 @@ public class IpConnectivityMetricsTest extends TestCase { 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 0ab440641d53..f98ab3d06921 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 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; + +import android.content.Context; 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.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 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 org.mockito.Mockito.any; -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; - -public class NetdEventListenerServiceTest extends TestCase { - - // 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; - } - } +import org.junit.runner.RunWith; +@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); - - verify(mCm, times(1)).registerNetworkCallback(any(), mCallbackCaptor.capture()); - } - - @SmallTest - public void testOneDnsBatch() throws Exception { - log(105, LATENCIES); - log(106, Arrays.copyOf(LATENCIES, BATCH_SIZE - 1)); // one lookup short of a batch event + NetworkCapabilities ncWifi = new NetworkCapabilities(); + NetworkCapabilities ncCell = new NetworkCapabilities(); + ncWifi.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); + ncCell.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); - verifyLoggedDnsEvents(new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES)); + mCm = mock(ConnectivityManager.class); + when(mCm.getNetworkCapabilities(new Network(100))).thenReturn(ncWifi); + when(mCm.getNetworkCapabilities(new Network(101))).thenReturn(ncCell); - 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)); - } - - @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)); + mNetdEventListenerService = new NetdEventListenerService(mCm); } - @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)); + @Test + public void testDnsLogging() throws Exception { + asyncDump(100); + + 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); + + 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 + @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 @@ public class NetdEventListenerServiceTest extends TestCase { 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", - " >", - " errnos_counters <", - " key: 11", - " value: 1", - " >", - " errnos_counters <", - " key: 13", - " value: 3", + "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: 98", - " 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: 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); - } - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - } - - void logDnsAsync(int netId, int[] latencies) { - new Thread(() -> log(netId, latencies)).start(); - } - - 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()); - } + void dnsEvent(int netId, int type, int result, int latency) throws Exception { + mNetdEventListenerService.onDnsEvent(netId, type, result, latency, "", null, 0, 0); } - /** 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)); + 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); + } + }).start(); } - static void verifyConnectEvent(String expected, IpConnectivityEvent got) { - try { - Arrays.sort(got.getConnectStatistics().latenciesMs); - Arrays.sort(got.getConnectStatistics().errnosCounters, + // 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; + + 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/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index 6e0809e62450..b86188fa8503 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -87,6 +87,7 @@ struct LinkOptions { 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; @@ -376,8 +377,8 @@ bool ResourceFileFlattener::LinkAndVersionXmlFile(ResourceTable* table, FileOper versioned_file_desc.config.sdkVersion = (uint16_t)sdk_level; FileOperation new_file_op; - new_file_op.xml_to_flatten = - util::make_unique<xml::XmlResource>(versioned_file_desc, doc->root->Clone()); + new_file_op.xml_to_flatten = util::make_unique<xml::XmlResource>( + 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 = @@ -837,8 +838,8 @@ class LinkCommand { } bool WriteJavaFile(ResourceTable* table, const StringPiece& package_name_to_generate, - const StringPiece& out_package, - const JavaClassGeneratorOptions& java_options) { + const StringPiece& out_package, const JavaClassGeneratorOptions& java_options, + const Maybe<std::string> out_text_symbols_path = {}) { if (!options_.generate_java_class_path) { return true; } @@ -861,8 +862,20 @@ class LinkCommand { 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; } @@ -1683,7 +1696,8 @@ class LinkCommand { 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; } } @@ -1785,9 +1799,9 @@ int Link(const std::vector<StringPiece>& args) { .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) @@ -1841,6 +1855,10 @@ int Link(const std::vector<StringPiece>& args) { .OptionalFlagList("--add-javadoc-annotation", "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\n" "<add-resource> tags.", @@ -1855,7 +1873,8 @@ int Link(const std::vector<StringPiece>& args) { &options.extensions_to_not_compress) .OptionalFlagList("--split", "Split resources matching a set of configs out to a Split APK.\n" - "Syntax: path/to/output.apk:<config>[,<config>[...]].", + "Syntax: path/to/output.apk:<config>[,<config>[...]].\n" + "On Windows, use a semicolon ';' separator instead.", &split_args) .OptionalSwitch("-v", "Enables verbose logging.", &verbose); diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp index 8f8e0c8e4f6d..e99ee8aa93c2 100644 --- a/tools/aapt2/cmd/Optimize.cpp +++ b/tools/aapt2/cmd/Optimize.cpp @@ -302,7 +302,8 @@ int Optimize(const std::vector<StringPiece>& args) { &configs) .OptionalFlagList("--split", "Split resources matching a set of configs out to a " - "Split APK.\nSyntax: path/to/output.apk:<config>[,<config>[...]].", + "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" diff --git a/tools/aapt2/cmd/Util.cpp b/tools/aapt2/cmd/Util.cpp index fd94bbc0a1c3..14d426061e56 100644 --- a/tools/aapt2/cmd/Util.cpp +++ b/tools/aapt2/cmd/Util.cpp @@ -57,10 +57,17 @@ bool ParseSplitParameter(const StringPiece& arg, IDiagnostics* diag, std::string CHECK(out_path != nullptr); CHECK(out_split != nullptr); - std::vector<std::string> parts = util::Split(arg, ':'); +#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:<config>[,<config>...]"); + diag->Note(DiagMessage() << "should be --split path/to/output.apk" << sSeparator + << "<config>[,<config>...]."); return false; } diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp index 68bdb959ca07..a8226c0a9082 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 @@ void JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const Res 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 @@ void JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const Res 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 @@ void JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const Res 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::ProcessStyleable(const ResourceNameRef& name, const Res 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 @@ void JavaClassGenerator::ProcessResource(const ResourceNameRef& name, const Reso 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 @@ bool JavaClassGenerator::ProcessType(const StringPiece& package_name_to_generate 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 @@ bool JavaClassGenerator::ProcessType(const StringPiece& package_name_to_generate 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 @@ static void AppendJavaDocAnnotations(const std::vector<std::string>& annotations } 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 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, 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 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, 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 @@ bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, } 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 45104301e7f5..18746ffc5a0a 100644 --- a/tools/aapt2/java/JavaClassGenerator.h +++ b/tools/aapt2/java/JavaClassGenerator.h @@ -59,7 +59,7 @@ struct JavaClassGeneratorOptions { 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 @@ class JavaClassGenerator { // 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 @@ class JavaClassGenerator { 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 @@ class JavaClassGenerator { 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/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp index 4a278f632a4a..60551901fe8d 100644 --- a/tools/aapt2/xml/XmlDom.cpp +++ b/tools/aapt2/xml/XmlDom.cpp @@ -224,7 +224,8 @@ std::unique_ptr<XmlResource> Inflate(std::istream* in, IDiagnostics* diag, const XML_ParserFree(parser); if (stack.root) { - return util::make_unique<XmlResource>(ResourceFile{{}, {}, source}, std::move(stack.root)); + return util::make_unique<XmlResource>(ResourceFile{{}, {}, source}, StringPool{}, + std::move(stack.root)); } return {}; } @@ -357,7 +358,7 @@ std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, IDiagnos } } } - return util::make_unique<XmlResource>(ResourceFile{}, std::move(root), std::move(string_pool)); + 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 f1d0953c5494..6950c307abf3 100644 --- a/tools/aapt2/xml/XmlDom.h +++ b/tools/aapt2/xml/XmlDom.h @@ -128,8 +128,13 @@ class Text : public BaseNode<Text> { class XmlResource { public: ResourceFile file; - std::unique_ptr<xml::Node> root; + + // 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; }; /** diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java index a21fe68e9003..78b6f7187af3 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.Map; 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; /** diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java index 5a239e1f3f38..ad26bc8b8672 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java @@ -923,4 +923,9 @@ public class BridgePackageManager extends PackageManager { public ComponentName getInstantAppResolverSettingsComponent() { return null; } + + @Override + public ComponentName getInstantAppInstallerComponent() { + return null; + } } |