Merge "AudioFocusRequest: longer code sample, javadoc fixes" into oc-dev
diff --git a/api/current.txt b/api/current.txt
index 82b6ae9..6023aab 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -206,9 +206,6 @@
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
@@ -273,7 +270,7 @@
field public static final int allowTaskReparenting = 16843268; // 0x1010204
field public static final int allowUndo = 16843999; // 0x10104df
field public static final int alpha = 16843551; // 0x101031f
- field public static final int alphabeticModifiers = 16844112; // 0x1010550
+ field public static final int alphabeticModifiers = 16844110; // 0x101054e
field public static final int alphabeticShortcut = 16843235; // 0x10101e3
field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
field public static final int alwaysRetainTaskState = 16843267; // 0x1010203
@@ -293,7 +290,7 @@
field public static final int anyDensity = 16843372; // 0x101026c
field public static final int apduServiceBanner = 16843757; // 0x10103ed
field public static final int apiKey = 16843281; // 0x1010211
- field public static final int appCategory = 16844102; // 0x1010546
+ field public static final int appCategory = 16844101; // 0x1010545
field public static final int author = 16843444; // 0x10102b4
field public static final int authorities = 16842776; // 0x1010018
field public static final int autoAdvanceViewId = 16843535; // 0x101030f
@@ -301,7 +298,7 @@
field public static final int autoLink = 16842928; // 0x10100b0
field public static final int autoMirrored = 16843754; // 0x10103ea
field public static final int autoRemoveFromRecents = 16843847; // 0x1010447
- field public static final int autoSizeMaxTextSize = 16844103; // 0x1010547
+ field public static final int autoSizeMaxTextSize = 16844102; // 0x1010546
field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
field public static final int autoSizePresetSizes = 16844087; // 0x1010537
field public static final int autoSizeStepGranularity = 16844086; // 0x1010536
@@ -310,8 +307,8 @@
field public static final deprecated int autoText = 16843114; // 0x101016a
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 autofilledHighlight = 16844139; // 0x101056b
+ field public static final int autofillHints = 16844118; // 0x1010556
+ field public static final int autofilledHighlight = 16844136; // 0x1010568
field public static final int background = 16842964; // 0x10100d4
field public static final int backgroundDimAmount = 16842802; // 0x1010032
field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -361,7 +358,7 @@
field public static final int canRecord = 16844060; // 0x101051c
field public static final deprecated int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
field public static final int canRequestFilterKeyEvents = 16843737; // 0x10103d9
- field public static final int canRequestFingerprintGestures = 16844111; // 0x101054f
+ field public static final int canRequestFingerprintGestures = 16844109; // 0x101054d
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
@@ -373,7 +370,7 @@
field public static final int centerMedium = 16842959; // 0x10100cf
field public static final int centerX = 16843170; // 0x10101a2
field public static final int centerY = 16843171; // 0x10101a3
- field public static final int certDigest = 16844106; // 0x101054a
+ field public static final int certDigest = 16844104; // 0x1010548
field public static final int checkBoxPreferenceStyle = 16842895; // 0x101008f
field public static final int checkMark = 16843016; // 0x1010108
field public static final int checkMarkTint = 16843943; // 0x10104a7
@@ -412,12 +409,12 @@
field public static final int colorControlHighlight = 16843820; // 0x101042c
field public static final int colorControlNormal = 16843817; // 0x1010429
field public static final int colorEdgeEffect = 16843982; // 0x10104ce
- field public static final int colorError = 16844100; // 0x1010544
+ field public static final int colorError = 16844099; // 0x1010543
field public static final int colorFocusedHighlight = 16843663; // 0x101038f
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
field public static final int colorLongPressedHighlight = 16843662; // 0x101038e
- field public static final int colorMode = 16844108; // 0x101054c
+ field public static final int colorMode = 16844106; // 0x101054a
field public static final int colorMultiSelectHighlight = 16843665; // 0x1010391
field public static final int colorPressedHighlight = 16843661; // 0x101038d
field public static final int colorPrimary = 16843827; // 0x1010433
@@ -470,7 +467,7 @@
field public static final deprecated int dayOfWeekBackground = 16843924; // 0x1010494
field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
field public static final int debuggable = 16842767; // 0x101000f
- field public static final int defaultFocusHighlightEnabled = 16844133; // 0x1010565
+ field public static final int defaultFocusHighlightEnabled = 16844130; // 0x1010562
field public static final int defaultHeight = 16844021; // 0x10104f5
field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
field public static final int defaultValue = 16843245; // 0x10101ed
@@ -602,15 +599,15 @@
field public static final int flipInterval = 16843129; // 0x1010179
field public static final int focusable = 16842970; // 0x10100da
field public static final int focusableInTouchMode = 16842971; // 0x10100db
- field public static final int focusedByDefault = 16844101; // 0x1010545
+ field public static final int focusedByDefault = 16844100; // 0x1010544
field public static final deprecated int focusedMonthDateColor = 16843587; // 0x1010343
field public static final int font = 16844082; // 0x1010532
field public static final int fontFamily = 16843692; // 0x10103ac
field public static final int fontFeatureSettings = 16843959; // 0x10104b7
- field public static final int fontProviderAuthority = 16844114; // 0x1010552
- field public static final int fontProviderCerts = 16844128; // 0x1010560
- field public static final int fontProviderPackage = 16844122; // 0x101055a
- field public static final int fontProviderQuery = 16844115; // 0x1010553
+ field public static final int fontProviderAuthority = 16844112; // 0x1010550
+ field public static final int fontProviderCerts = 16844125; // 0x101055d
+ field public static final int fontProviderPackage = 16844119; // 0x1010557
+ field public static final int fontProviderQuery = 16844113; // 0x1010551
field public static final int fontStyle = 16844095; // 0x101053f
field public static final int fontWeight = 16844083; // 0x1010533
field public static final int footerDividersEnabled = 16843311; // 0x101022f
@@ -696,9 +693,9 @@
field public static final int hyphenationFrequency = 16843998; // 0x10104de
field public static final int icon = 16842754; // 0x1010002
field public static final int iconPreview = 16843337; // 0x1010249
- field public static final int iconSpaceReserved = 16844132; // 0x1010564
- field public static final int iconTint = 16844129; // 0x1010561
- field public static final int iconTintMode = 16844130; // 0x1010562
+ field public static final int iconSpaceReserved = 16844129; // 0x1010561
+ field public static final int iconTint = 16844126; // 0x101055e
+ field public static final int iconTintMode = 16844127; // 0x101055f
field public static final int iconifiedByDefault = 16843514; // 0x10102fa
field public static final int id = 16842960; // 0x10100d0
field public static final int ignoreGravity = 16843263; // 0x10101ff
@@ -715,7 +712,7 @@
field public static final int imeSubtypeMode = 16843501; // 0x10102ed
field public static final int immersive = 16843456; // 0x10102c0
field public static final int importantForAccessibility = 16843690; // 0x10103aa
- field public static final int importantForAutofill = 16844123; // 0x101055b
+ field public static final int importantForAutofill = 16844120; // 0x1010558
field public static final int inAnimation = 16843127; // 0x1010177
field public static final int includeFontPadding = 16843103; // 0x101015f
field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -750,21 +747,21 @@
field public static final int isAsciiCapable = 16843753; // 0x10103e9
field public static final int isAuxiliary = 16843647; // 0x101037f
field public static final int isDefault = 16843297; // 0x1010221
- field public static final int isFeatureSplit = 16844126; // 0x101055e
+ field public static final int isFeatureSplit = 16844123; // 0x101055b
field public static final int isGame = 16843764; // 0x10103f4
field public static final int isIndicator = 16843079; // 0x1010147
field public static final int isModifier = 16843334; // 0x1010246
field public static final int isRepeatable = 16843336; // 0x1010248
field public static final int isScrollContainer = 16843342; // 0x101024e
- field public static final int isStatic = 16844125; // 0x101055d
+ field public static final int isStatic = 16844122; // 0x101055a
field public static final int isSticky = 16843335; // 0x1010247
field public static final int isolatedProcess = 16843689; // 0x10103a9
- field public static final int isolatedSplits = 16844109; // 0x101054d
+ field public static final int isolatedSplits = 16844107; // 0x101054b
field public static final int itemBackground = 16843056; // 0x1010130
field public static final int itemIconDisabledAlpha = 16843057; // 0x1010131
field public static final int itemPadding = 16843565; // 0x101032d
field public static final int itemTextAppearance = 16843052; // 0x101012c
- field public static final int justificationMode = 16844138; // 0x101056a
+ field public static final int justificationMode = 16844135; // 0x1010567
field public static final int keepScreenOn = 16843286; // 0x1010216
field public static final int key = 16843240; // 0x10101e8
field public static final int keyBackground = 16843315; // 0x1010233
@@ -881,7 +878,7 @@
field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
field public static final int matchOrder = 16843855; // 0x101044f
field public static final int max = 16843062; // 0x1010136
- field public static final int maxAspectRatio = 16844131; // 0x1010563
+ field public static final int maxAspectRatio = 16844128; // 0x1010560
field public static final int maxButtonHeight = 16844029; // 0x10104fd
field public static final int maxDate = 16843584; // 0x1010340
field public static final int maxEms = 16843095; // 0x1010157
@@ -944,7 +941,7 @@
field public static final int numbersSelectorColor = 16843939; // 0x10104a3
field public static final int numbersTextColor = 16843937; // 0x10104a1
field public static final deprecated int numeric = 16843109; // 0x1010165
- field public static final int numericModifiers = 16844113; // 0x1010551
+ field public static final int numericModifiers = 16844111; // 0x101054f
field public static final int numericShortcut = 16843236; // 0x10101e4
field public static final int offset = 16844052; // 0x1010514
field public static final int onClick = 16843375; // 0x101026f
@@ -992,7 +989,7 @@
field public static final int persistableMode = 16843821; // 0x101042d
field public static final int persistent = 16842765; // 0x101000d
field public static final int persistentDrawingCache = 16842990; // 0x10100ee
- field public static final int persistentWhenFeatureAvailable = 16844134; // 0x1010566
+ field public static final int persistentWhenFeatureAvailable = 16844131; // 0x1010563
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
@@ -1018,7 +1015,7 @@
field public static final int preferenceStyle = 16842894; // 0x101008e
field public static final int presentationTheme = 16843712; // 0x10103c0
field public static final int previewImage = 16843482; // 0x10102da
- field public static final int primaryContentAlpha = 16844117; // 0x1010555
+ field public static final int primaryContentAlpha = 16844114; // 0x1010552
field public static final int priority = 16842780; // 0x101001c
field public static final int privateImeOptions = 16843299; // 0x1010223
field public static final int process = 16842769; // 0x1010011
@@ -1061,8 +1058,8 @@
field public static final int ratingBarStyleSmall = 16842877; // 0x101007d
field public static final int readPermission = 16842759; // 0x1010007
field public static final int recognitionService = 16843932; // 0x101049c
- field public static final int recreateOnConfigChanges = 16844105; // 0x1010549
- field public static final int recycleEnabled = 16844124; // 0x101055c
+ field public static final int recreateOnConfigChanges = 16844103; // 0x1010547
+ field public static final int recycleEnabled = 16844121; // 0x1010559
field public static final int relinquishTaskIdentity = 16843894; // 0x1010476
field public static final int reparent = 16843964; // 0x10104bc
field public static final int reparentWithOverlay = 16843965; // 0x10104bd
@@ -1076,9 +1073,9 @@
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
- field public static final int requiredFeature = 16844119; // 0x1010557
+ field public static final int requiredFeature = 16844116; // 0x1010554
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
- field public static final int requiredNotFeature = 16844120; // 0x1010558
+ field public static final int requiredNotFeature = 16844117; // 0x1010555
field public static final int requiresFadingEdge = 16843685; // 0x10103a5
field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
field public static final int resizeClip = 16843983; // 0x10104cf
@@ -1146,7 +1143,7 @@
field public static final int searchSuggestSelection = 16843224; // 0x10101d8
field public static final int searchSuggestThreshold = 16843373; // 0x101026d
field public static final int searchViewStyle = 16843904; // 0x1010480
- field public static final int secondaryContentAlpha = 16844118; // 0x1010556
+ field public static final int secondaryContentAlpha = 16844115; // 0x1010553
field public static final int secondaryProgress = 16843064; // 0x1010138
field public static final int secondaryProgressTint = 16843879; // 0x1010467
field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
@@ -1186,7 +1183,7 @@
field public static final deprecated int shownWeekCount = 16843585; // 0x1010341
field public static final int shrinkColumns = 16843082; // 0x101014a
field public static final deprecated int singleLine = 16843101; // 0x101015d
- field public static final int singleLineTitle = 16844127; // 0x101055f
+ field public static final int singleLineTitle = 16844124; // 0x101055c
field public static final int singleUser = 16843711; // 0x10103bf
field public static final int slideEdge = 16843824; // 0x1010430
field public static final int smallIcon = 16843422; // 0x101029e
@@ -1200,7 +1197,7 @@
field public static final int spinnerStyle = 16842881; // 0x1010081
field public static final int spinnersShown = 16843595; // 0x101034b
field public static final int splitMotionEvents = 16843503; // 0x10102ef
- field public static final int splitName = 16844107; // 0x101054b
+ field public static final int splitName = 16844105; // 0x1010549
field public static final int splitTrack = 16843852; // 0x101044c
field public static final int spotShadowAlpha = 16843967; // 0x10104bf
field public static final int src = 16843033; // 0x1010119
@@ -1297,7 +1294,7 @@
field public static final int targetName = 16843853; // 0x101044d
field public static final int targetPackage = 16842785; // 0x1010021
field public static final int targetProcesses = 16844097; // 0x1010541
- field public static final int targetSandboxVersion = 16844110; // 0x101054e
+ field public static final int targetSandboxVersion = 16844108; // 0x101054c
field public static final int targetSdkVersion = 16843376; // 0x1010270
field public static final int taskAffinity = 16842770; // 0x1010012
field public static final int taskCloseEnterAnimation = 16842942; // 0x10100be
@@ -1540,7 +1537,7 @@
field public static final int windowShowAnimation = 16842934; // 0x10100b6
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
- field public static final int windowSplashscreenContent = 16844135; // 0x1010567
+ field public static final int windowSplashscreenContent = 16844132; // 0x1010564
field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
field public static final int windowTitleSize = 16842842; // 0x101005a
@@ -30508,7 +30505,7 @@
field public static final int M = 23; // 0x17
field public static final int N = 24; // 0x18
field public static final int N_MR1 = 25; // 0x19
- field public static final int O = 10000; // 0x2710
+ field public static final int O = 26; // 0x1a
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/api/removed.txt b/api/removed.txt
index f52b39a..9baafeb 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -254,18 +254,6 @@
field public static final int BADGING_SD = 10; // 0xa
}
- public abstract class NetworkRecommendationProvider {
- ctor public deprecated NetworkRecommendationProvider(android.os.Handler);
- method public deprecated void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback);
- field public static final deprecated java.lang.String EXTRA_RECOMMENDATION_RESULT = "android.net.extra.RECOMMENDATION_RESULT";
- field public static final deprecated java.lang.String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
- }
-
- public static deprecated class NetworkRecommendationProvider.ResultCallback {
- ctor public NetworkRecommendationProvider.ResultCallback(android.os.IRemoteCallback, int);
- method public void onResult(android.net.RecommendationResult);
- }
-
public abstract class PskKeyManager {
ctor public PskKeyManager();
field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
@@ -273,37 +261,6 @@
field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
}
- public final deprecated class RecommendationRequest implements android.os.Parcelable {
- ctor protected RecommendationRequest(android.os.Parcel);
- method public android.net.wifi.WifiConfiguration[] getConnectableConfigs();
- method public android.net.wifi.WifiConfiguration getConnectedConfig();
- method public android.net.wifi.WifiConfiguration getDefaultWifiConfig();
- method public int getLastSelectedNetworkId();
- method public long getLastSelectedNetworkTimestamp();
- method public android.net.wifi.ScanResult[] getScanResults();
- method public void setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
- method public void setConnectedConfig(android.net.wifi.WifiConfiguration);
- field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR;
- }
-
- public static final deprecated class RecommendationRequest.Builder {
- ctor public RecommendationRequest.Builder();
- method public android.net.RecommendationRequest build();
- method public android.net.RecommendationRequest.Builder setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
- method public android.net.RecommendationRequest.Builder setConnectedWifiConfig(android.net.wifi.WifiConfiguration);
- method public android.net.RecommendationRequest.Builder setDefaultWifiConfig(android.net.wifi.WifiConfiguration);
- method public android.net.RecommendationRequest.Builder setLastSelectedNetwork(int, long);
- method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]);
- }
-
- public final deprecated class RecommendationResult implements android.os.Parcelable {
- method public static android.net.RecommendationResult createConnectRecommendation(android.net.wifi.WifiConfiguration);
- method public static android.net.RecommendationResult createDoNotConnectRecommendation();
- method public android.net.wifi.WifiConfiguration getWifiConfiguration();
- method public boolean hasRecommendation();
- field public static final android.os.Parcelable.Creator<android.net.RecommendationResult> CREATOR;
- }
-
public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index fcc647d..67b6e82 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -327,9 +327,6 @@
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
@@ -394,7 +391,7 @@
field public static final int allowTaskReparenting = 16843268; // 0x1010204
field public static final int allowUndo = 16843999; // 0x10104df
field public static final int alpha = 16843551; // 0x101031f
- field public static final int alphabeticModifiers = 16844112; // 0x1010550
+ field public static final int alphabeticModifiers = 16844110; // 0x101054e
field public static final int alphabeticShortcut = 16843235; // 0x10101e3
field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
field public static final int alwaysRetainTaskState = 16843267; // 0x1010203
@@ -414,7 +411,7 @@
field public static final int anyDensity = 16843372; // 0x101026c
field public static final int apduServiceBanner = 16843757; // 0x10103ed
field public static final int apiKey = 16843281; // 0x1010211
- field public static final int appCategory = 16844102; // 0x1010546
+ field public static final int appCategory = 16844101; // 0x1010545
field public static final int author = 16843444; // 0x10102b4
field public static final int authorities = 16842776; // 0x1010018
field public static final int autoAdvanceViewId = 16843535; // 0x101030f
@@ -422,7 +419,7 @@
field public static final int autoLink = 16842928; // 0x10100b0
field public static final int autoMirrored = 16843754; // 0x10103ea
field public static final int autoRemoveFromRecents = 16843847; // 0x1010447
- field public static final int autoSizeMaxTextSize = 16844103; // 0x1010547
+ field public static final int autoSizeMaxTextSize = 16844102; // 0x1010546
field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
field public static final int autoSizePresetSizes = 16844087; // 0x1010537
field public static final int autoSizeStepGranularity = 16844086; // 0x1010536
@@ -431,8 +428,8 @@
field public static final deprecated int autoText = 16843114; // 0x101016a
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 autofilledHighlight = 16844139; // 0x101056b
+ field public static final int autofillHints = 16844118; // 0x1010556
+ field public static final int autofilledHighlight = 16844136; // 0x1010568
field public static final int background = 16842964; // 0x10100d4
field public static final int backgroundDimAmount = 16842802; // 0x1010032
field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -482,7 +479,7 @@
field public static final int canRecord = 16844060; // 0x101051c
field public static final deprecated int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
field public static final int canRequestFilterKeyEvents = 16843737; // 0x10103d9
- field public static final int canRequestFingerprintGestures = 16844111; // 0x101054f
+ field public static final int canRequestFingerprintGestures = 16844109; // 0x101054d
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
@@ -494,7 +491,7 @@
field public static final int centerMedium = 16842959; // 0x10100cf
field public static final int centerX = 16843170; // 0x10101a2
field public static final int centerY = 16843171; // 0x10101a3
- field public static final int certDigest = 16844106; // 0x101054a
+ field public static final int certDigest = 16844104; // 0x1010548
field public static final int checkBoxPreferenceStyle = 16842895; // 0x101008f
field public static final int checkMark = 16843016; // 0x1010108
field public static final int checkMarkTint = 16843943; // 0x10104a7
@@ -533,12 +530,12 @@
field public static final int colorControlHighlight = 16843820; // 0x101042c
field public static final int colorControlNormal = 16843817; // 0x1010429
field public static final int colorEdgeEffect = 16843982; // 0x10104ce
- field public static final int colorError = 16844100; // 0x1010544
+ field public static final int colorError = 16844099; // 0x1010543
field public static final int colorFocusedHighlight = 16843663; // 0x101038f
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
field public static final int colorLongPressedHighlight = 16843662; // 0x101038e
- field public static final int colorMode = 16844108; // 0x101054c
+ field public static final int colorMode = 16844106; // 0x101054a
field public static final int colorMultiSelectHighlight = 16843665; // 0x1010391
field public static final int colorPressedHighlight = 16843661; // 0x101038d
field public static final int colorPrimary = 16843827; // 0x1010433
@@ -591,7 +588,7 @@
field public static final deprecated int dayOfWeekBackground = 16843924; // 0x1010494
field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
field public static final int debuggable = 16842767; // 0x101000f
- field public static final int defaultFocusHighlightEnabled = 16844133; // 0x1010565
+ field public static final int defaultFocusHighlightEnabled = 16844130; // 0x1010562
field public static final int defaultHeight = 16844021; // 0x10104f5
field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
field public static final int defaultValue = 16843245; // 0x10101ed
@@ -723,15 +720,15 @@
field public static final int flipInterval = 16843129; // 0x1010179
field public static final int focusable = 16842970; // 0x10100da
field public static final int focusableInTouchMode = 16842971; // 0x10100db
- field public static final int focusedByDefault = 16844101; // 0x1010545
+ field public static final int focusedByDefault = 16844100; // 0x1010544
field public static final deprecated int focusedMonthDateColor = 16843587; // 0x1010343
field public static final int font = 16844082; // 0x1010532
field public static final int fontFamily = 16843692; // 0x10103ac
field public static final int fontFeatureSettings = 16843959; // 0x10104b7
- field public static final int fontProviderAuthority = 16844114; // 0x1010552
- field public static final int fontProviderCerts = 16844128; // 0x1010560
- field public static final int fontProviderPackage = 16844122; // 0x101055a
- field public static final int fontProviderQuery = 16844115; // 0x1010553
+ field public static final int fontProviderAuthority = 16844112; // 0x1010550
+ field public static final int fontProviderCerts = 16844125; // 0x101055d
+ field public static final int fontProviderPackage = 16844119; // 0x1010557
+ field public static final int fontProviderQuery = 16844113; // 0x1010551
field public static final int fontStyle = 16844095; // 0x101053f
field public static final int fontWeight = 16844083; // 0x1010533
field public static final int footerDividersEnabled = 16843311; // 0x101022f
@@ -817,9 +814,9 @@
field public static final int hyphenationFrequency = 16843998; // 0x10104de
field public static final int icon = 16842754; // 0x1010002
field public static final int iconPreview = 16843337; // 0x1010249
- field public static final int iconSpaceReserved = 16844132; // 0x1010564
- field public static final int iconTint = 16844129; // 0x1010561
- field public static final int iconTintMode = 16844130; // 0x1010562
+ field public static final int iconSpaceReserved = 16844129; // 0x1010561
+ field public static final int iconTint = 16844126; // 0x101055e
+ field public static final int iconTintMode = 16844127; // 0x101055f
field public static final int iconifiedByDefault = 16843514; // 0x10102fa
field public static final int id = 16842960; // 0x10100d0
field public static final int ignoreGravity = 16843263; // 0x10101ff
@@ -836,7 +833,7 @@
field public static final int imeSubtypeMode = 16843501; // 0x10102ed
field public static final int immersive = 16843456; // 0x10102c0
field public static final int importantForAccessibility = 16843690; // 0x10103aa
- field public static final int importantForAutofill = 16844123; // 0x101055b
+ field public static final int importantForAutofill = 16844120; // 0x1010558
field public static final int inAnimation = 16843127; // 0x1010177
field public static final int includeFontPadding = 16843103; // 0x101015f
field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -871,21 +868,21 @@
field public static final int isAsciiCapable = 16843753; // 0x10103e9
field public static final int isAuxiliary = 16843647; // 0x101037f
field public static final int isDefault = 16843297; // 0x1010221
- field public static final int isFeatureSplit = 16844126; // 0x101055e
+ field public static final int isFeatureSplit = 16844123; // 0x101055b
field public static final int isGame = 16843764; // 0x10103f4
field public static final int isIndicator = 16843079; // 0x1010147
field public static final int isModifier = 16843334; // 0x1010246
field public static final int isRepeatable = 16843336; // 0x1010248
field public static final int isScrollContainer = 16843342; // 0x101024e
- field public static final int isStatic = 16844125; // 0x101055d
+ field public static final int isStatic = 16844122; // 0x101055a
field public static final int isSticky = 16843335; // 0x1010247
field public static final int isolatedProcess = 16843689; // 0x10103a9
- field public static final int isolatedSplits = 16844109; // 0x101054d
+ field public static final int isolatedSplits = 16844107; // 0x101054b
field public static final int itemBackground = 16843056; // 0x1010130
field public static final int itemIconDisabledAlpha = 16843057; // 0x1010131
field public static final int itemPadding = 16843565; // 0x101032d
field public static final int itemTextAppearance = 16843052; // 0x101012c
- field public static final int justificationMode = 16844138; // 0x101056a
+ field public static final int justificationMode = 16844135; // 0x1010567
field public static final int keepScreenOn = 16843286; // 0x1010216
field public static final int key = 16843240; // 0x10101e8
field public static final int keyBackground = 16843315; // 0x1010233
@@ -1002,7 +999,7 @@
field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
field public static final int matchOrder = 16843855; // 0x101044f
field public static final int max = 16843062; // 0x1010136
- field public static final int maxAspectRatio = 16844131; // 0x1010563
+ field public static final int maxAspectRatio = 16844128; // 0x1010560
field public static final int maxButtonHeight = 16844029; // 0x10104fd
field public static final int maxDate = 16843584; // 0x1010340
field public static final int maxEms = 16843095; // 0x1010157
@@ -1065,7 +1062,7 @@
field public static final int numbersSelectorColor = 16843939; // 0x10104a3
field public static final int numbersTextColor = 16843937; // 0x10104a1
field public static final deprecated int numeric = 16843109; // 0x1010165
- field public static final int numericModifiers = 16844113; // 0x1010551
+ field public static final int numericModifiers = 16844111; // 0x101054f
field public static final int numericShortcut = 16843236; // 0x10101e4
field public static final int offset = 16844052; // 0x1010514
field public static final int onClick = 16843375; // 0x101026f
@@ -1113,7 +1110,7 @@
field public static final int persistableMode = 16843821; // 0x101042d
field public static final int persistent = 16842765; // 0x101000d
field public static final int persistentDrawingCache = 16842990; // 0x10100ee
- field public static final int persistentWhenFeatureAvailable = 16844134; // 0x1010566
+ field public static final int persistentWhenFeatureAvailable = 16844131; // 0x1010563
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
@@ -1139,7 +1136,7 @@
field public static final int preferenceStyle = 16842894; // 0x101008e
field public static final int presentationTheme = 16843712; // 0x10103c0
field public static final int previewImage = 16843482; // 0x10102da
- field public static final int primaryContentAlpha = 16844117; // 0x1010555
+ field public static final int primaryContentAlpha = 16844114; // 0x1010552
field public static final int priority = 16842780; // 0x101001c
field public static final int privateImeOptions = 16843299; // 0x1010223
field public static final int process = 16842769; // 0x1010011
@@ -1182,8 +1179,8 @@
field public static final int ratingBarStyleSmall = 16842877; // 0x101007d
field public static final int readPermission = 16842759; // 0x1010007
field public static final int recognitionService = 16843932; // 0x101049c
- field public static final int recreateOnConfigChanges = 16844105; // 0x1010549
- field public static final int recycleEnabled = 16844124; // 0x101055c
+ field public static final int recreateOnConfigChanges = 16844103; // 0x1010547
+ field public static final int recycleEnabled = 16844121; // 0x1010559
field public static final int relinquishTaskIdentity = 16843894; // 0x1010476
field public static final int reparent = 16843964; // 0x10104bc
field public static final int reparentWithOverlay = 16843965; // 0x10104bd
@@ -1197,11 +1194,11 @@
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
- field public static final int requiredFeature = 16844119; // 0x1010557
+ field public static final int requiredFeature = 16844116; // 0x1010554
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
- field public static final int requiredNotFeature = 16844120; // 0x1010558
- field public static final int requiredSystemPropertyName = 16844136; // 0x1010568
- field public static final int requiredSystemPropertyValue = 16844137; // 0x1010569
+ field public static final int requiredNotFeature = 16844117; // 0x1010555
+ field public static final int requiredSystemPropertyName = 16844133; // 0x1010565
+ field public static final int requiredSystemPropertyValue = 16844134; // 0x1010566
field public static final int requiresFadingEdge = 16843685; // 0x10103a5
field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
field public static final int resizeClip = 16843983; // 0x10104cf
@@ -1273,7 +1270,7 @@
field public static final int searchSuggestSelection = 16843224; // 0x10101d8
field public static final int searchSuggestThreshold = 16843373; // 0x101026d
field public static final int searchViewStyle = 16843904; // 0x1010480
- field public static final int secondaryContentAlpha = 16844118; // 0x1010556
+ field public static final int secondaryContentAlpha = 16844115; // 0x1010553
field public static final int secondaryProgress = 16843064; // 0x1010138
field public static final int secondaryProgressTint = 16843879; // 0x1010467
field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
@@ -1313,7 +1310,7 @@
field public static final deprecated int shownWeekCount = 16843585; // 0x1010341
field public static final int shrinkColumns = 16843082; // 0x101014a
field public static final deprecated int singleLine = 16843101; // 0x101015d
- field public static final int singleLineTitle = 16844127; // 0x101055f
+ field public static final int singleLineTitle = 16844124; // 0x101055c
field public static final int singleUser = 16843711; // 0x10103bf
field public static final int slideEdge = 16843824; // 0x1010430
field public static final int smallIcon = 16843422; // 0x101029e
@@ -1327,7 +1324,7 @@
field public static final int spinnerStyle = 16842881; // 0x1010081
field public static final int spinnersShown = 16843595; // 0x101034b
field public static final int splitMotionEvents = 16843503; // 0x10102ef
- field public static final int splitName = 16844107; // 0x101054b
+ field public static final int splitName = 16844105; // 0x1010549
field public static final int splitTrack = 16843852; // 0x101044c
field public static final int spotShadowAlpha = 16843967; // 0x10104bf
field public static final int src = 16843033; // 0x1010119
@@ -1424,7 +1421,7 @@
field public static final int targetName = 16843853; // 0x101044d
field public static final int targetPackage = 16842785; // 0x1010021
field public static final int targetProcesses = 16844097; // 0x1010541
- field public static final int targetSandboxVersion = 16844110; // 0x101054e
+ field public static final int targetSandboxVersion = 16844108; // 0x101054c
field public static final int targetSdkVersion = 16843376; // 0x1010270
field public static final int taskAffinity = 16842770; // 0x1010012
field public static final int taskCloseEnterAnimation = 16842942; // 0x10100be
@@ -1667,7 +1664,7 @@
field public static final int windowShowAnimation = 16842934; // 0x10100b6
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
- field public static final int windowSplashscreenContent = 16844135; // 0x1010567
+ field public static final int windowSplashscreenContent = 16844132; // 0x1010564
field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
field public static final int windowTitleSize = 16842842; // 0x101005a
@@ -33218,7 +33215,7 @@
field public static final int M = 23; // 0x17
field public static final int N = 24; // 0x18
field public static final int N_MR1 = 25; // 0x19
- field public static final int O = 10000; // 0x2710
+ field public static final int O = 26; // 0x1a
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 9f3970d..b1a29e7 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -252,18 +252,6 @@
field public static final int BADGING_SD = 10; // 0xa
}
- public abstract class NetworkRecommendationProvider {
- ctor public deprecated NetworkRecommendationProvider(android.os.Handler);
- method public deprecated void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback);
- field public static final deprecated java.lang.String EXTRA_RECOMMENDATION_RESULT = "android.net.extra.RECOMMENDATION_RESULT";
- field public static final deprecated java.lang.String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
- }
-
- public static deprecated class NetworkRecommendationProvider.ResultCallback {
- ctor public NetworkRecommendationProvider.ResultCallback(android.os.IRemoteCallback, int);
- method public void onResult(android.net.RecommendationResult);
- }
-
public abstract class PskKeyManager {
ctor public PskKeyManager();
field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
@@ -271,37 +259,6 @@
field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
}
- public final deprecated class RecommendationRequest implements android.os.Parcelable {
- ctor protected RecommendationRequest(android.os.Parcel);
- method public android.net.wifi.WifiConfiguration[] getConnectableConfigs();
- method public android.net.wifi.WifiConfiguration getConnectedConfig();
- method public android.net.wifi.WifiConfiguration getDefaultWifiConfig();
- method public int getLastSelectedNetworkId();
- method public long getLastSelectedNetworkTimestamp();
- method public android.net.wifi.ScanResult[] getScanResults();
- method public void setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
- method public void setConnectedConfig(android.net.wifi.WifiConfiguration);
- field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR;
- }
-
- public static final deprecated class RecommendationRequest.Builder {
- ctor public RecommendationRequest.Builder();
- method public android.net.RecommendationRequest build();
- method public android.net.RecommendationRequest.Builder setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
- method public android.net.RecommendationRequest.Builder setConnectedWifiConfig(android.net.wifi.WifiConfiguration);
- method public android.net.RecommendationRequest.Builder setDefaultWifiConfig(android.net.wifi.WifiConfiguration);
- method public android.net.RecommendationRequest.Builder setLastSelectedNetwork(int, long);
- method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]);
- }
-
- public final deprecated class RecommendationResult implements android.os.Parcelable {
- method public static android.net.RecommendationResult createConnectRecommendation(android.net.wifi.WifiConfiguration);
- method public static android.net.RecommendationResult createDoNotConnectRecommendation();
- method public android.net.wifi.WifiConfiguration getWifiConfiguration();
- method public boolean hasRecommendation();
- field public static final android.os.Parcelable.Creator<android.net.RecommendationResult> CREATOR;
- }
-
public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 1ff9efe..d3cb4c9 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -206,9 +206,6 @@
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
@@ -273,7 +270,7 @@
field public static final int allowTaskReparenting = 16843268; // 0x1010204
field public static final int allowUndo = 16843999; // 0x10104df
field public static final int alpha = 16843551; // 0x101031f
- field public static final int alphabeticModifiers = 16844112; // 0x1010550
+ field public static final int alphabeticModifiers = 16844110; // 0x101054e
field public static final int alphabeticShortcut = 16843235; // 0x10101e3
field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
field public static final int alwaysRetainTaskState = 16843267; // 0x1010203
@@ -293,7 +290,7 @@
field public static final int anyDensity = 16843372; // 0x101026c
field public static final int apduServiceBanner = 16843757; // 0x10103ed
field public static final int apiKey = 16843281; // 0x1010211
- field public static final int appCategory = 16844102; // 0x1010546
+ field public static final int appCategory = 16844101; // 0x1010545
field public static final int author = 16843444; // 0x10102b4
field public static final int authorities = 16842776; // 0x1010018
field public static final int autoAdvanceViewId = 16843535; // 0x101030f
@@ -301,7 +298,7 @@
field public static final int autoLink = 16842928; // 0x10100b0
field public static final int autoMirrored = 16843754; // 0x10103ea
field public static final int autoRemoveFromRecents = 16843847; // 0x1010447
- field public static final int autoSizeMaxTextSize = 16844103; // 0x1010547
+ field public static final int autoSizeMaxTextSize = 16844102; // 0x1010546
field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
field public static final int autoSizePresetSizes = 16844087; // 0x1010537
field public static final int autoSizeStepGranularity = 16844086; // 0x1010536
@@ -310,8 +307,8 @@
field public static final deprecated int autoText = 16843114; // 0x101016a
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 autofilledHighlight = 16844139; // 0x101056b
+ field public static final int autofillHints = 16844118; // 0x1010556
+ field public static final int autofilledHighlight = 16844136; // 0x1010568
field public static final int background = 16842964; // 0x10100d4
field public static final int backgroundDimAmount = 16842802; // 0x1010032
field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -361,7 +358,7 @@
field public static final int canRecord = 16844060; // 0x101051c
field public static final deprecated int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
field public static final int canRequestFilterKeyEvents = 16843737; // 0x10103d9
- field public static final int canRequestFingerprintGestures = 16844111; // 0x101054f
+ field public static final int canRequestFingerprintGestures = 16844109; // 0x101054d
field public static final int canRequestTouchExplorationMode = 16843735; // 0x10103d7
field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
@@ -373,7 +370,7 @@
field public static final int centerMedium = 16842959; // 0x10100cf
field public static final int centerX = 16843170; // 0x10101a2
field public static final int centerY = 16843171; // 0x10101a3
- field public static final int certDigest = 16844106; // 0x101054a
+ field public static final int certDigest = 16844104; // 0x1010548
field public static final int checkBoxPreferenceStyle = 16842895; // 0x101008f
field public static final int checkMark = 16843016; // 0x1010108
field public static final int checkMarkTint = 16843943; // 0x10104a7
@@ -412,12 +409,12 @@
field public static final int colorControlHighlight = 16843820; // 0x101042c
field public static final int colorControlNormal = 16843817; // 0x1010429
field public static final int colorEdgeEffect = 16843982; // 0x10104ce
- field public static final int colorError = 16844100; // 0x1010544
+ field public static final int colorError = 16844099; // 0x1010543
field public static final int colorFocusedHighlight = 16843663; // 0x101038f
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
field public static final int colorLongPressedHighlight = 16843662; // 0x101038e
- field public static final int colorMode = 16844108; // 0x101054c
+ field public static final int colorMode = 16844106; // 0x101054a
field public static final int colorMultiSelectHighlight = 16843665; // 0x1010391
field public static final int colorPressedHighlight = 16843661; // 0x101038d
field public static final int colorPrimary = 16843827; // 0x1010433
@@ -470,7 +467,7 @@
field public static final deprecated int dayOfWeekBackground = 16843924; // 0x1010494
field public static final deprecated int dayOfWeekTextAppearance = 16843925; // 0x1010495
field public static final int debuggable = 16842767; // 0x101000f
- field public static final int defaultFocusHighlightEnabled = 16844133; // 0x1010565
+ field public static final int defaultFocusHighlightEnabled = 16844130; // 0x1010562
field public static final int defaultHeight = 16844021; // 0x10104f5
field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
field public static final int defaultValue = 16843245; // 0x10101ed
@@ -602,15 +599,15 @@
field public static final int flipInterval = 16843129; // 0x1010179
field public static final int focusable = 16842970; // 0x10100da
field public static final int focusableInTouchMode = 16842971; // 0x10100db
- field public static final int focusedByDefault = 16844101; // 0x1010545
+ field public static final int focusedByDefault = 16844100; // 0x1010544
field public static final deprecated int focusedMonthDateColor = 16843587; // 0x1010343
field public static final int font = 16844082; // 0x1010532
field public static final int fontFamily = 16843692; // 0x10103ac
field public static final int fontFeatureSettings = 16843959; // 0x10104b7
- field public static final int fontProviderAuthority = 16844114; // 0x1010552
- field public static final int fontProviderCerts = 16844128; // 0x1010560
- field public static final int fontProviderPackage = 16844122; // 0x101055a
- field public static final int fontProviderQuery = 16844115; // 0x1010553
+ field public static final int fontProviderAuthority = 16844112; // 0x1010550
+ field public static final int fontProviderCerts = 16844125; // 0x101055d
+ field public static final int fontProviderPackage = 16844119; // 0x1010557
+ field public static final int fontProviderQuery = 16844113; // 0x1010551
field public static final int fontStyle = 16844095; // 0x101053f
field public static final int fontWeight = 16844083; // 0x1010533
field public static final int footerDividersEnabled = 16843311; // 0x101022f
@@ -696,9 +693,9 @@
field public static final int hyphenationFrequency = 16843998; // 0x10104de
field public static final int icon = 16842754; // 0x1010002
field public static final int iconPreview = 16843337; // 0x1010249
- field public static final int iconSpaceReserved = 16844132; // 0x1010564
- field public static final int iconTint = 16844129; // 0x1010561
- field public static final int iconTintMode = 16844130; // 0x1010562
+ field public static final int iconSpaceReserved = 16844129; // 0x1010561
+ field public static final int iconTint = 16844126; // 0x101055e
+ field public static final int iconTintMode = 16844127; // 0x101055f
field public static final int iconifiedByDefault = 16843514; // 0x10102fa
field public static final int id = 16842960; // 0x10100d0
field public static final int ignoreGravity = 16843263; // 0x10101ff
@@ -715,7 +712,7 @@
field public static final int imeSubtypeMode = 16843501; // 0x10102ed
field public static final int immersive = 16843456; // 0x10102c0
field public static final int importantForAccessibility = 16843690; // 0x10103aa
- field public static final int importantForAutofill = 16844123; // 0x101055b
+ field public static final int importantForAutofill = 16844120; // 0x1010558
field public static final int inAnimation = 16843127; // 0x1010177
field public static final int includeFontPadding = 16843103; // 0x101015f
field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -750,21 +747,21 @@
field public static final int isAsciiCapable = 16843753; // 0x10103e9
field public static final int isAuxiliary = 16843647; // 0x101037f
field public static final int isDefault = 16843297; // 0x1010221
- field public static final int isFeatureSplit = 16844126; // 0x101055e
+ field public static final int isFeatureSplit = 16844123; // 0x101055b
field public static final int isGame = 16843764; // 0x10103f4
field public static final int isIndicator = 16843079; // 0x1010147
field public static final int isModifier = 16843334; // 0x1010246
field public static final int isRepeatable = 16843336; // 0x1010248
field public static final int isScrollContainer = 16843342; // 0x101024e
- field public static final int isStatic = 16844125; // 0x101055d
+ field public static final int isStatic = 16844122; // 0x101055a
field public static final int isSticky = 16843335; // 0x1010247
field public static final int isolatedProcess = 16843689; // 0x10103a9
- field public static final int isolatedSplits = 16844109; // 0x101054d
+ field public static final int isolatedSplits = 16844107; // 0x101054b
field public static final int itemBackground = 16843056; // 0x1010130
field public static final int itemIconDisabledAlpha = 16843057; // 0x1010131
field public static final int itemPadding = 16843565; // 0x101032d
field public static final int itemTextAppearance = 16843052; // 0x101012c
- field public static final int justificationMode = 16844138; // 0x101056a
+ field public static final int justificationMode = 16844135; // 0x1010567
field public static final int keepScreenOn = 16843286; // 0x1010216
field public static final int key = 16843240; // 0x10101e8
field public static final int keyBackground = 16843315; // 0x1010233
@@ -881,7 +878,7 @@
field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
field public static final int matchOrder = 16843855; // 0x101044f
field public static final int max = 16843062; // 0x1010136
- field public static final int maxAspectRatio = 16844131; // 0x1010563
+ field public static final int maxAspectRatio = 16844128; // 0x1010560
field public static final int maxButtonHeight = 16844029; // 0x10104fd
field public static final int maxDate = 16843584; // 0x1010340
field public static final int maxEms = 16843095; // 0x1010157
@@ -944,7 +941,7 @@
field public static final int numbersSelectorColor = 16843939; // 0x10104a3
field public static final int numbersTextColor = 16843937; // 0x10104a1
field public static final deprecated int numeric = 16843109; // 0x1010165
- field public static final int numericModifiers = 16844113; // 0x1010551
+ field public static final int numericModifiers = 16844111; // 0x101054f
field public static final int numericShortcut = 16843236; // 0x10101e4
field public static final int offset = 16844052; // 0x1010514
field public static final int onClick = 16843375; // 0x101026f
@@ -992,7 +989,7 @@
field public static final int persistableMode = 16843821; // 0x101042d
field public static final int persistent = 16842765; // 0x101000d
field public static final int persistentDrawingCache = 16842990; // 0x10100ee
- field public static final int persistentWhenFeatureAvailable = 16844134; // 0x1010566
+ field public static final int persistentWhenFeatureAvailable = 16844131; // 0x1010563
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
@@ -1018,7 +1015,7 @@
field public static final int preferenceStyle = 16842894; // 0x101008e
field public static final int presentationTheme = 16843712; // 0x10103c0
field public static final int previewImage = 16843482; // 0x10102da
- field public static final int primaryContentAlpha = 16844117; // 0x1010555
+ field public static final int primaryContentAlpha = 16844114; // 0x1010552
field public static final int priority = 16842780; // 0x101001c
field public static final int privateImeOptions = 16843299; // 0x1010223
field public static final int process = 16842769; // 0x1010011
@@ -1061,8 +1058,8 @@
field public static final int ratingBarStyleSmall = 16842877; // 0x101007d
field public static final int readPermission = 16842759; // 0x1010007
field public static final int recognitionService = 16843932; // 0x101049c
- field public static final int recreateOnConfigChanges = 16844105; // 0x1010549
- field public static final int recycleEnabled = 16844124; // 0x101055c
+ field public static final int recreateOnConfigChanges = 16844103; // 0x1010547
+ field public static final int recycleEnabled = 16844121; // 0x1010559
field public static final int relinquishTaskIdentity = 16843894; // 0x1010476
field public static final int reparent = 16843964; // 0x10104bc
field public static final int reparentWithOverlay = 16843965; // 0x10104bd
@@ -1076,9 +1073,9 @@
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
- field public static final int requiredFeature = 16844119; // 0x1010557
+ field public static final int requiredFeature = 16844116; // 0x1010554
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
- field public static final int requiredNotFeature = 16844120; // 0x1010558
+ field public static final int requiredNotFeature = 16844117; // 0x1010555
field public static final int requiresFadingEdge = 16843685; // 0x10103a5
field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
field public static final int resizeClip = 16843983; // 0x10104cf
@@ -1146,7 +1143,7 @@
field public static final int searchSuggestSelection = 16843224; // 0x10101d8
field public static final int searchSuggestThreshold = 16843373; // 0x101026d
field public static final int searchViewStyle = 16843904; // 0x1010480
- field public static final int secondaryContentAlpha = 16844118; // 0x1010556
+ field public static final int secondaryContentAlpha = 16844115; // 0x1010553
field public static final int secondaryProgress = 16843064; // 0x1010138
field public static final int secondaryProgressTint = 16843879; // 0x1010467
field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
@@ -1186,7 +1183,7 @@
field public static final deprecated int shownWeekCount = 16843585; // 0x1010341
field public static final int shrinkColumns = 16843082; // 0x101014a
field public static final deprecated int singleLine = 16843101; // 0x101015d
- field public static final int singleLineTitle = 16844127; // 0x101055f
+ field public static final int singleLineTitle = 16844124; // 0x101055c
field public static final int singleUser = 16843711; // 0x10103bf
field public static final int slideEdge = 16843824; // 0x1010430
field public static final int smallIcon = 16843422; // 0x101029e
@@ -1200,7 +1197,7 @@
field public static final int spinnerStyle = 16842881; // 0x1010081
field public static final int spinnersShown = 16843595; // 0x101034b
field public static final int splitMotionEvents = 16843503; // 0x10102ef
- field public static final int splitName = 16844107; // 0x101054b
+ field public static final int splitName = 16844105; // 0x1010549
field public static final int splitTrack = 16843852; // 0x101044c
field public static final int spotShadowAlpha = 16843967; // 0x10104bf
field public static final int src = 16843033; // 0x1010119
@@ -1297,7 +1294,7 @@
field public static final int targetName = 16843853; // 0x101044d
field public static final int targetPackage = 16842785; // 0x1010021
field public static final int targetProcesses = 16844097; // 0x1010541
- field public static final int targetSandboxVersion = 16844110; // 0x101054e
+ field public static final int targetSandboxVersion = 16844108; // 0x101054c
field public static final int targetSdkVersion = 16843376; // 0x1010270
field public static final int taskAffinity = 16842770; // 0x1010012
field public static final int taskCloseEnterAnimation = 16842942; // 0x10100be
@@ -1540,7 +1537,7 @@
field public static final int windowShowAnimation = 16842934; // 0x10100b6
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
- field public static final int windowSplashscreenContent = 16844135; // 0x1010567
+ field public static final int windowSplashscreenContent = 16844132; // 0x1010564
field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
field public static final int windowTitleSize = 16842842; // 0x101005a
@@ -30617,7 +30614,7 @@
field public static final int M = 23; // 0x17
field public static final int N = 24; // 0x18
field public static final int N_MR1 = 25; // 0x19
- field public static final int O = 10000; // 0x2710
+ field public static final int O = 26; // 0x1a
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/api/test-removed.txt b/api/test-removed.txt
index f52b39a..9baafeb 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -254,18 +254,6 @@
field public static final int BADGING_SD = 10; // 0xa
}
- public abstract class NetworkRecommendationProvider {
- ctor public deprecated NetworkRecommendationProvider(android.os.Handler);
- method public deprecated void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback);
- field public static final deprecated java.lang.String EXTRA_RECOMMENDATION_RESULT = "android.net.extra.RECOMMENDATION_RESULT";
- field public static final deprecated java.lang.String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
- }
-
- public static deprecated class NetworkRecommendationProvider.ResultCallback {
- ctor public NetworkRecommendationProvider.ResultCallback(android.os.IRemoteCallback, int);
- method public void onResult(android.net.RecommendationResult);
- }
-
public abstract class PskKeyManager {
ctor public PskKeyManager();
field public static final int MAX_IDENTITY_HINT_LENGTH_BYTES = 128; // 0x80
@@ -273,37 +261,6 @@
field public static final int MAX_KEY_LENGTH_BYTES = 256; // 0x100
}
- public final deprecated class RecommendationRequest implements android.os.Parcelable {
- ctor protected RecommendationRequest(android.os.Parcel);
- method public android.net.wifi.WifiConfiguration[] getConnectableConfigs();
- method public android.net.wifi.WifiConfiguration getConnectedConfig();
- method public android.net.wifi.WifiConfiguration getDefaultWifiConfig();
- method public int getLastSelectedNetworkId();
- method public long getLastSelectedNetworkTimestamp();
- method public android.net.wifi.ScanResult[] getScanResults();
- method public void setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
- method public void setConnectedConfig(android.net.wifi.WifiConfiguration);
- field public static final android.os.Parcelable.Creator<android.net.RecommendationRequest> CREATOR;
- }
-
- public static final deprecated class RecommendationRequest.Builder {
- ctor public RecommendationRequest.Builder();
- method public android.net.RecommendationRequest build();
- method public android.net.RecommendationRequest.Builder setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
- method public android.net.RecommendationRequest.Builder setConnectedWifiConfig(android.net.wifi.WifiConfiguration);
- method public android.net.RecommendationRequest.Builder setDefaultWifiConfig(android.net.wifi.WifiConfiguration);
- method public android.net.RecommendationRequest.Builder setLastSelectedNetwork(int, long);
- method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]);
- }
-
- public final deprecated class RecommendationResult implements android.os.Parcelable {
- method public static android.net.RecommendationResult createConnectRecommendation(android.net.wifi.WifiConfiguration);
- method public static android.net.RecommendationResult createDoNotConnectRecommendation();
- method public android.net.wifi.WifiConfiguration getWifiConfiguration();
- method public boolean hasRecommendation();
- field public static final android.os.Parcelable.Creator<android.net.RecommendationResult> CREATOR;
- }
-
public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
}
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 3fd0f50..38ce427 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -1346,6 +1346,8 @@
for (int n = 0; n < nodeCount; n++) {
final Node node = mNodes.get(n);
Node nodeClone = node.clone();
+ // Remove the old internal listener from the cloned child
+ nodeClone.mAnimation.removeListener(mDummyListener);
clonesMap.put(node, nodeClone);
anim.mNodes.add(nodeClone);
anim.mNodeMap.put(nodeClone.mAnimation, nodeClone);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a8183f2..ab03556 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2092,7 +2092,6 @@
if (params == null) {
throw new IllegalArgumentException("Expected non-null picture-in-picture params");
}
- updatePictureInPictureParamsForContentInsets(params);
return ActivityManagerNative.getDefault().enterPictureInPictureMode(mToken, params);
} catch (RemoteException e) {
return false;
@@ -2116,7 +2115,6 @@
if (params == null) {
throw new IllegalArgumentException("Expected non-null picture-in-picture params");
}
- updatePictureInPictureParamsForContentInsets(params);
ActivityManagerNative.getDefault().setPictureInPictureParams(mToken, params);
} catch (RemoteException e) {
}
@@ -2136,21 +2134,6 @@
}
}
- /**
- * Updates the provided {@param params} with the last known content insets for this activity, to
- * be used with the source hint rect for the transition into PiP.
- */
- private void updatePictureInPictureParamsForContentInsets(PictureInPictureParams params) {
- if (params != null && params.hasSourceBoundsHint() && getWindow() != null &&
- getWindow().peekDecorView() != null &&
- getWindow().peekDecorView().getViewRootImpl() != null) {
- params.setSourceRectHintInsets(
- getWindow().peekDecorView().getViewRootImpl().getLastContentInsets());
- } else {
- params.setSourceRectHintInsets(null);
- }
- }
-
void dispatchMovedToDisplay(int displayId, Configuration config) {
updateDisplay(displayId);
onMovedToDisplay(displayId, config);
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 3eec596..53608fb 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -38,6 +38,7 @@
import android.util.Pair;
import android.util.Slog;
import android.view.AppTransitionAnimationSpec;
+import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
@@ -213,6 +214,7 @@
private static final String KEY_INSTANT_APP_VERIFICATION_BUNDLE
= "android:instantapps.installerbundle";
+ private static final String KEY_SPECS_FUTURE = "android:activity.specsFuture";
/** @hide */
public static final int ANIM_NONE = 0;
@@ -268,6 +270,7 @@
private AppTransitionAnimationSpec mAnimSpecs[];
private int mRotationAnimationHint = -1;
private Bundle mAppVerificationBundle;
+ private IAppTransitionAnimationSpecsFuture mSpecsFuture;
/**
* Create an ActivityOptions specifying a custom animation to run when
@@ -492,35 +495,12 @@
* is not executed, the callback will happen immediately.
* @return Returns a new ActivityOptions object that you can use to
* supply these options as the options Bundle when starting an activity.
- * @hide
*/
- public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
+ private static ActivityOptions makeThumbnailScaleUpAnimation(View source,
Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, true);
}
- /**
- * Create an ActivityOptions specifying an animation where an activity window
- * is scaled from a given position to a thumbnail at a specified location.
- *
- * @param source The View that this thumbnail is animating to. This
- * defines the coordinate space for <var>startX</var> and <var>startY</var>.
- * @param thumbnail The bitmap that will be shown as the final thumbnail
- * of the animation.
- * @param startX The x end location of the bitmap, relative to <var>source</var>.
- * @param startY The y end location of the bitmap, relative to <var>source</var>.
- * @param listener Optional OnAnimationStartedListener to find out when the
- * requested animation has started running. If for some reason the animation
- * is not executed, the callback will happen immediately.
- * @return Returns a new ActivityOptions object that you can use to
- * supply these options as the options Bundle when starting an activity.
- * @hide
- */
- public static ActivityOptions makeThumbnailScaleDownAnimation(View source,
- Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
- return makeThumbnailAnimation(source, thumbnail, startX, startY, listener, false);
- }
-
private static ActivityOptions makeThumbnailAnimation(View source,
Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener,
boolean scaleUp) {
@@ -537,29 +517,21 @@
}
/**
- * Create an ActivityOptions specifying an animation where the new activity
- * window and a thumbnail is aspect-scaled to a new location.
- *
- * @param source The View that this thumbnail is animating from. This
- * defines the coordinate space for <var>startX</var> and <var>startY</var>.
- * @param thumbnail The bitmap that will be shown as the initial thumbnail
- * of the animation.
- * @param startX The x starting location of the bitmap, relative to <var>source</var>.
- * @param startY The y starting location of the bitmap, relative to <var>source</var>.
- * @param handler If <var>listener</var> is non-null this must be a valid
- * Handler on which to dispatch the callback; otherwise it should be null.
- * @param listener Optional OnAnimationStartedListener to find out when the
- * requested animation has started running. If for some reason the animation
- * is not executed, the callback will happen immediately.
- * @return Returns a new ActivityOptions object that you can use to
- * supply these options as the options Bundle when starting an activity.
+ * Create an ActivityOptions specifying an animation where a list of activity windows and
+ * thumbnails are aspect scaled to/from a new location.
* @hide
*/
- public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source,
- Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
- Handler handler, OnAnimationStartedListener listener) {
- return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
- targetWidth, targetHeight, handler, listener, true);
+ public static ActivityOptions makeMultiThumbFutureAspectScaleAnimation(Context context,
+ Handler handler, IAppTransitionAnimationSpecsFuture specsFuture,
+ OnAnimationStartedListener listener, boolean scaleUp) {
+ ActivityOptions opts = new ActivityOptions();
+ opts.mPackageName = context.getPackageName();
+ opts.mAnimationType = scaleUp
+ ? ANIM_THUMBNAIL_ASPECT_SCALE_UP
+ : ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
+ opts.mSpecsFuture = specsFuture;
+ opts.setOnAnimationStartedListener(handler, listener);
+ return opts;
}
/**
@@ -891,6 +863,10 @@
}
mRotationAnimationHint = opts.getInt(KEY_ROTATION_ANIMATION_HINT);
mAppVerificationBundle = opts.getBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE);
+ if (opts.containsKey(KEY_SPECS_FUTURE)) {
+ mSpecsFuture = IAppTransitionAnimationSpecsFuture.Stub.asInterface(opts.getBinder(
+ KEY_SPECS_FUTURE));
+ }
}
/**
@@ -1029,6 +1005,11 @@
public AppTransitionAnimationSpec[] getAnimSpecs() { return mAnimSpecs; }
/** @hide */
+ public IAppTransitionAnimationSpecsFuture getSpecsFuture() {
+ return mSpecsFuture;
+ }
+
+ /** @hide */
public static ActivityOptions fromBundle(Bundle bOptions) {
return bOptions != null ? new ActivityOptions(bOptions) : null;
}
@@ -1205,6 +1186,7 @@
}
mAnimSpecs = otherOptions.mAnimSpecs;
mAnimationFinishedListener = otherOptions.mAnimationFinishedListener;
+ mSpecsFuture = otherOptions.mSpecsFuture;
}
/**
@@ -1279,6 +1261,9 @@
if (mAnimationFinishedListener != null) {
b.putBinder(KEY_ANIMATION_FINISHED_LISTENER, mAnimationFinishedListener.asBinder());
}
+ if (mSpecsFuture != null) {
+ b.putBinder(KEY_SPECS_FUTURE, mSpecsFuture.asBinder());
+ }
b.putInt(KEY_ROTATION_ANIMATION_HINT, mRotationAnimationHint);
if (mAppVerificationBundle != null) {
b.putBundle(KEY_INSTANT_APP_VERIFICATION_BUNDLE, mAppVerificationBundle);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 51c2246..525b151 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -478,7 +478,7 @@
public @NonNull List<SharedLibraryInfo> getSharedLibrariesAsUser(int flags, int userId) {
try {
ParceledListSlice<SharedLibraryInfo> sharedLibs = mPM.getSharedLibraries(
- flags, userId);
+ mContext.getOpPackageName(), flags, userId);
if (sharedLibs == null) {
return Collections.emptyList();
}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 1b2543c..95d55dc 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -2303,11 +2303,15 @@
*/
private void completeExecute(BackStackRecord record, boolean isPop, boolean runTransitions,
boolean moveToState) {
+ if (isPop) {
+ record.executePopOps(moveToState);
+ } else {
+ record.executeOps();
+ }
ArrayList<BackStackRecord> records = new ArrayList<>(1);
ArrayList<Boolean> isRecordPop = new ArrayList<>(1);
records.add(record);
isRecordPop.add(isPop);
- executeOps(records, isRecordPop, 0, 1);
if (runTransitions) {
FragmentTransition.startTransitions(this, records, isRecordPop, 0, 1, true);
}
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 4994fbb..b5b1017 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -30,7 +30,7 @@
void onTaskStackChanged();
/** Called whenever an Activity is moved to the pinned stack from another stack. */
- void onActivityPinned(String packageName);
+ void onActivityPinned(String packageName, int taskId);
/** Called whenever an Activity is moved from the pinned stack to another stack. */
void onActivityUnpinned();
diff --git a/core/java/android/app/PictureInPictureArgs.java b/core/java/android/app/PictureInPictureArgs.java
index d7317f4..cbe8bb9 100644
--- a/core/java/android/app/PictureInPictureArgs.java
+++ b/core/java/android/app/PictureInPictureArgs.java
@@ -160,9 +160,6 @@
if (in.readInt() != 0) {
mSourceRectHint = Rect.CREATOR.createFromParcel(in);
}
- if (in.readInt() != 0) {
- mSourceRectHintInsets = Rect.CREATOR.createFromParcel(in);
- }
}
private PictureInPictureArgs(Rational aspectRatio, List<RemoteAction> actions,
@@ -220,9 +217,6 @@
if (otherArgs.hasSourceBoundsHint()) {
mSourceRectHint = new Rect(otherArgs.getSourceRectHint());
}
- if (otherArgs.hasSourceBoundsHintInsets()) {
- mSourceRectHintInsets = new Rect(otherArgs.getSourceRectHintInsets());
- }
}
/**
@@ -346,12 +340,6 @@
} else {
out.writeInt(0);
}
- if (mSourceRectHintInsets != null) {
- out.writeInt(1);
- mSourceRectHintInsets.writeToParcel(out, 0);
- } else {
- out.writeInt(0);
- }
}
public static final Creator<PictureInPictureArgs> CREATOR =
diff --git a/core/java/android/app/PictureInPictureParams.java b/core/java/android/app/PictureInPictureParams.java
index 323a0fb..7313b0d 100644
--- a/core/java/android/app/PictureInPictureParams.java
+++ b/core/java/android/app/PictureInPictureParams.java
@@ -135,13 +135,6 @@
@Nullable
private Rect mSourceRectHint;
- /**
- * The content insets that are used with the source hint rect for the transition into PiP where
- * the insets are removed at the beginning of the transition.
- */
- @Nullable
- private Rect mSourceRectHintInsets;
-
/** {@hide} */
PictureInPictureParams() {
}
@@ -158,9 +151,6 @@
if (in.readInt() != 0) {
mSourceRectHint = Rect.CREATOR.createFromParcel(in);
}
- if (in.readInt() != 0) {
- mSourceRectHintInsets = Rect.CREATOR.createFromParcel(in);
- }
}
/** {@hide} */
@@ -185,9 +175,6 @@
if (otherArgs.hasSourceBoundsHint()) {
mSourceRectHint = new Rect(otherArgs.getSourceRectHint());
}
- if (otherArgs.hasSourceBoundsHintInsets()) {
- mSourceRectHintInsets = new Rect(otherArgs.getSourceRectHintInsets());
- }
}
/**
@@ -241,19 +228,6 @@
}
/**
- * Sets the insets to be used with the source rect hint bounds.
- * @hide
- */
- @Deprecated
- public void setSourceRectHintInsets(Rect insets) {
- if (insets == null) {
- mSourceRectHintInsets = null;
- } else {
- mSourceRectHintInsets = new Rect(insets);
- }
- }
-
- /**
* @return the source rect hint
* @hide
*/
@@ -262,14 +236,6 @@
}
/**
- * @return the source rect hint insets.
- * @hide
- */
- public Rect getSourceRectHintInsets() {
- return mSourceRectHintInsets;
- }
-
- /**
* @return whether there are launch bounds set
* @hide
*/
@@ -277,14 +243,6 @@
return mSourceRectHint != null && !mSourceRectHint.isEmpty();
}
- /**
- * @return whether there are source rect hint insets set
- * @hide
- */
- public boolean hasSourceBoundsHintInsets() {
- return mSourceRectHintInsets != null;
- }
-
@Override
public int describeContents() {
return 0;
@@ -311,12 +269,6 @@
} else {
out.writeInt(0);
}
- if (mSourceRectHintInsets != null) {
- out.writeInt(1);
- mSourceRectHintInsets.writeToParcel(out, 0);
- } else {
- out.writeInt(0);
- }
}
public static final Creator<PictureInPictureParams> CREATOR =
@@ -328,4 +280,4 @@
return new PictureInPictureParams[size];
}
};
-}
\ No newline at end of file
+}
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 2df011f..a52ca0a 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -31,7 +31,7 @@
}
@Override
- public void onActivityPinned(String packageName) throws RemoteException {
+ public void onActivityPinned(String packageName, int taskId) throws RemoteException {
}
@Override
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index ce8b05a..0d7a941 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -15,10 +15,13 @@
*/
package android.app.usage;
+import android.annotation.IntDef;
import android.content.res.Configuration;
import android.os.Parcel;
import android.os.Parcelable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.List;
@@ -28,6 +31,12 @@
*/
public final class UsageEvents implements Parcelable {
+ /** @hide */
+ public static final String INSTANT_APP_PACKAGE_NAME = "android.instant_app";
+
+ /** @hide */
+ public static final String INSTANT_APP_CLASS_NAME = "android.instant_class";
+
/**
* An event representing a state change for a component.
*/
@@ -91,6 +100,17 @@
*/
public static final int CHOOSER_ACTION = 9;
+ /** @hide */
+ public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
+
+ /** @hide */
+ @IntDef(flag = true,
+ value = {
+ FLAG_IS_PACKAGE_INSTANT_APP,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface EventFlags {}
+
/**
* {@hide}
*/
@@ -145,6 +165,27 @@
*/
public String[] mContentAnnotations;
+ /** @hide */
+ @EventFlags
+ public int mFlags;
+
+ public Event() {
+ }
+
+ /** @hide */
+ public Event(Event orig) {
+ mPackage = orig.mPackage;
+ mClass = orig.mClass;
+ mTimeStamp = orig.mTimeStamp;
+ mEventType = orig.mEventType;
+ mConfiguration = orig.mConfiguration;
+ mShortcutId = orig.mShortcutId;
+ mAction = orig.mAction;
+ mContentType = orig.mContentType;
+ mContentAnnotations = orig.mContentAnnotations;
+ mFlags = orig.mFlags;
+ }
+
/**
* The package name of the source of this event.
*/
@@ -196,6 +237,20 @@
public String getShortcutId() {
return mShortcutId;
}
+
+ /** @hide */
+ public Event getObfuscatedIfInstantApp() {
+ if ((mFlags & FLAG_IS_PACKAGE_INSTANT_APP) == 0) {
+ return this;
+ }
+ final Event ret = new Event(this);
+ ret.mPackage = INSTANT_APP_PACKAGE_NAME;
+ ret.mClass = INSTANT_APP_CLASS_NAME;
+
+ // Note there are other string fields too, but they're for app shortcuts and choosers,
+ // which instant apps can't use anyway, so there's no need to hide them.
+ return ret;
+ }
}
// Only used when creating the resulting events. Not used for reading/unparceling.
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 0874095..7eef85c 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -85,6 +85,17 @@
mChooserCounts = stats.mChooserCounts;
}
+ /**
+ * {@hide}
+ */
+ public UsageStats getObfuscatedForInstantApp() {
+ final UsageStats ret = new UsageStats(this);
+
+ ret.mPackageName = UsageEvents.INSTANT_APP_PACKAGE_NAME;
+
+ return ret;
+ }
+
public String getPackageName() {
return mPackageName;
}
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index 08595dd..dbaace2 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -127,7 +127,12 @@
public abstract void applyRestoredPayload(int user, String key, byte[] payload);
- /* Cache Quota Service API */
+ /**
+ * Return usage stats.
+ *
+ * @param obfuscateInstantApps whether instant app package names need to be obfuscated in the
+ * result.
+ */
public abstract List<UsageStats> queryUsageStatsForUser(
- int userId, int interval, long beginTime, long endTime);
+ int userId, int interval, long beginTime, long endTime, boolean obfuscateInstantApps);
}
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 5fabbb6..a3d6e9f 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -16,7 +16,6 @@
package android.bluetooth;
-import android.content.Context;
import android.os.Handler;
import android.os.ParcelUuid;
import android.os.RemoteException;
@@ -927,6 +926,31 @@
}
/**
+ * Discovers a service by UUID. This is exposed only for passing PTS tests.
+ * It should never be used by real applications. The service is not searched
+ * for characteristics and descriptors, or returned in any callback.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @return true, if the remote service discovery has been started
+ * @hide
+ */
+ public boolean discoverServiceByUuid(UUID uuid) {
+ if (DBG) Log.d(TAG, "discoverServiceByUuid() - device: " + mDevice.getAddress());
+ if (mService == null || mClientIf == 0) return false;
+
+ mServices.clear();
+
+ try {
+ mService.discoverServiceByUuid(mClientIf, mDevice.getAddress(), new ParcelUuid(uuid));
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ return false;
+ }
+ return true;
+ }
+
+ /**
* Returns a list of GATT services offered by the remote device.
*
* <p>This function requires that service discovery has been completed
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index dc5c7b6..167f5e9 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -80,6 +80,7 @@
void clientReadPhy(in int clientIf, in String address);
void refreshDevice(in int clientIf, in String address);
void discoverServices(in int clientIf, in String address);
+ void discoverServiceByUuid(in int clientIf, in String address, in ParcelUuid uuid);
void readCharacteristic(in int clientIf, in String address, in int handle, in int authReq);
void readUsingCharacteristicUuid(in int clientIf, in String address, in ParcelUuid uuid,
in int startHandle, in int endHandle, in int authReq);
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 702b91c..7aaf453 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -617,7 +617,7 @@
int getInstallReason(String packageName, int userId);
- ParceledListSlice getSharedLibraries(int flags, int userId);
+ ParceledListSlice getSharedLibraries(in String packageName, int flags, int userId);
boolean canRequestPackageInstalls(String packageName, int userId);
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 426f3cf..87e6a84 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -341,4 +341,7 @@
* Return the taget SDK version for the app with the given UID.
*/
public abstract int getUidTargetSdkVersion(int uid);
+
+ /** Whether the binder caller can access instant apps. */
+ public abstract boolean canAccessInstantApps(int callingUid);
}
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 8e57e85..b00e65a 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -100,8 +100,8 @@
public static final int FINGERPRINT_ERROR_CANCELED = 5;
/**
- * The {@link FingerprintManager#remove(Fingerprint, RemovalCallback)} call failed. Typically
- * this will happen when the provided fingerprint id was incorrect.
+ * The {@link FingerprintManager#remove} call failed. Typically this will happen when the
+ * provided fingerprint id was incorrect.
*
* @hide
*/
@@ -398,10 +398,10 @@
};
/**
- * Callback structure provided to {@link FingerprintManager#remove(int). Users of
- * {@link #FingerprintManager()} may optionally provide an implementation of this to
- * {@link FingerprintManager#remove(int, int, RemovalCallback)} for listening to
- * fingerprint template removal events.
+ * Callback structure provided to {@link #remove}. Users of {@link FingerprintManager} may
+ * optionally provide an implementation of this to
+ * {@link #remove(Fingerprint, int, RemovalCallback)} for listening to fingerprint template
+ * removal events.
*
* @hide
*/
@@ -416,9 +416,13 @@
/**
* Called when a given fingerprint is successfully removed.
- * @param fingerprint the fingerprint template that was removed.
+ * @param fp The fingerprint template that was removed.
+ * @param remaining The number of fingerprints yet to be removed in this operation. If
+ * {@link #remove} is called on one fingerprint, this should be 0. If
+ * {@link #remove} is called on a group, this should be the number of remaining
+ * fingerprints in the group, and 0 after the last fingerprint is removed.
*/
- public void onRemovalSucceeded(Fingerprint fingerprint) { }
+ public void onRemovalSucceeded(Fingerprint fp, int remaining) { }
};
/**
@@ -878,8 +882,7 @@
msg.arg2 /* vendorCode */);
break;
case MSG_REMOVED:
- sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
- msg.arg2 /* groupId */);
+ sendRemovedResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
break;
case MSG_ENUMERATED:
sendEnumeratedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
@@ -888,21 +891,29 @@
}
}
- private void sendRemovedResult(long deviceId, int fingerId, int groupId) {
- if (mRemovalCallback != null) {
- int reqFingerId = mRemovalFingerprint.getFingerId();
- int reqGroupId = mRemovalFingerprint.getGroupId();
- if (reqFingerId != 0 && fingerId != 0 && fingerId != reqFingerId) {
- Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
- return;
- }
- if (groupId != reqGroupId) {
- Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
- return;
- }
- mRemovalCallback.onRemovalSucceeded(new Fingerprint(null, groupId, fingerId,
- deviceId));
+ private void sendRemovedResult(Fingerprint fingerprint, int remaining) {
+ if (mRemovalCallback == null) {
+ return;
}
+ if (fingerprint == null) {
+ Log.e(TAG, "Received MSG_REMOVED, but fingerprint is null");
+ return;
+ }
+
+ int fingerId = fingerprint.getFingerId();
+ int reqFingerId = mRemovalFingerprint.getFingerId();
+ if (reqFingerId != 0 && fingerId != 0 && fingerId != reqFingerId) {
+ Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
+ return;
+ }
+ int groupId = fingerprint.getGroupId();
+ int reqGroupId = mRemovalFingerprint.getGroupId();
+ if (groupId != reqGroupId) {
+ Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
+ return;
+ }
+
+ mRemovalCallback.onRemovalSucceeded(fingerprint, remaining);
}
private void sendEnumeratedResult(long deviceId, int fingerId, int groupId) {
@@ -1100,8 +1111,8 @@
@Override // binder call
public void onRemoved(long deviceId, int fingerId, int groupId, int remaining) {
- // TODO: propagate remaining
- mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
+ mHandler.obtainMessage(MSG_REMOVED, remaining, 0,
+ new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
}
@Override // binder call
diff --git a/core/java/android/net/NetworkRecommendationProvider.java b/core/java/android/net/NetworkRecommendationProvider.java
index d7b58f7..fdb4ba0 100644
--- a/core/java/android/net/NetworkRecommendationProvider.java
+++ b/core/java/android/net/NetworkRecommendationProvider.java
@@ -20,19 +20,14 @@
import android.annotation.SystemApi;
import android.content.Context;
import android.os.Build;
-import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
-import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.util.Log;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
-import java.util.Objects;
import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicBoolean;
/**
* The base class for implementing a network recommendation provider.
@@ -55,34 +50,10 @@
public abstract class NetworkRecommendationProvider {
private static final String TAG = "NetworkRecProvider";
private static final boolean VERBOSE = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.VERBOSE);
- /** The key into the callback Bundle where the RecommendationResult will be found.
- * @deprecated to be removed.
- * @removed
- */
- public static final String EXTRA_RECOMMENDATION_RESULT =
- "android.net.extra.RECOMMENDATION_RESULT";
- /** The key into the callback Bundle where the sequence will be found.
- * @deprecated to be removed.
- * @removed
- */
- public static final String EXTRA_SEQUENCE = "android.net.extra.SEQUENCE";
private final IBinder mService;
/**
* Constructs a new instance.
- * @param handler indicates which thread to use when handling requests. Cannot be {@code null}.
- * @deprecated use {@link #NetworkRecommendationProvider(Context, Executor)}
- * @removed
- */
- public NetworkRecommendationProvider(Handler handler) {
- if (handler == null) {
- throw new IllegalArgumentException("The provided handler cannot be null.");
- }
- mService = new ServiceWrapper(handler);
- }
-
- /**
- * Constructs a new instance.
* @param context the current context instance. Cannot be {@code null}.
* @param executor used to execute the incoming requests. Cannot be {@code null}.
*/
@@ -93,19 +64,6 @@
}
/**
- * Invoked when a recommendation has been requested.
- *
- * @param request a {@link RecommendationRequest} instance containing additional
- * request details
- * @param callback a {@link ResultCallback} instance. When a {@link RecommendationResult} is
- * available it must be passed into
- * {@link ResultCallback#onResult(RecommendationResult)}.
- * @deprecated to be removed.
- * @removed
- */
- public void onRequestRecommendation(RecommendationRequest request, ResultCallback callback) {}
-
- /**
* Invoked when network scores have been requested.
* <p>
* Use {@link NetworkScoreManager#updateScores(ScoredNetwork[])} to respond to score requests.
@@ -123,66 +81,6 @@
}
/**
- * A callback implementing applications should invoke when a {@link RecommendationResult}
- * is available.
- *
- * @deprecated to be removed.
- * @removed
- */
- public static class ResultCallback {
- private final IRemoteCallback mCallback;
- private final int mSequence;
- private final AtomicBoolean mCallbackRun;
-
- /**
- * @hide
- */
- @VisibleForTesting
- public ResultCallback(IRemoteCallback callback, int sequence) {
- mCallback = callback;
- mSequence = sequence;
- mCallbackRun = new AtomicBoolean(false);
- }
-
- /**
- * Run the callback with the available {@link RecommendationResult}.
- * @param result a {@link RecommendationResult} instance.
- */
- public void onResult(RecommendationResult result) {
- if (VERBOSE) Log.v(TAG, "onResult(seq=" + mSequence + ")");
- if (!mCallbackRun.compareAndSet(false, true)) {
- throw new IllegalStateException("The callback cannot be run more than once. "
- + "seq=" + mSequence);
- }
- final Bundle data = new Bundle();
- data.putInt(EXTRA_SEQUENCE, mSequence);
- data.putParcelable(EXTRA_RECOMMENDATION_RESULT, result);
- try {
- mCallback.sendResult(data);
- } catch (RemoteException e) {
- Log.w(TAG, "Callback failed for seq: " + mSequence, e);
- }
- if (VERBOSE) Log.v(TAG, "onResult() complete. seq=" + mSequence);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- ResultCallback that = (ResultCallback) o;
-
- return mSequence == that.mSequence
- && Objects.equals(mCallback, that.mCallback);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mCallback, mSequence);
- }
- }
-
- /**
* A wrapper around INetworkRecommendationProvider that dispatches to the provided Handler.
*/
private final class ServiceWrapper extends INetworkRecommendationProvider.Stub {
@@ -190,12 +88,6 @@
private final Executor mExecutor;
private final Handler mHandler;
- ServiceWrapper(Handler handler) {
- mHandler = handler;
- mExecutor = null;
- mContext = null;
- }
-
ServiceWrapper(Context context, Executor executor) {
mContext = context;
mExecutor = executor;
diff --git a/core/java/android/net/RecommendationRequest.java b/core/java/android/net/RecommendationRequest.java
deleted file mode 100644
index 21641d9..0000000
--- a/core/java/android/net/RecommendationRequest.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.net;
-
-
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * A request for a network recommendation.
- *
- * @see {@link NetworkScoreManager#requestRecommendation(RecommendationRequest)}.
- * @hide
- * @deprecated to be removed.
- * @removed
- */
-public final class RecommendationRequest implements Parcelable {
- private final ScanResult[] mScanResults;
- private final WifiConfiguration mDefaultConfig;
- private WifiConfiguration mConnectedConfig;
- private WifiConfiguration[] mConnectableConfigs;
- private final int mLastSelectedNetworkId;
- private final long mLastSelectedNetworkTimestamp;
-
- /**
- * Builder class for constructing {@link RecommendationRequest} instances.
- * @hide
- * @deprecated to be removed.
- * @removed
- */
- public static final class Builder {
- private ScanResult[] mScanResults;
- private WifiConfiguration mDefaultConfig;
- private WifiConfiguration mConnectedConfig;
- private WifiConfiguration[] mConnectableConfigs;
- private int mLastSelectedNetworkId = -1;
- private long mLastSelectedTimestamp;
-
- public Builder setScanResults(ScanResult[] scanResults) {
- mScanResults = scanResults;
- return this;
- }
-
- /**
- * @param config the {@link WifiConfiguration} to return if no recommendation is available.
- * @return this
- */
- public Builder setDefaultWifiConfig(WifiConfiguration config) {
- this.mDefaultConfig = config;
- return this;
- }
-
- /**
- * @param config the {@link WifiConfiguration} of the connected network at the time the
- * this request was made.
- * @return this
- */
- public Builder setConnectedWifiConfig(WifiConfiguration config) {
- this.mConnectedConfig = config;
- return this;
- }
-
- /**
- * @param connectableConfigs the set of saved {@link WifiConfiguration}s that can be
- * connected to based on the current set of {@link ScanResult}s.
- * @return this
- */
- public Builder setConnectableConfigs(WifiConfiguration[] connectableConfigs) {
- this.mConnectableConfigs = connectableConfigs;
- return this;
- }
-
- /**
- * @param networkId The {@link WifiConfiguration#networkId} of the last user selected
- * network.
- * @param timestamp The {@link android.os.SystemClock#elapsedRealtime()} when the user
- * selected {@code networkId}.
- * @return this
- */
- public Builder setLastSelectedNetwork(int networkId, long timestamp) {
- this.mLastSelectedNetworkId = networkId;
- this.mLastSelectedTimestamp = timestamp;
- return this;
- }
-
- /**
- * @return a new {@link RecommendationRequest} instance
- */
- public RecommendationRequest build() {
- return new RecommendationRequest(mScanResults, mDefaultConfig, mConnectedConfig,
- mConnectableConfigs, mLastSelectedNetworkId, mLastSelectedTimestamp);
- }
- }
-
- /**
- * @return the array of {@link ScanResult}s the recommendation must be constrained to i.e. if a
- * non-null wifi config recommendation is returned then it must be able to connect to
- * one of the networks in the results list.
- *
- * If the array is {@code null} or empty then there is no constraint.
- */
- public ScanResult[] getScanResults() {
- return mScanResults;
- }
-
- /**
- * @return the {@link WifiConfiguration} to return if no recommendation is available.
- */
- public WifiConfiguration getDefaultWifiConfig() {
- return mDefaultConfig;
- }
-
- /**
- * @return the {@link WifiConfiguration} of the connected network at the time the this request
- * was made.
- */
- public WifiConfiguration getConnectedConfig() {
- return mConnectedConfig;
- }
-
- /**
- * @return the set of saved {@link WifiConfiguration}s that can be connected to based on the
- * current set of {@link ScanResult}s.
- */
- public WifiConfiguration[] getConnectableConfigs() {
- return mConnectableConfigs;
- }
-
- /**
- * @param connectedConfig the {@link WifiConfiguration} of the connected network at the time
- * the this request was made.
- */
- public void setConnectedConfig(WifiConfiguration connectedConfig) {
- mConnectedConfig = connectedConfig;
- }
-
- /**
- * @param connectableConfigs the set of saved {@link WifiConfiguration}s that can be connected
- * to based on the current set of {@link ScanResult}s.
- */
- public void setConnectableConfigs(WifiConfiguration[] connectableConfigs) {
- mConnectableConfigs = connectableConfigs;
- }
-
- /**
- * @return The {@link WifiConfiguration#networkId} of the last user selected network.
- * {@code -1} if not set.
- */
- public int getLastSelectedNetworkId() {
- return mLastSelectedNetworkId;
- }
-
- /**
- * @return The {@link android.os.SystemClock#elapsedRealtime()} when the user selected
- * {@link #getLastSelectedNetworkId()}. {@code 0} if not set.
- */
- public long getLastSelectedNetworkTimestamp() {
- return mLastSelectedNetworkTimestamp;
- }
-
- @VisibleForTesting
- RecommendationRequest(ScanResult[] scanResults,
- WifiConfiguration defaultWifiConfig,
- WifiConfiguration connectedWifiConfig,
- WifiConfiguration[] connectableConfigs,
- int lastSelectedNetworkId,
- long lastSelectedNetworkTimestamp) {
- mScanResults = scanResults;
- mDefaultConfig = defaultWifiConfig;
- mConnectedConfig = connectedWifiConfig;
- mConnectableConfigs = connectableConfigs;
- mLastSelectedNetworkId = lastSelectedNetworkId;
- mLastSelectedNetworkTimestamp = lastSelectedNetworkTimestamp;
- }
-
- protected RecommendationRequest(Parcel in) {
- final int resultCount = in.readInt();
- if (resultCount > 0) {
- mScanResults = new ScanResult[resultCount];
- final ClassLoader classLoader = ScanResult.class.getClassLoader();
- for (int i = 0; i < resultCount; i++) {
- mScanResults[i] = in.readParcelable(classLoader);
- }
- } else {
- mScanResults = null;
- }
-
- mDefaultConfig = in.readParcelable(WifiConfiguration.class.getClassLoader());
- mConnectedConfig = in.readParcelable(WifiConfiguration.class.getClassLoader());
-
- final int configCount = in.readInt();
- if (configCount > 0) {
- mConnectableConfigs = new WifiConfiguration[configCount];
- final ClassLoader classLoader = WifiConfiguration.class.getClassLoader();
- for (int i = 0; i < configCount; i++) {
- mConnectableConfigs[i] = in.readParcelable(classLoader);
- }
- } else {
- mConnectableConfigs = null;
- }
-
- mLastSelectedNetworkId = in.readInt();
- mLastSelectedNetworkTimestamp = in.readLong();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- if (mScanResults != null) {
- dest.writeInt(mScanResults.length);
- for (int i = 0; i < mScanResults.length; i++) {
- dest.writeParcelable(mScanResults[i], flags);
- }
- } else {
- dest.writeInt(0);
- }
-
- dest.writeParcelable(mDefaultConfig, flags);
- dest.writeParcelable(mConnectedConfig, flags);
-
- if (mConnectableConfigs != null) {
- dest.writeInt(mConnectableConfigs.length);
- for (int i = 0; i < mConnectableConfigs.length; i++) {
- dest.writeParcelable(mConnectableConfigs[i], flags);
- }
- } else {
- dest.writeInt(0);
- }
-
- dest.writeInt(mLastSelectedNetworkId);
- dest.writeLong(mLastSelectedNetworkTimestamp);
- }
-
- public static final Creator<RecommendationRequest> CREATOR =
- new Creator<RecommendationRequest>() {
- @Override
- public RecommendationRequest createFromParcel(Parcel in) {
- return new RecommendationRequest(in);
- }
-
- @Override
- public RecommendationRequest[] newArray(int size) {
- return new RecommendationRequest[size];
- }
- };
-}
diff --git a/core/java/android/net/RecommendationResult.java b/core/java/android/net/RecommendationResult.java
deleted file mode 100644
index d66dd22..0000000
--- a/core/java/android/net/RecommendationResult.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.net;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.net.wifi.WifiConfiguration;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.util.Preconditions;
-
-/**
- * The result of a network recommendation.
- *
- * @see {@link NetworkScoreManager#requestRecommendation(RecommendationRequest)}.
- * @hide
- * @deprecated to be removed.
- * @removed
- */
-public final class RecommendationResult implements Parcelable {
- private final WifiConfiguration mWifiConfiguration;
-
- /**
- * Create a {@link RecommendationResult} that indicates that no network connection should be
- * attempted at this time.
- *
- * @return a {@link RecommendationResult}
- */
- public static RecommendationResult createDoNotConnectRecommendation() {
- return new RecommendationResult((WifiConfiguration) null);
- }
-
- /**
- * Create a {@link RecommendationResult} that indicates that a connection attempt should be
- * made for the given Wi-Fi network.
- *
- * @param wifiConfiguration {@link WifiConfiguration} with at least SSID and BSSID set.
- * @return a {@link RecommendationResult}
- */
- public static RecommendationResult createConnectRecommendation(
- @NonNull WifiConfiguration wifiConfiguration) {
- Preconditions.checkNotNull(wifiConfiguration, "wifiConfiguration must not be null");
- Preconditions.checkNotNull(wifiConfiguration.SSID, "SSID must not be null");
- Preconditions.checkNotNull(wifiConfiguration.BSSID, "BSSID must not be null");
- return new RecommendationResult(wifiConfiguration);
- }
-
- private RecommendationResult(@Nullable WifiConfiguration wifiConfiguration) {
- mWifiConfiguration = wifiConfiguration;
- }
-
- private RecommendationResult(Parcel in) {
- mWifiConfiguration = in.readParcelable(WifiConfiguration.class.getClassLoader());
- }
-
- /**
- * @return {@code true} if a network recommendation exists. {@code false} indicates that
- * no connection should be attempted at this time.
- */
- public boolean hasRecommendation() {
- return mWifiConfiguration != null;
- }
-
- /**
- * @return The recommended {@link WifiConfiguration} to connect to. A {@code null} value
- * is returned if {@link #hasRecommendation} returns {@code false}.
- */
- @Nullable public WifiConfiguration getWifiConfiguration() {
- return mWifiConfiguration;
- }
-
- @Override
- public String toString() {
- return "RecommendationResult{" +
- "mWifiConfiguration=" + mWifiConfiguration +
- "}";
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(mWifiConfiguration, flags);
- }
-
- public static final Creator<RecommendationResult> CREATOR =
- new Creator<RecommendationResult>() {
- @Override
- public RecommendationResult createFromParcel(Parcel in) {
- return new RecommendationResult(in);
- }
-
- @Override
- public RecommendationResult[] newArray(int size) {
- return new RecommendationResult[size];
- }
- };
-}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 86fcfc8..4bad7ab 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -758,7 +758,7 @@
/**
* O.
*/
- public static final int O = CUR_DEVELOPMENT; // STOPSHIP Replace with the real version.
+ public static final int O = 26;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index e4cdbce..f9eaba9 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -20,6 +20,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.opengl.EGL14;
+import android.os.Build;
import android.os.SystemProperties;
import android.util.Log;
@@ -81,6 +82,12 @@
}
return;
}
+ if (driverInfo.targetSdkVersion < Build.VERSION_CODES.O) {
+ // O drivers are restricted to the sphal linker namespace, so don't try to use
+ // packages unless they declare they're compatible with that restriction.
+ Log.w(TAG, "updated driver package is not known to be compatible with O");
+ return;
+ }
StringBuilder sb = new StringBuilder();
sb.append(driverInfo.nativeLibraryDir)
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 3212139..c091420 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -547,7 +547,8 @@
* Converts a string representing a file mode, such as "rw", into a bitmask suitable for use
* with {@link #open}.
* <p>
- * @param mode The string representation of the file mode.
+ * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw"
+ * or "rwt".
* @return A bitmask representing the given file mode.
* @throws IllegalArgumentException if the given string does not match a known file mode.
*/
diff --git a/core/java/android/os/ProxyFileDescriptorCallback.java b/core/java/android/os/ProxyFileDescriptorCallback.java
index e69fb55..9f56802 100644
--- a/core/java/android/os/ProxyFileDescriptorCallback.java
+++ b/core/java/android/os/ProxyFileDescriptorCallback.java
@@ -22,7 +22,23 @@
/**
* Callback that handles file system requests from ProxyFileDescriptor.
*
- * @see android.os.storage.StorageManager#openProxyFileDescriptor(int, ProxyFileDescriptorCallback)
+ * All callback methods except for onRelease should throw {@link android.system.ErrnoException}
+ * with proper errno on errors. See
+ * <a href="http://man7.org/linux/man-pages/man3/errno.3.html">errno(3)</a> and
+ * {@link android.system.OsConstants}.
+ *
+ * Typical errnos are
+ *
+ * <ul>
+ * <li>{@link android.system.OsConstants#EIO} for general I/O issues
+ * <li>{@link android.system.OsConstants#ENOENT} when the file is not found
+ * <li>{@link android.system.OsConstants#EBADF} if the file doesn't allow read/write operations
+ * based on how it was opened. (For example, trying to write a file that was opened read-only.)
+ * <li>{@link android.system.OsConstants#ENOSPC} if you cannot handle a write operation to
+ * space/quota limitations.
+ * </ul>
+ * @see android.os.storage.StorageManager#openProxyFileDescriptor(int, ProxyFileDescriptorCallback,
+ * Handler)
*/
public abstract class ProxyFileDescriptorCallback {
/**
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index 97da588..17f00c2 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -167,4 +167,12 @@
* Remove user's running state
*/
public abstract void removeUserState(int userId);
+
+ /**
+ * Returns an array of user ids. This array is cached in UserManagerService and passed as a
+ * reference, so do not modify the returned array.
+ *
+ * @return the array of user ids.
+ */
+ public abstract int[] getUserIds();
}
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 2cc4b71..92f7f31 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -295,4 +295,5 @@
long getCacheSizeBytes(String volumeUuid, int uid) = 76;
long getAllocatableBytes(String volumeUuid, int flags) = 77;
void allocateBytes(String volumeUuid, long bytes, int flags) = 78;
+ void secdiscard(in String path) = 79;
}
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index bd43d6a..f361c54 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1252,6 +1252,15 @@
}
/** {@hide} */
+ public void secdiscard(String path) {
+ try {
+ mStorageManager.secdiscard(path);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** {@hide} */
public static boolean isUserKeyUnlocked(int userId) {
if (sStorageManager == null) {
sStorageManager = IStorageManager.Stub
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 2a83c4b..3eef31a 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -655,8 +655,12 @@
* <p>
* Your provider should return a reliable {@link ParcelFileDescriptor} to
* detect when the remote caller has finished reading or writing the
- * document. You may return a pipe or socket pair if the mode is exclusively
- * "r" or "w", but complex modes like "rw" imply a normal file on disk that
+ * document.
+ * <p>
+ * Mode "r" should always be supported. Provider should throw
+ * {@link UnsupportedOperationException} if the passing mode is not supported.
+ * You may return a pipe or socket pair if the mode is exclusively "r" or
+ * "w", but complex modes like "rw" imply a normal file on disk that
* supports seeking.
* <p>
* If you block while downloading content, you should periodically check
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 2ade9b5..9cea4ed 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -245,6 +245,7 @@
super.onAttachedToWindow();
getViewRootImpl().addWindowStoppedCallback(this);
+ mWindowStopped = false;
mParent.requestTransparentRegion(this);
mViewVisibility = getVisibility() == VISIBLE;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d3d753b..2d48295 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20506,6 +20506,9 @@
* @throws IllegalStateException if the drawable could not be found.
*/
@Nullable private Drawable getAutofilledDrawable() {
+ if (mAttachInfo == null) {
+ return null;
+ }
// Lazily load the isAutofilled drawable.
if (mAttachInfo.mAutofilledDrawable == null) {
Context rootContext = getRootView().getContext();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 109cac0..28ded55 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1561,16 +1561,6 @@
host.dispatchApplyWindowInsets(getWindowInsets(true /* forceConstruct */));
}
- /**
- * @return the last content insets for use in adjusting the source hint rect for the
- * picture-in-picture transition.
- *
- * @hide
- */
- public Rect getLastContentInsets() {
- return mAttachInfo.mContentInsets;
- }
-
private static boolean shouldUseDisplaySize(final WindowManager.LayoutParams lp) {
return lp.type == TYPE_STATUS_BAR_PANEL
|| lp.type == TYPE_INPUT_METHOD
@@ -2411,6 +2401,9 @@
}
private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
+ if (mView == null) {
+ return;
+ }
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");
try {
mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 3605585..05d0f96 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -248,7 +248,7 @@
mRadialTimePickerHeader.setVisibility(View.GONE);
mTextInputPickerHeader.setVisibility(View.VISIBLE);
mTextInputPickerView.setVisibility(View.VISIBLE);
- mRadialTimePickerModeButton.setImageResource(R.drawable.btn_event_material);
+ mRadialTimePickerModeButton.setImageResource(R.drawable.btn_clock_material);
mRadialTimePickerModeButton.setContentDescription(
mRadialTimePickerModeEnabledDescription);
mRadialPickerModeEnabled = false;
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 13ebe5c..d807120 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -449,6 +449,11 @@
public void handleShow(IBinder windowToken) {
if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
+ " mNextView=" + mNextView);
+ // If a cancel/hide is pending - no need to show - at this point
+ // the window token is already invalid and no need to do any work.
+ if (mHandler.hasMessages(CANCEL) || mHandler.hasMessages(HIDE)) {
+ return;
+ }
if (mView != mNextView) {
// remove the old view if necessary
handleHide();
@@ -483,8 +488,16 @@
mWM.removeView(mView);
}
if (localLOGV) Log.v(TAG, "ADD! " + mView + " in " + this);
- mWM.addView(mView, mParams);
- trySendAccessibilityEvent();
+ // Since the notification manager service cancels the token right
+ // after it notifies us to cancel the toast there is an inherent
+ // race and we may attempt to add a window after the token has been
+ // invalidated. Let us hedge against that.
+ try {
+ mWM.addView(mView, mParams);
+ trySendAccessibilityEvent();
+ } catch (WindowManager.BadTokenException e) {
+ /* ignore */
+ }
}
}
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index 797cf2b..d279746 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -47,6 +47,7 @@
public static String RETAIL_MODE = "RETAIL_MODE";
public static String USB = "USB";
public static String FOREGROUND_SERVICE = "FOREGROUND_SERVICE";
+ public static String ALERT_WINDOW = "ALERT_WINDOW";
public static void createAll(Context context) {
final NotificationManager nm = context.getSystemService(NotificationManager.class);
@@ -137,6 +138,11 @@
context.getString(R.string.notification_channel_foreground_service),
NotificationManager.IMPORTANCE_MIN));
+ channelsList.add(new NotificationChannel(
+ ALERT_WINDOW,
+ context.getString(R.string.alert_windows_notification_channel_name),
+ NotificationManager.IMPORTANCE_MIN));
+
nm.createNotificationChannels(channelsList);
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 0d0d099..b9d3a30 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -10129,7 +10129,7 @@
@Override
public void onUidCpuFreqTime(int uid, long[] cpuFreqTimeMs) {
- final Uid u = getUidStatsLocked(uid);
+ final Uid u = getUidStatsLocked(mapUid(uid));
if (u.mCpuFreqTimeMs == null) {
u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
}
diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java
index e86932c..6b53368 100644
--- a/core/java/com/android/internal/widget/ImageFloatingTextView.java
+++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java
@@ -169,4 +169,8 @@
}
return false;
}
+
+ public int getLayoutHeight() {
+ return getLayout().getHeight();
+ }
}
diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java
index 1104318..70473a0 100644
--- a/core/java/com/android/internal/widget/MessagingLinearLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java
@@ -138,7 +138,7 @@
first = false;
boolean measuredTooSmall = false;
if (textChild != null) {
- measuredTooSmall = childHeight < textChild.getLayout().getHeight()
+ measuredTooSmall = childHeight < textChild.getLayoutHeight()
+ textChild.getPaddingTop() + textChild.getPaddingBottom();
}
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index b529e37..214d97c 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -60,17 +60,14 @@
static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jobject jbitmap,
jint tileModeX, jint tileModeY) {
const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
- sk_sp<SkImage> image;
+ SkBitmap bitmap;
if (jbitmap) {
// Only pass a valid SkBitmap object to the constructor if the Bitmap exists. Otherwise,
// we'll pass an empty SkBitmap to avoid crashing/excepting for compatibility.
- image = android::bitmap::toBitmap(env, jbitmap).makeImage(nullptr);
+ android::bitmap::toBitmap(env, jbitmap).getSkBitmapForShaders(&bitmap);
}
- if (!image.get()) {
- SkBitmap bitmap;
- image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
- }
+ sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
sk_sp<SkShader> baseShader = image->makeShader(
(SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY);
diff --git a/core/jni/android_app_ApplicationLoaders.cpp b/core/jni/android_app_ApplicationLoaders.cpp
index 3e7c039..8bbf24a 100644
--- a/core/jni/android_app_ApplicationLoaders.cpp
+++ b/core/jni/android_app_ApplicationLoaders.cpp
@@ -32,7 +32,7 @@
loader_data.layer_path = layerPathChars.c_str();
loader_data.app_namespace = ns;
} else {
- ALOGD("ignored Vulkan layer search path %s for namespace %p",
+ ALOGV("Vulkan layer search path already set, not clobbering with '%s' for namespace %p'",
layerPathChars.c_str(), ns);
}
}
diff --git a/core/res/res/drawable/btn_event_material.xml b/core/res/res/drawable/btn_clock_material.xml
similarity index 73%
rename from core/res/res/drawable/btn_event_material.xml
rename to core/res/res/drawable/btn_clock_material.xml
index 47c49cf..f785ebf 100644
--- a/core/res/res/drawable/btn_event_material.xml
+++ b/core/res/res/drawable/btn_clock_material.xml
@@ -18,12 +18,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
-
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
<path
android:fillColor="#90ffffff"
- android:pathData="M17 12h-5v5h5v-5zM16 1v2H8V1H6v2H5c-1.11 0-1.99 .9 -1.99 2L3 19c0 1.1 .89 2 2
-2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2zm3 18H5V8h14v11z" />
- <path android:pathData="M0 0h24v24H0z" />
-</vector>
\ No newline at end of file
+ android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z"/>
+</vector>
diff --git a/core/res/res/layout-land/time_picker_material.xml b/core/res/res/layout-land/time_picker_material.xml
index 8b95f9f..863efef 100644
--- a/core/res/res/layout-land/time_picker_material.xml
+++ b/core/res/res/layout-land/time_picker_material.xml
@@ -20,11 +20,10 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
- <LinearLayout
+ <RelativeLayout
android:id="@+id/time_header"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:orientation="vertical"
android:gravity="center"
android:paddingStart="?attr/dialogPreferredPadding"
android:paddingEnd="?attr/dialogPreferredPadding">
@@ -112,7 +111,7 @@
android:includeFontPadding="false"
android:button="@null" />
</RadioGroup>
- </LinearLayout>
+ </RelativeLayout>
<TextView
android:visibility="gone"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index be38c83..bafd40d 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Opdaterings"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Netwerkstatus"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Netwerkwaarskuwings"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Netwerk is beskikbaar"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-status"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Toesteladministrasie"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Opletberigte"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vingerafdrukuittelling is bereik. Probeer weer."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Vingerafdrukhandeling is gekanselleer."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Te veel pogings. Probeer later weer."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Probeer weer."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Vinger <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index fa2d60b..d91c185 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"ዝማኔዎች"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"የአውታረ መረብ ሁኔታ"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"የአውታረ መረብ ማንቂያዎች"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"አውታረ መረብ ይገኛል"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"የቪፒኤን ሁኔታ"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"የመሣሪያ አስተዳደር"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"ማንቂያዎች"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"የጣት አሻራ ማብቂያ ጊዜ ደርሷል። እንደገና ይሞክሩ።"</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"የጣት አሻራ ስርዓተ ክወና ተትቷል።"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"ከልክ በላይ ብዙ ሙከራዎች። በኋላ ላይ እንደገና ይሞክሩ።"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"እንደገና ይሞክሩ።"</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"ጣት <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 91d360f..2646333 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -272,8 +272,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"التحديثات"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"حالة الشبكة"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"تنبيهات الشبكة"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"الشبكة متوفرة"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"حالة الشبكة الظاهرية الخاصة"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"إدارة الجهاز"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"التنبيهات"</string>
@@ -504,6 +503,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"تم بلوغ مهلة إدخال بصمة الإصبع. أعد المحاولة."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"تم إلغاء تشغيل بصمة الإصبع."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"تم إجراء عدد كبير من المحاولات. أعد المحاولة لاحقًا."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"أعد المحاولة."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"الإصبع <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index f5fe77e..a4a3881 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Güncəlləmələr"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Şəbəkə statusu"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Şəbəkə siqnalları"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Şəbəkə əlçatandır"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN statusu"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Cihaz administrasiyası"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Siqnallar"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Barmaq izinin vaxtı başa çatdı. Yenidən cəhd edin."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Barmaq izi əməliyyatı ləğv edildi."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Cəhdlər çox oldu. Sonraya saxlayın."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Yenidən cəhd edin."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Barmaq <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 9cee985..ebb5cd0 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -263,8 +263,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Ažuriranja"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Status mreže"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Obaveštenja u vezi sa mrežom"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Mreža je dostupna"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Status VPN-a"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Administriranje uređaja"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Obaveštenja"</string>
@@ -495,6 +494,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vremensko ograničenje za otisak prsta je isteklo. Probajte ponovo."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja sa otiskom prsta je otkazana."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Probajte ponovo kasnije."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Probajte ponovo."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 2f46637..32cec88 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -266,8 +266,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Абнаўленні"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Стан сеткі"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Абвесткі сеткі"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Сетка даступная"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Стан VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Адміністраванне прылады"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Абвесткi"</string>
@@ -498,6 +497,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час чакання адбіткаў пальцаў выйшаў. Паспрабуйце яшчэ раз."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Аперацыя з адбіткамі пальцаў скасавана."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Занадта шмат спроб. Паспрабуйце яшчэ раз пазней."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Паспрабуйце яшчэ раз."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Палец <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 42dfd9b..e72b2f9 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Времето за изчакване за отпечатък изтече. Опитайте отново."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Операцията за отпечатък е анулирана."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Твърде много опити. Пробвайте отново по-късно."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Опитайте отново."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Пръст <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index d185ad5..954c910 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"আঙ্গুলের ছাপ নেওয়ার সময়সীমা শেষ হযেছে৷ আবার চেষ্টা করুন৷"</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"আঙ্গুলের ছাপ অপারেশন বাতিল করা হয়েছে৷"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"অনেকবার প্রচেষ্টা করা হয়েছে৷ পরে আবার চেষ্টা করুন৷"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"আবার চেষ্টা করুন৷"</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"আঙ্গুল <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index cedc392..101afb7 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -263,8 +263,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Ažuriranja"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Status mreže"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Mrežna upozorenja"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Mreža je dostupna"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Status VPN-a"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Administracija uređaja"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string>
@@ -495,6 +494,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vremensko ograničenje za otisak prsta je isteklo. Pokušajte ponovo."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja sa otiskom prsta je otkazana."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Pokušajte ponovo."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 04afd6c..e928cd9 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Actualitzacions"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Estat de la xarxa"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertes de xarxa"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Hi ha una xarxa disponible"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Estat de la VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Administració del dispositiu"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"S\'ha esgotat el temps d\'espera per a l\'empremta digital. Torna-ho a provar."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"S\'ha cancel·lat l\'operació d\'empremta digital."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"S\'han produït massa intents. Torna-ho a provar més tard."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Torna-ho a provar."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Dit <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 0cffb88..5b5dbcf 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -266,8 +266,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Aktualizace"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Stav sítě"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Síťová upozornění"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"K dispozici je síť"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Stav sítě VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Administrace zařízení"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornění"</string>
@@ -498,6 +497,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit sejmutí otisku prstu vypršel. Zkuste to znovu."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operace otisku prstu byla zrušena."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Příliš mnoho pokusů. Zkuste to později."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Zkuste to znovu."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 15a3fee..441a25b 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Opdateringer"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Netværksstatus"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Netværksunderretninger"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Tilgængeligt netværk"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-status"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Enhedsadministration"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Underretninger"</string>
@@ -301,7 +300,7 @@
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"observere tekst, du skriver"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Dette omfatter personlige data såsom kreditkortnumre og adgangskoder."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"administrere skærmforstørrelsen"</string>
- <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Kontrollér skærmens zoomniveau og position."</string>
+ <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Tjek skærmens zoomniveau og position."</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Udfør bevægelser"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Kan trykke, stryge, knibe sammen og udføre andre bevægelser."</string>
<string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingeraftryksbevægelser"</string>
@@ -408,8 +407,8 @@
<string name="permdesc_sim_communication" msgid="5725159654279639498">"Tillader, at appen sender kommandoer til SIM-kortet. Dette er meget farligt."</string>
<string name="permlab_camera" msgid="3616391919559751192">"tage billeder og optage video"</string>
<string name="permdesc_camera" msgid="5392231870049240670">"Med denne app kan du tage billeder og optage video med kameraet når som helst."</string>
- <string name="permlab_vibrate" msgid="7696427026057705834">"kontrollere vibration"</string>
- <string name="permdesc_vibrate" msgid="6284989245902300945">"Tillader, at appen kan kontrollere vibratoren."</string>
+ <string name="permlab_vibrate" msgid="7696427026057705834">"administrere vibration"</string>
+ <string name="permdesc_vibrate" msgid="6284989245902300945">"Tillader, at appen kan administrere vibratoren."</string>
<string name="permlab_callPhone" msgid="3925836347681847954">"ringe direkte op til telefonnumre"</string>
<string name="permdesc_callPhone" msgid="3740797576113760827">"Tillader, at appen kan ringe til telefonnumre uden din indgriben. Dette kan resultere i uventede opkrævninger eller opkald. Bemærk, at appen med denne tilladelse ikke kan ringe til nødopkaldsnumre. Skadelige apps kan koste dig penge ved at foretage opkald uden din bekræftelse."</string>
<string name="permlab_accessImsCallService" msgid="3574943847181793918">"få adgang til chat-opkaldstjeneste"</string>
@@ -472,7 +471,7 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Tillader, at appen kan læse konfigurationen af Bluetooth på tabletten samt kan oprette og acceptere forbindelser med parrede enheder."</string>
<string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"Giver appen lov til at se fjernsynets Bluetooth-konfiguration og til at oprette og acceptere forbindelser til parrede enheder."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Tillader, at appen kan læse konfigurationen af Bluetooth på telefonen samt kan oprette og acceptere forbindelser med parrede enheder."</string>
- <string name="permlab_nfc" msgid="4423351274757876953">"kontrollere Near Field Communication"</string>
+ <string name="permlab_nfc" msgid="4423351274757876953">"administrere Near Field Communication"</string>
<string name="permdesc_nfc" msgid="7120611819401789907">"Tillader, at appen kan kommunikere med NFC-tags (Near Field Communication), -kort og -læsere."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"deaktivere din skærmlås"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Tillader, at appen kan deaktivere tastaturlåsen og anden form for tilknyttet adgangskodesikkerhed. Telefonen deaktiverer f.eks. tastaturlåsen ved indgående telefonopkald og aktiverer tastaturlåsen igen, når opkaldet er afsluttet."</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Registrering af fingeraftryk fik timeout. Prøv igen."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingeraftrykshandlingen blev annulleret."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Du har prøvet for mange gange. Prøv igen senere."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Prøv igen."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Fingeraftryk <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
@@ -558,7 +559,7 @@
<string name="permlab_access_notification_policy" msgid="4247510821662059671">"have adgang til Forstyr ikke"</string>
<string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Giver appen tilladelse til at læse og skrive konfigurationen af Forstyr ikke."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Angiv regler for adgangskoder"</string>
- <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrollér længden samt tilladte tegn i adgangskoder og pinkoder til skærmlåsen."</string>
+ <string name="policydesc_limitPassword" msgid="2502021457917874968">"Tjek længden samt tilladte tegn i adgangskoder og pinkoder til skærmlåsen."</string>
<string name="policylab_watchLogin" msgid="5091404125971980158">"Overvåg forsøg på oplåsning af skærm"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Overvåg antallet af forkert indtastede adgangskoder, når du låser skærmen op, og lås din tablet, eller slet alle data i den, hvis der er indtastet for mange forkerte adgangskoder."</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Overvåg antallet af forkert indtastede adgangskoder ved oplåsning af skærmen, og lås tv\'et eller slet alle dets data, hvis der indtastes for mange forkerte adgangskoder."</string>
@@ -1291,7 +1292,7 @@
<string name="vpn_text" msgid="1610714069627824309">"Tryk for at administrere netværket."</string>
<string name="vpn_text_long" msgid="4907843483284977618">"Forbundet til <xliff:g id="SESSION">%s</xliff:g>. Tryk for at administrere netværket."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Opretter forbindelse til altid aktiveret VPN…"</string>
- <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN er forbundet"</string>
+ <string name="vpn_lockdown_connected" msgid="8202679674819213931">"Altid aktiveret VPN er forbundet"</string>
<string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Forbindelsen til altid aktiveret VPN er afbrudt"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Fejl i altid aktiveret VPN"</string>
<string name="vpn_lockdown_config" msgid="5099330695245008680">"Tryk for at konfigurere"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 6d1ebc8..c158ad5 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Updates"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Netzwerkstatus"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Netzwerkwarnungen"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Netzwerk verfügbar"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-Status"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Geräteverwaltung"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Warnmeldungen"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Zeitüberschreitung für Fingerabdruck. Versuche es erneut."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerabdruckvorgang abgebrochen"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Zu viele Versuche. Versuche es später erneut."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Bitte versuche es erneut."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index d61fdca..10db204 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Ενημερώσεις"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Κατάσταση δικτύου"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Ειδοποιήσεις δικτύου"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Το δίκτυο είναι διαθέσιμο"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Κατάσταση VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Διαχείριση συσκευής"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Ειδοποιήσεις"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Λήξη χρονικού ορίου μοναδικού χαρακτηριστικού. Δοκιμάστε ξανά."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Η λειτουργία μοναδικού χαρακτηριστικού ακυρώθηκε."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Πάρα πολλές προσπάθειες. Δοκιμάστε ξανά αργότερα."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Δοκιμάστε ξανά."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Δάχτυλο <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index c076e16..8a1b42c 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Updates"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Network status"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Network alerts"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Network available"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN status"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Device administration"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerprint operation cancelled."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Too many attempts. Try again later."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Try again."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index c076e16..8a1b42c 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Updates"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Network status"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Network alerts"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Network available"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN status"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Device administration"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerprint operation cancelled."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Too many attempts. Try again later."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Try again."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index c076e16..8a1b42c 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Updates"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Network status"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Network alerts"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Network available"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN status"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Device administration"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alerts"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerprint operation cancelled."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Too many attempts. Try again later."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Try again."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index ab195df..ba5af6d 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Actualizaciones"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Estado de la red"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertas de red"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Red disponible"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Estado de VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Administración del dispositivo"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Finalizó el tiempo de espera para la huella digital. Vuelve a intentarlo."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Se canceló la operación de huella digital."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiados intentos. Vuelve a intentarlo más tarde."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Vuelve a intentarlo."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
@@ -1754,7 +1755,7 @@
<string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"Opciones de autocompletar"</string>
<string name="autofill_save_accessibility_title" msgid="7244365268417107822">"Guardar para Autocompletar"</string>
<string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"El contenido no puede autocompletarse"</string>
- <string name="autofill_picker_no_suggestions" msgid="3908514303773350735">"Sin sugerencias de Autocompletar"</string>
+ <string name="autofill_picker_no_suggestions" msgid="3908514303773350735">"No hay sugerencias de Autocompletar"</string>
<plurals name="autofill_picker_some_suggestions" formatted="false" msgid="5506565809835815274">
<item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugerencias de Autocompletar</item>
<item quantity="one">Una sugerencia de Autocompletar</item>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 0891aa2..9369ee5 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Actualizaciones"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Estado de la red"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertas de la red"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Red disponible"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Estado de la VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Administración del dispositivo"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Se ha alcanzado el tiempo de espera de la huella digital. Vuelve a intentarlo."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Se ha cancelado la operación de huella digital."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiados intentos. Vuelve a intentarlo más tarde."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Vuelve a intentarlo."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 95d6bb0..d85a37f 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Värskendused"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Võrgu olek"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Võrguteavitused"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Võrk on saadaval"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-i olek"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Seadme haldamine"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Teatised"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Sõrmejälje riistvara taimeri ajalõpp. Proovige uuesti."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Sõrmejälje toiming tühistati."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Liiga palju katseid. Proovige hiljem uuesti."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Proovige uuesti."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Sõrm <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 2208e91..2abdeef 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Eguneratzeak"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Sarearen egoera"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Sarearen alertak"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Sare bat erabilgarri dago"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN egoera"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Gailuen administrazioa"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Abisuak"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Hatz-marka digitalak prozesatzeko denbora-muga gainditu da. Saiatu berriro."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Hatz-markaren eragiketa bertan behera utzi da."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Saiakera gehiegi egin dituzu. Saiatu berriro geroago."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Saiatu berriro."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> hatza"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 942bc88..319a5a1 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"مهلت زمانی ثبت اثر انگشت به پایان رسید. دوباره امتحان کنید."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"عملکرد اثر انگشت لغو شد."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"تلاشهای زیادی انجام شده است. بعداً دوباره امتحان کنید."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"دوباره امتحان کنید."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"انگشت <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 69b4b3c..f8fd2b3 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Päivitykset"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Verkon tila"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Verkkoilmoitukset"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Verkko käytettävissä"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-tila"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Laitteen järjestelmänvalvonta"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Ilmoitukset"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Sormenjälkitunnistimen toiminta aikakatkaistiin. Yritä uudelleen."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Sormenjälkitoiminto peruutettiin."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Liian monta yritystä. Yritä myöhemmin uudelleen."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Yritä uudelleen."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Sormi <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 7e62890..15071e9 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Le temps attribué pour lire l\'empreinte est écoulé. Veuillez essayer de nouveau."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Opération d\'empreinte numérique annulée."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Trop de tentatives. Veuillez réessayer plus tard."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Réessayer."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Doigt <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 2f6ea57..6a1b8b7 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Mises à jour"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"État du réseau"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertes réseau"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Réseau disponible"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"État du VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Gestion de l\'appareil"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Délai de détection de l\'empreinte numérique expiré. Veuillez réessayer."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Opération d\'empreinte numérique annulée."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Trop de tentatives. Veuillez réessayer plus tard."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Veuillez réessayer."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Doigt <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index aeae75b..cfbb5c3 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Actualizacións"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Estado da rede"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertas de rede"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"A rede está dispoñible"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Estado da VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Administración de dispositivos"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Esgotouse o tempo de espera da impresión dixital. Téntao de novo."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Cancelouse a operación da impresión dixital."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiados intentos. Téntao de novo máis tarde."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Téntao de novo."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index ab0edb8..e78dfa9 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"અપડેટ્સ"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"નેટવર્ક સ્થિતિ"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"નેટવર્ક ચેતવણીઓ"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"નેટવર્ક ઉપલબ્ધ છે"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN સ્થિતિ"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"ઉપકરણ વ્યવસ્થાપન"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"ચેતવણીઓ"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"ફિંગરપ્રિન્ટનો સમય બાહ્ય થયો. ફરી પ્રયાસ કરો."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"ફિંગરપ્રિન્ટ ઓપરેશન રદ કર્યું."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"ઘણા બધા પ્રયત્નો. પછીથી ફરી પ્રયાસ કરો."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ફરી પ્રયાસ કરો."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"આંગળી <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index f7bcbc6..30be4d5 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"अपडेट"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"नेटवर्क की स्थिति"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"नेटवर्क संबंधी सूचनाएं"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"नेटवर्क उपलब्ध है"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN की स्थिति"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"डिवाइस का व्यवस्थापन"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"सूचनाएं"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"फ़िंगरप्रिंट का समय समाप्त हो गया. पुनः प्रयास करें."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"फ़िंगरप्रिंट क्रियान्वयन रोक दिया गया."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"बहुत अधिक प्रयास कर लिए गए हैं. बाद में पुन: प्रयास करें."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"पुन: प्रयास करें."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"अंगुली <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index b2c325f..9eaf027 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -263,8 +263,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Ažuriranja"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Mrežni status"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Mrežna upozorenja"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Mreža je dostupna"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Status VPN-a"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Administracija uređaja"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Upozorenja"</string>
@@ -495,6 +494,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Isteklo je vrijeme čekanja za otisak prsta. Pokušajte ponovo."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja otiska prsta otkazana je."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Pokušajte ponovo."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 64e1c8a..1270eb3 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Az ujjlenyomat-beolvasási műveletkor időtúllépés történt. Próbálkozzon újra."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Ujjlenyomattal kapcsolatos művelet megszakítva"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Túl sok próbálkozás. Próbálja újra később."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Próbálkozzon újra."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g>. ujj"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index be3cfdd..28a01c0 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Թարմացումներ"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Ցանցի կարգավիճակ"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Ցանցային զգուշացումներ"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Ցանցը հասանելի է"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN կարգավիճակ"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Սարքի կառավարում"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Ծանուցումներ"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Մատնահետքի գրանցման ժամանակը սպառվել է: Փորձեք նորից:"</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Իսկորոշումը մատնահետքի միջոցով չեղարկվեց:"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Չափից շատ փորձ եք կատարել: Փորձեք նորից քիչ հետո:"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Փորձեք նորից:"</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Մատնահետք <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 2fda698..e7d160b 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Update"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Status jaringan"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Notifikasi jaringan"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Jaringan tersedia"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Status VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Administrasi perangkat"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Notifikasi"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Waktu sidik jari habis. Coba lagi."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operasi sidik jari dibatalkan."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Terlalu banyak upaya. Coba lagi nanti."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Coba lagi."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Jari <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index b43b21e..8313cba12 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Uppfærslur"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Staða netkerfis"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Viðvaranir netkerfis"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Net í boði"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Staða VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Stjórnun tækis"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Tilkynningar"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tímamörk runnu út fyrir fingrafar. Reyndu aftur."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Hætt við fingrafarsaðgerð."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Of margar tilraunir. Reyndu aftur síðar."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Reyndu aftur."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Fingur <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index b9af901..53c00b2 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Aggiornamenti"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Stato della rete"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Avvisi di rete"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Rete disponibile"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Stato della VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Amministrazione dispositivo"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Avvisi"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Timeout impronta digitale. Riprova."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operazione associata all\'impronta digitale annullata."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Troppi tentativi. Riprova più tardi."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Riprova."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Dito <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 29579ec..7761209 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -266,8 +266,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"עדכונים"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"סטטוס הרשת"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"התראות רשת"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"יש רשת זמינה"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"סטטוס ה-VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"ניהול מכשירים"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"התראות"</string>
@@ -498,6 +497,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"חלף הזמן הקצוב לטביעת אצבע. נסה שוב."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"פעולת טביעת האצבע בוטלה."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"יותר מדי ניסיונות. נסה שוב מאוחר יותר."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"נסה שוב."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"אצבע <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 3f5044b..b3af109 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"アップデート"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"ネットワークのステータス"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"ネットワーク通知"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"ネットワークを利用できます"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN のステータス"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"端末管理"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"指紋の読み取りがタイムアウトになりました。もう一度お試しください。"</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"指紋の操作をキャンセルしました。"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"所定の回数以上間違えました。しばらくしてからもう一度お試しください。"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"もう一度お試しください。"</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"指紋<xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index c193ee8..1301220 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"თითის ანაბეჭდის ლოდინის დრო ამოიწურა. სცადეთ ხელახლა."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"თითის ანაბეჭდის აღების ოპერაცია გაუქმდა."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"ძალიან ბევრი მცდელობა იყო. სცადეთ მოგვიანებით."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ხელახლა სცადეთ"</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"თითი <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index c2cf55f..4c9cd5d 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Жаңартылған нұсқалар"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Желі күйі"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Желі дабылдары"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Желі қолжетімді"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN күйі"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Құрылғыны басқару"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Дабылдар"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Саусақ ізін күту уақыты бітті. Әрекетті қайталаңыз."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Саусақ ізі операциясынан бас тартылған."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Талпыныстар тым көп. Кейінірек қайталап көріңіз."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Әрекетті қайталаңыз."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> саусағы"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index d164467..213f305 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"បច្ចុប្បន្នភាព"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"ស្ថានភាពបណ្តាញ"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"ការជូនដំណឹងអំពីបណ្តាញ"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"មានបណ្តាញ"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"ស្ថានភាព VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"ការគ្រប់គ្រងឧបករណ៍"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"ការជូនដំណឹង"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"ការផ្តិតម្រាមដៃបានអស់ពេល។ សូមព្យាយាមម្តងទៀត។"</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"បានបោះបង់ប្រតិបត្តិការស្នាមម្រាមដៃ។"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"ព្យាយាមចូលច្រើនពេកហើយ។ សូមព្យាយាមម្តងទៀតពេលក្រោយ។"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ព្យាយាមម្ដងទៀត។"</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"ម្រាមដៃ <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 1581520..9a6e89a 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"ಬೆರಳಚ್ಚು ಅವಧಿ ಮೀರಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"ಬೆರಳಚ್ಚು ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಮಾಡಲಾಗಿದೆ."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"ಹಲವಾರು ಪ್ರಯತ್ನಗಳು. ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"ಫಿಂಗರ್ <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 266ecf1..cc7aff3 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"지문 인식 시간이 초과되었습니다. 다시 시도하세요."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"지문 인식 작업이 취소되었습니다."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"시도 횟수가 너무 많습니다. 나중에 다시 시도하세요."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"다시 시도해 보세요."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"손가락 <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 5833d04..0f5f403 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Жаңыртуулар"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Тармактын абалы"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Тармактын эскертүүлөрү"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Жеткиликтүү тармактар"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN абалы"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Түзмөктү администрациялоо"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Эскертүүлөр"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Манжа изин күтүү мөөнөтү бүттү. Кайра аракет кылыңыз."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Манжа изи иш-аракети жокко чыгарылды."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Аракеттер өтө көп болду. Кийинчерээк кайра аракет кылыңыз."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Кайра бир аракеттениңиз."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> манжасы"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index c29fe19..f6eb279 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"ອັບເດດ"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"ສະຖານະເຄືອຂ່າຍ"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"ແຈ້ງເຕືອນເຄືອຂ່າຍ"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"ມີເຄືອຂ່າຍທີ່ສາມາດໃຊ້ໄດ້"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"ສະຖານະ VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"ການເບິ່ງແຍງອຸປະກອນ"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"ການເຕືອນ"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"ເວລາລາຍນີ້ວມືບໍ່ເຂົ້າເຖິງໄດ້. ລອງໃໝ່ອີກ."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"ຍົກເລີກການດຳເນີນການລາຍນີ້ວມືແລ້ວ."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"ມີຄວາມພະຍາຍາມຫຼາຍຄັ້ງເກີນໄປ. ລອງໃໝ່ພາຍຫຼັງ."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ລອງໃໝ່ອີກຄັ້ງ."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"ນີ້ວມື <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index d5924bc..7838067 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -266,8 +266,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Naujiniai"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Tinklo būsena"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Tinklo įspėjimai"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Tinklas pasiekiamas"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN būsena"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Įrenginio administravimas"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Įspėjimai"</string>
@@ -498,6 +497,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Baigėsi kontrolinio kodo nustatymo skirtasis laikas. Bandykite dar kartą."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Kontrolinio kodo operacija atšaukta."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Per daug bandymų. Vėliau bandykite dar kartą."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Bandykite dar kartą."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> pirštas"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 100f3df..b71a220 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -263,8 +263,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Atjauninājumi"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Tīkla statuss"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Tīkla brīdinājumi"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Tīkls ir pieejams"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN statuss"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Ierīces administrēšana"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Brīdinājumi"</string>
@@ -495,6 +494,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Pirkstu nospiedumu nolasīšanas aparatūras noildze. Mēģiniet vēlreiz."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Nospieduma darbība neizdevās."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Pārāk daudz mēģinājumu. Vēlāk mēģiniet vēlreiz."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Mēģiniet vēlreiz."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g>. pirksts"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 38eb49b..febacb2 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Ажурирања"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Статус на мрежа"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Известувања на мрежа"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Има достапна мрежа"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-статус"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Управување со уред"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Предупредувања"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Се достигна времето на истекување на отпечатокот. Обидете се повторно."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Операцијата со отпечаток од прст се откажа."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Премногу обиди. Обидете се повторно подоцна."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Обидете се повторно."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Прст <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index ddd6117..03e21aa 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"വിരലടയാളം നൽകേണ്ട സമയം കഴിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"ഫിംഗർപ്രിന്റ് പ്രവർത്തനം റദ്ദാക്കി."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"നിരവധി തവണ ശ്രമിച്ചു. പിന്നീട് വീണ്ടും ശ്രമിക്കുക."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"വീണ്ടും ശ്രമിക്കൂ."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"കൈവിരൽ <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 8fdad78..7a8e821 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Шинэчлэлтүүд"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Сүлжээний төлөв"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Сүлжээний сануулга"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Сүлжээ боломжтой"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN төлөв"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Төхөөрөмжийн удирдлага"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Сануулга"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Хурууны хээ оруулах хугацаа өнгөрсөн байна. Дахин оруулна уу."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Хурууны хээний бүртгэл амжилтгүй боллоо."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Хэтэрхий олон оролдлоо. Түр хүлээгээд дахин оролдоно уу."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Дахин оролдно уу."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Хурууны хээ <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index ebdf0e4..d44f900 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"अद्यतने"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"नेटवर्क स्थिती"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"नेटवर्क सूचना"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"नेटवर्क उपलब्ध"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN स्थिती"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"डिव्हाइस प्रशासन"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"सूचना"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"फिंगरप्रिंट कालबाह्य झाले. पुन्हा प्रयत्न करा."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"फिंगरप्रिंट ऑपरेशन रद्द झाले."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"खूप प्रयत्न केले. नंतर पुन्हा प्रयत्न करा."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"पुन्हा प्रयत्न करा."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> बोट"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 6ec0fe3..4f0f557 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tamat masa cap jari dicapai. Cuba lagi."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Pengendalian cap jari dibatalkan."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Terlalu banyak percubaan. Cuba sebentar lagi."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Cuba lagi."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Jari <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 53ae1ca..f801df5 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"အပ်ဒိတ်များ"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"ကွန်ရက် အခြေအနေ"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"ကွန်ရက် သတိပေးချက်များ"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"ကွန်ရက်ချိတ်ဆက်မှု ရရှိနိုင်ပါသည်"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN အခြေအနေ"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"စက်ပစ္စည်း စီမံခန့်ခွဲမှု"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"သတိပေးချက်များ"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"လက်ဗွေရာအချိန်ကုန် သွားပါသည်။ ထပ်မံကြိုးစားပါ။"</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"လက်ဗွေရာ လုပ်ငန်း ဖျက်သိမ်းခဲ့၏။"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"ကြိုးစာမှု အကြိမ်များနေ၏။ နောက်မှ ထပ်မံကြိုးစားပါ။"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ပြန်ကြိုးစားပါ"</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"လက်ချောင်း <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index f0c5a98..f9b73e0 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tidsavbrudd for fingeravtrykk er nådd. Prøv på nytt."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingeravtrykk-operasjonen ble avbrutt."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"For mange forsøk. Prøve på nytt senere."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Prøv igjen."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index a10724b..30c6e8c 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"औँठाछापको समय सकिएको छ। फेरि प्रयास गर्नुहोस्।"</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"औँठाछाप सञ्चालन रद्द गरियो।"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"धेरै प्रयासहरू। केहि समय पछि पुन: प्रयास गर्नुहोला"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"पुन: प्रयास गर्नुहोला।"</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"औंला <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index f30b85c..f102451 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Updates"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Netwerkstatus"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Netwerkmeldingen"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Netwerk beschikbaar"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-status"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Apparaatbeheer"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Meldingen"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Time-out bereikt voor vingerafdruk. Probeer het opnieuw."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Vingerafdrukbewerking geannuleerd."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Te veel pogingen. Probeer het later opnieuw."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Probeer het opnieuw."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Vinger <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 7eab363..4a4bb62 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸਮਾਂ ਸਮਾਪਤ ਹੋ ਗਿਆ ਹੈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"ਫਿੰਗਰ"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"ਬਹੁਤ ਸਾਰੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ. ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"ਉਂਗਲ <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 22133df..72cc52a 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -266,8 +266,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Aktualizacje"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Stan sieci"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alerty dotyczące sieci"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Sieć dostępna"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Stan sieci VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Administracja urządzeniem"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alerty"</string>
@@ -498,6 +497,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Osiągnięto limit czasu odczytu linii papilarnych. Spróbuj ponownie."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Odczyt odcisku palca został anulowany."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Zbyt wiele prób. Spróbuj ponownie później."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Spróbuj ponownie."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Odcisk palca <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index a2dc606..7157dab 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operação de impressão digital cancelada."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Excesso de tentativas. Tente novamente mais tarde."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tente novamente."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 641c115..026a866 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Atualizações"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Estado da rede"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertas da rede"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Rede disponível"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Estado da VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Administração do dispositivo"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Foi atingido o limite de tempo da impressão digital. Tente novamente."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operação de impressão digital cancelada."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiadas tentativas. Tente novamente mais tarde."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tente novamente."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index a2dc606..7157dab 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operação de impressão digital cancelada."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Excesso de tentativas. Tente novamente mais tarde."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tente novamente."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index b093298..1a3e0c5 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -263,8 +263,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Actualizări"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Starea rețelei"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alerte privind rețeaua"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Rețea disponibilă"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Stare VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Administrarea dispozitivului"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Alerte"</string>
@@ -495,6 +494,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Timpul pentru amprentare a expirat. Încercați din nou."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operațiunea privind amprenta a fost anulată."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Prea multe încercări. Încercați din nou mai târziu."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Încercați din nou."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Degetul <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 61f6dc1..ab91c0a 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -266,8 +266,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Обновления"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Статус сети"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Оповещения сети"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Сеть доступна"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Статус VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Управление устройством"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Уведомления"</string>
@@ -498,6 +497,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Превышено время ожидания. Повторите попытку."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Операция с отпечатком отменена."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Слишком много попыток. Повторите позже."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Повторите попытку."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Палец <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 81f735e..71466bc 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"යාවත්කාලීන කිරීම්"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"ජාල තත්ත්වය"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"ජාල ඇඟවීම්"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"ජාලය ලබා ගැනීමට හැකිය"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN තත්ත්වය"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"උපාංග පරිපාලනය"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"ඇඟවීම්"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"ඇඟිලි සලකුණු කාල නිමාව ළඟා විය. නැවත උත්සාහ කරන්න."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"ඇඟිලි සලකුණු මෙහෙයුම අවලංගු කරන ලදී."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"උත්සාහයන් ඉතා වැඩි ගණනකි. කරුණාකර පසුව නැවත උත්සාහ කරන්න."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"නැවත උත්සාහ කරන්න."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"ඇඟිලි <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 01de743..08efcd9 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -498,6 +498,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit rozpoznania odtlačku vypršal. Skúste to znova."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operácia týkajúca sa odtlačku prsta bola zrušená"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Príliš veľa pokusov. Skúste to znova neskôr."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Skúste to znova"</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Prst: <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 9a41492e..9aa39e9 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -266,8 +266,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Posodobitve"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Stanje omrežja"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Opozorila omrežja"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Omrežje je na voljo"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Stanje omrežja VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Skrbništvo naprave"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Opozorila"</string>
@@ -498,6 +497,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Dosežena časovna omejitev za prstni odtis. Poskusite znova."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Dejanje s prstnim odtisom je bilo preklicano."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Preveč poskusov. Poskusite znova pozneje."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Poskusite znova."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 2a030a2..b9b8e98 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Përditësimet"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Statusi i rrjetit"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Sinjalizimet e rrjetit"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Ka rrjet të disponueshëm"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Statusi i VPN-së"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Administrimi i pajisjes"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Sinjalizimet"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Koha e veprimit për gjurmën e gishtit skadoi. Provo përsëri."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operacioni i gjurmës së gishtit u anulua."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Keni bërë shumë tentativa. Provo përsëri më vonë."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Provo përsëri."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Gishti <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 8e314f8..b85df9f 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -263,8 +263,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Ажурирања"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Статус мреже"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Обавештења у вези са мрежом"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Мрежа је доступна"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Статус VPN-а"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Администрирање уређаја"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Обавештења"</string>
@@ -495,6 +494,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Временско ограничење за отисак прста је истекло. Пробајте поново."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Радња са отиском прста је отказана."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Превише покушаја. Пробајте поново касније."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Пробајте поново."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Прст <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 253dcac..c6865a1 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tidsgränsen för fingeravtrycket har uppnåtts. Försök igen."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingeravtrycksåtgärden avbröts."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Du har gjort för många försök. Försök igen senare."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Försök igen."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 86ec23b..55da8d9 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -207,7 +207,7 @@
<string name="reboot_to_update_prepare" msgid="6305853831955310890">"Inajiandaa kusasisha..."</string>
<string name="reboot_to_update_package" msgid="3871302324500927291">"Inachakata kifurushi cha kusasisha…"</string>
<string name="reboot_to_update_reboot" msgid="6428441000951565185">"Inazima na kuwasha upya..."</string>
- <string name="reboot_to_reset_title" msgid="4142355915340627490">"Rejesha data ya mwanzo"</string>
+ <string name="reboot_to_reset_title" msgid="4142355915340627490">"Rejesha mipangilio ya kiwandani"</string>
<string name="reboot_to_reset_message" msgid="2432077491101416345">"Inazima na kuwasha upya..."</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Inafunga..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Kompyuta kibao yako itazima."</string>
@@ -258,8 +258,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Taarifa"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Hali ya mtandao"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Arifa za mtandao"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Mtandao unapatikana"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Hali ya VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Udhibiti wa kifaa"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Arifa"</string>
@@ -490,6 +489,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Muda wa kitambulisho umekwisha. Jaribu tena."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Utendaji wa kitambulisho imeghairiwa."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Majaribio mengi mno. Jaribu tena baadaye."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Jaribu tena."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Kitambulisho <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
@@ -569,7 +570,7 @@
<string name="policylab_forceLock" msgid="2274085384704248431">"Kufunga skrini"</string>
<string name="policydesc_forceLock" msgid="1141797588403827138">"Kudhibiti jinsi na wakati skrini inapofunga."</string>
<string name="policylab_wipeData" msgid="3910545446758639713">"Kufuta data yote"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Futa data ya kompyuta kibao bila ilani kwa kurejesha mipangilio ya mwanzo."</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Futa data ya kompyuta kibao bila ilani kwa kurejesha mipangilio ambayo kompyuta ilitoka nayo kiwandani."</string>
<string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"Futa data ya runinga bila onyo kwa kurejesha katika hali iliyotoka nayo kiwandani."</string>
<string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Kufuta data ya simu bila ilani kwa kurejesha data ambayo kifaa kilitoka nayo kiwandani"</string>
<string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"Futa data yote ya mtumiaji"</string>
@@ -749,9 +750,9 @@
<string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Umekosea katika kuweka mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%2$d</xliff:g> bila kufaulu, utaulizwa kufungua kompyuta yako ndogo kwa kuingia kwa Google.\n\n Jaribu tena katika sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Umekosea kuchora mchoro wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Ukikosea majaribio mengine <xliff:g id="NUMBER_1">%2$d</xliff:g>, utaombwa ufungue runinga yako ukitumia Google.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Umekosea kuchora mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%2$d</xliff:g> yasiyofaulu, utaulizwa kufungua simu kupitia kuingia Google.\n\n Jaribu tena katika sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
- <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Umejaribu kufungua kompyuta ndogo kwa njia isiyo sahihi mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Baada ya zaidi ya <xliff:g id="NUMBER_1">%2$d</xliff:g> majaribio yasiyofanikiwa, kompyuta ndogo itawekwa upya kwa kiwanda chaguo-msingi na data yote ya mtumiaji itapotea."</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Umejaribu kufungua kompyuta kibao kwa njia isiyo sahihi mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Ukijaribu tena mara <xliff:g id="NUMBER_1">%2$d</xliff:g> bila mafanikio, kompyuta ndogo itarejeshwa kwenye mipangilio iliyotoka nayo kiwandani na data yote iliyomo itafutwa."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"Umekosea majaribio ya kufungua runinga mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Ukikosea majaribio <xliff:g id="NUMBER_1">%2$d</xliff:g> zaidi, runinga itarejeshwa katika hali iliyotoka nayo kiwandani na data yote ya watumiaji itafutwa."</string>
- <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Umejaribu kufungua simu kwa njia isiyo sahihi mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%2$d</xliff:g> zaidi yasiyofanikiwa, simu itawekwa upya kwa kiwanda chaguo-msingi na data yote ya mtumiaji itapotea."</string>
+ <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Umejaribu kufungua simu kwa njia isiyo sahihi mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Ukijaribu tena mara <xliff:g id="NUMBER_1">%2$d</xliff:g> bila mafanikio, simu itarejeshwa kwenye mipangilio iliyotoka nayo kiwandani na data yote iliyomo itafutwa."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Umejaribu kufungua kompyuta ndogo kwa njia isiyo sahihi mara <xliff:g id="NUMBER">%d</xliff:g>. Kompyuta ndogo haitaweza kuwekwa upya kwa kiwanda chaguo-msingi."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"Umekosea majaribio ya kufungua runinga mara <xliff:g id="NUMBER">%d</xliff:g>. Sasa runinga itarejeshwa katika mipangilio iliyotoka nayo kiwandani."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Umejaribu kufungua kompyuta ndogo kwa njia isiyo sahihi mara <xliff:g id="NUMBER">%d</xliff:g>. Kompyuta ndogo haitaweza kuwekwa upya kwa kiwanda chaguo-msingi."</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index c832173..6cbfba5 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"புதுப்பிப்புகள்"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"நெட்வொர்க்கின் நிலை"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"நெட்வொர்க் விழிப்பூட்டல்கள்"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"நெட்வொர்க் உள்ளது"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN நிலை"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"சாதன நிர்வாகம்"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"விழிப்பூட்டல்கள்"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"கைரேகைக்கான நேரம் முடிந்தது. மீண்டும் முயலவும்."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"கைரேகை செயல்பாடு ரத்துசெய்யப்பட்டது."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"அதிகமான முயற்சிகள். பிறகு முயற்சிக்கவும்."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"மீண்டும் முயற்சிக்கவும்."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"கைரேகை <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index e2791b7..b3e5e4a 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"వేలిముద్ర గడువు సమయం చేరుకుంది. మళ్లీ ప్రయత్నించండి."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"వేలిముద్ర కార్యాచరణ రద్దయింది."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"చాలా ఎక్కువ ప్రయత్నాలు చేసారు. తర్వాత మళ్లీ ప్రయత్నించండి."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"మళ్లీ ప్రయత్నించండి."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"వేలు <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index b1d40267..c2ae15e 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"การอัปเดต"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"สถานะเครือข่าย"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"การแจ้งเตือนเครือข่าย"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"มีเครือข่ายพร้อมใช้งาน"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"สถานะ VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"การดูแลระบบอุปกรณ์"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"การแจ้งเตือน"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"หมดเวลาใช้ลายนิ้วมือแล้ว โปรดลองอีกครั้ง"</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"ยกเลิกการทำงานของลายนิ้วมือ"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"ดำเนินการหลายครั้งเกินไป ลองอีกครั้งในภายหลัง"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ลองอีกครั้ง"</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"นิ้ว <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 33bb5b1..2ef0c7a 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Mga Update"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Status ng network"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Mga alerto sa network"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Available ang network"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Status ng VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Pamamahala ng device"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Mga Alerto"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Nag-time out ang fingerprint. Subukang muli."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Nakansela ang operasyong ginagamitan ng fingerprint."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Masyadong maraming beses sumubok. Subukang muli sa ibang pagkakataon."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Subukang muli."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Daliri <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 9d4ea40..c3b2001 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Parmak izi için zaman aşımı oluştu. Tekrar deneyin."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Parmak izi işlemi iptal edildi."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Çok fazla deneme yapıldı. Daha sonra tekrar deneyin."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tekrar deneyin."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g>. parmak"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index e6fb07a..a5a289c 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -266,8 +266,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Оновлення"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Статус мережі"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Сповіщення мережі"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Мережа доступна"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Статус мережі VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Адміністрування пристрою"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Сповіщення"</string>
@@ -498,6 +497,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час очікування відбитка минув. Повторіть спробу."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Дію з відбитком скасовано."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Забагато спроб. Спробуйте пізніше."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Повторіть спробу."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Відбиток пальця <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 192a2e9..c16c0c6 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"فنگر پرنٹ کی میعاد ختم ہوگئی۔ دوبارہ کوشش کریں۔"</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"فنگر پرنٹ کی کارروائی منسوخ ہوگئی۔"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"کافی زیادہ کوششیں کی گئیں۔ بعد میں دوبارہ کوشش کریں۔"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"دوبارہ کوشش کریں۔"</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"انگلی <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 68cfc85..b2ea945 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Yangilanishlar"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Tarmoq holati"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Tarmoqqa oid bildirgilar"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Tarmoq mavjud"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"VPN holati"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Qurilma boshqaruvi"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Ogohlantirishlar"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Barmoq izini aniqlash vaqti tugab qoldi. Qayta urinib ko‘ring."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Barmoq izi tekshiruvi bekor qilindi."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Urinishlar soni ko‘payib ketdi. Keyinroq qayta urinib ko‘ring."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Qayta urinib ko‘ring."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Barmoq izi <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
@@ -770,7 +771,7 @@
<string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"Tekshirilmoqda…"</string>
<string name="lockscreen_unlock_label" msgid="737440483220667054">"Qulfdan chiqarish"</string>
<string name="lockscreen_sound_on_label" msgid="9068877576513425970">"Ovozni yoqish"</string>
- <string name="lockscreen_sound_off_label" msgid="996822825154319026">"Ovozni o‘chirish"</string>
+ <string name="lockscreen_sound_off_label" msgid="996822825154319026">"Ovozsiz qilish"</string>
<string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"Grafik kalitni chizish boshlandi"</string>
<string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Grafik kalit tozalandi"</string>
<string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Katak qo‘shildi"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index dacc9da..504ef5f 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Cập nhật"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Trạng thái mạng"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Cảnh báo mạng"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Có mạng"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Trạng thái VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Quản lý thiết bị"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Cảnh báo"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Đã hết thời gian chờ vân tay. Hãy thử lại."</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Thao tác dùng dấu vân tay bị hủy."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Quá nhiều lần thử. Hãy thử lại sau."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Thử lại."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Ngón tay <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index fcb6917..d195de8 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"指纹录入操作超时,请重试。"</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"指纹操作已取消。"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"尝试次数过多,请稍后重试。"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"请重试。"</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"手指 <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index c8e30e1..4eed27c 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"指紋已逾時。請再試一次。"</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"指紋操作已取消。"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"嘗試次數過多,請稍後再試。"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"再試一次。"</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"手指 <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 49fe199..0c4ffad 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -492,6 +492,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"指紋處理作業逾時,請再試一次。"</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"指紋作業已取消。"</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"嘗試次數過多,請稍後再試。"</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"請再試一次。"</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"手指 <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 3e2ca18..2ce9696 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -260,8 +260,7 @@
<string name="notification_channel_updates" msgid="4794517569035110397">"Izibuyekezo"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"Isimo senethiwekhi"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"Izexwayiso zenethiwekhi"</string>
- <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
- <skip />
+ <string name="notification_channel_network_available" msgid="4531717914138179517">"Inethiwekhi iyatholakala"</string>
<string name="notification_channel_vpn" msgid="8330103431055860618">"Isimo se-VPN"</string>
<string name="notification_channel_device_admin" msgid="1568154104368069249">"Ukulawula idivayisi"</string>
<string name="notification_channel_alerts" msgid="4496839309318519037">"Izexwayiso"</string>
@@ -492,6 +491,8 @@
<string name="fingerprint_error_timeout" msgid="3927186043737732875">"Kufinyelelwe isikhathi sokuvala sezigxivizo zeminwe. Zama futhi"</string>
<string name="fingerprint_error_canceled" msgid="4402024612660774395">"Ukusebenza kwezingxivizo zeminwe kukhanseliwe."</string>
<string name="fingerprint_error_lockout" msgid="5536934748136933450">"Imizamo eminingi kakhulu. Zama futhi emuva kwesikhathi."</string>
+ <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
+ <skip />
<string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Zama futhi."</string>
<string name="fingerprint_name_template" msgid="5870957565512716938">"Umunwe ongu-<xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 6640102..8e6c402 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2849,6 +2849,11 @@
<!-- Default data warning level in mb -->
<integer name="default_data_warning_level_mb">2048</integer>
+ <!-- When true, indicates that the vendor's IMS implementation requires a workaround when
+ sending a request to enable or disable the camera while the video session is also
+ paused. -->
+ <bool name="config_useVideoPauseWorkaround">false</bool>
+
<!-- Whether to send a custom package name with the PSD.-->
<bool name="config_sendPackageName">false</bool>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 42d3f27..4868774 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2761,81 +2761,80 @@
<eat-comment />
<public type="attr" name="visibleToInstantApps" id="0x01010531" />
+ <public type="attr" name="font" id="0x01010532" />
+ <public type="attr" name="fontWeight" id="0x01010533" />
+ <public type="attr" name="tooltipText" id="0x01010534" />
+ <public type="attr" name="autoSizeTextType" id="0x01010535" />
+ <public type="attr" name="autoSizeStepGranularity" id="0x01010536" />
+ <public type="attr" name="autoSizePresetSizes" id="0x01010537" />
+ <public type="attr" name="autoSizeMinTextSize" id="0x01010538" />
+ <public type="attr" name="min" id="0x01010539" />
+ <public type="attr" name="rotationAnimation" id="0x0101053a" />
+ <public type="attr" name="layout_marginHorizontal" id="0x0101053b" />
+ <public type="attr" name="layout_marginVertical" id="0x0101053c" />
+ <public type="attr" name="paddingHorizontal" id="0x0101053d" />
+ <public type="attr" name="paddingVertical" id="0x0101053e" />
+ <public type="attr" name="fontStyle" id="0x0101053f" />
+ <public type="attr" name="keyboardNavigationCluster" id="0x01010540" />
+ <public type="attr" name="targetProcesses" id="0x01010541" />
+ <public type="attr" name="nextClusterForward" id="0x01010542" />
+ <public type="attr" name="colorError" id="0x01010543" />
+ <public type="attr" name="focusedByDefault" id="0x01010544" />
+ <public type="attr" name="appCategory" id="0x01010545" />
+ <public type="attr" name="autoSizeMaxTextSize" id="0x01010546" />
+ <public type="attr" name="recreateOnConfigChanges" id="0x01010547" />
+ <public type="attr" name="certDigest" id="0x01010548" />
+ <public type="attr" name="splitName" id="0x01010549" />
+ <public type="attr" name="colorMode" id="0x0101054a" />
+ <public type="attr" name="isolatedSplits" id="0x0101054b" />
+ <public type="attr" name="targetSandboxVersion" id="0x0101054c" />
+ <public type="attr" name="canRequestFingerprintGestures" id="0x0101054d" />
+ <public type="attr" name="alphabeticModifiers" id="0x0101054e" />
+ <public type="attr" name="numericModifiers" id="0x0101054f" />
+ <public type="attr" name="fontProviderAuthority" id="0x01010550" />
+ <public type="attr" name="fontProviderQuery" id="0x01010551" />
+ <public type="attr" name="primaryContentAlpha" id="0x01010552" />
+ <public type="attr" name="secondaryContentAlpha" id="0x01010553" />
+ <public type="attr" name="requiredFeature" id="0x01010554" />
+ <public type="attr" name="requiredNotFeature" id="0x01010555" />
+ <public type="attr" name="autofillHints" id="0x01010556" />
+ <public type="attr" name="fontProviderPackage" id="0x01010557" />
+ <public type="attr" name="importantForAutofill" id="0x01010558" />
+ <public type="attr" name="recycleEnabled" id="0x01010559"/>
+ <public type="attr" name="isStatic" id="0x0101055a" />
+ <public type="attr" name="isFeatureSplit" id="0x0101055b" />
+ <public type="attr" name="singleLineTitle" id="0x0101055c" />
+ <public type="attr" name="fontProviderCerts" id="0x0101055d" />
+ <public type="attr" name="iconTint" id="0x0101055e" />
+ <public type="attr" name="iconTintMode" id="0x0101055f" />
+ <public type="attr" name="maxAspectRatio" id="0x01010560"/>
+ <public type="attr" name="iconSpaceReserved" id="0x01010561"/>
+ <public type="attr" name="defaultFocusHighlightEnabled" id="0x01010562" />
+ <public type="attr" name="persistentWhenFeatureAvailable" id="0x01010563"/>
+ <public type="attr" name="windowSplashscreenContent" id="0x01010564" />
+ <!-- @hide @SystemApi -->
+ <public type="attr" name="requiredSystemPropertyName" id="0x01010565" />
+ <!-- @hide @SystemApi -->
+ <public type="attr" name="requiredSystemPropertyValue" id="0x01010566" />
+ <public type="attr" name="justificationMode" id="0x01010567" />
+ <public type="attr" name="autofilledHighlight" id="0x01010568" />
- <public-group type="attr" first-id="0x01010532">
- <public name="font" />
- <public name="fontWeight" />
- <public name="tooltipText" />
- <public name="autoSizeTextType" />
- <public name="autoSizeStepGranularity" />
- <public name="autoSizePresetSizes" />
- <public name="autoSizeMinTextSize" />
- <public name="min" />
- <public name="rotationAnimation" />
- <public name="layout_marginHorizontal" />
- <public name="layout_marginVertical" />
- <public name="paddingHorizontal" />
- <public name="paddingVertical" />
- <public name="fontStyle" />
- <public name="keyboardNavigationCluster" />
- <public name="targetProcesses" />
- <public name="nextClusterForward" />
- <public name="__removed1" />
- <public name="colorError" />
- <public name="focusedByDefault" />
- <public name="appCategory" />
- <public name="autoSizeMaxTextSize" />
- <public name="__removed2" />
- <public name="recreateOnConfigChanges" />
- <public name="certDigest" />
- <public name="splitName" />
- <public name="colorMode" />
- <public name="isolatedSplits" />
- <public name="targetSandboxVersion" />
- <public name="canRequestFingerprintGestures" />
- <public name="alphabeticModifiers" />
- <public name="numericModifiers" />
- <public name="fontProviderAuthority" />
- <public name="fontProviderQuery" />
- <public name="__removed3" />
- <public name="primaryContentAlpha" />
- <public name="secondaryContentAlpha" />
- <public name="requiredFeature" />
- <public name="requiredNotFeature" />
- <public name="autofillHints" />
- <public name="fontProviderPackage" />
- <public name="importantForAutofill" />
- <public name="recycleEnabled"/>
- <public name="isStatic" />
- <public name="isFeatureSplit" />
- <public name="singleLineTitle" />
- <public name="fontProviderCerts" />
- <public name="iconTint" />
- <public name="iconTintMode" />
- <public name="maxAspectRatio"/>
- <public name="iconSpaceReserved"/>
- <public name="defaultFocusHighlightEnabled" />
- <public name="persistentWhenFeatureAvailable"/>
- <public name="windowSplashscreenContent" />
- <!-- @hide @SystemApi -->
- <public name="requiredSystemPropertyName" />
- <!-- @hide @SystemApi -->
- <public name="requiredSystemPropertyValue" />
- <public name="justificationMode" />
- <public name="autofilledHighlight" />
+ <public type="id" name="textAssist" id="0x01020041" />
+ <public type="id" name="accessibilityActionMoveWindow" id="0x01020042" />
+ <public type="id" name="autofill" id="0x01020043" />
+
+ <public type="string" name="paste_as_plain_text" id="0x01040019" />
+
+ <public-group type="attr" first-id="0x01010569">
</public-group>
<public-group type="style" first-id="0x010302e0">
</public-group>
- <public-group type="id" first-id="0x01020041">
- <public name="textAssist" />
- <public name="accessibilityActionMoveWindow" />
- <public name="autofill" />
+ <public-group type="id" first-id="0x01020044">
</public-group>
- <public-group type="string" first-id="0x01040019">
- <public name="paste_as_plain_text" />
+ <public-group type="string" first-id="0x0104001a">
</public-group>
<!-- ===============================================================
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f747d3d..fcabe31 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3225,7 +3225,7 @@
<skip />
<!-- Name of notification channel the system post notification to inform the use about apps
that are drawing ui on-top of other apps (alert-windows) [CHAR LIMIT=NONE] -->
- <string name="alert_windows_notification_channel_name"><xliff:g id="name" example="Google Maps">%s</xliff:g> displaying over other apps</string>
+ <string name="alert_windows_notification_channel_name">App activity</string>
<!-- Notification title when an application is displaying ui on-top of other apps
[CHAR LIMIT=30] -->
<string name="alert_windows_notification_title"><xliff:g id="name" example="Google Maps">%s</xliff:g> is displaying over other apps</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6e3f0e0..8d2666e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2936,7 +2936,7 @@
<java-symbol type="id" name="label_error"/>
<java-symbol type="layout" name="time_picker_text_input_material"/>
<java-symbol type="drawable" name="btn_keyboard_key_material"/>
- <java-symbol type="drawable" name="btn_event_material"/>
+ <java-symbol type="drawable" name="btn_clock_material"/>
<java-symbol type="string" name="time_picker_text_input_mode_description"/>
<java-symbol type="string" name="time_picker_radial_mode_description"/>
@@ -3005,7 +3005,7 @@
<java-symbol type="bool" name="enable_pbap_pce_profile" />
<java-symbol type="integer" name="default_data_warning_level_mb" />
-
+ <java-symbol type="bool" name="config_useVideoPauseWorkaround" />
<java-symbol type="bool" name="config_sendPackageName" />
<java-symbol type="string" name="config_helpPackageNameKey" />
<java-symbol type="string" name="config_helpPackageNameValue" />
diff --git a/core/tests/coretests/res/layout/messaging_linear_layout_test.xml b/core/tests/coretests/res/layout/messaging_linear_layout_test.xml
index 8ba3e07..9e70ca3 100644
--- a/core/tests/coretests/res/layout/messaging_linear_layout_test.xml
+++ b/core/tests/coretests/res/layout/messaging_linear_layout_test.xml
@@ -19,7 +19,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:maxHeight="300px"
android:spacing="5px">
</com.android.internal.widget.MessagingLinearLayout>
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/app/LoaderLifecycleTest.java b/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
index 1850d57..c83e798 100644
--- a/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
+++ b/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
@@ -17,6 +17,13 @@
package android.app;
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertNotSame;
+import static junit.framework.TestCase.assertSame;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import android.content.Context;
import android.os.Handler;
import android.os.Parcelable;
@@ -24,14 +31,11 @@
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.util.ArrayMap;
+
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static junit.framework.TestCase.assertNotNull;
-import static junit.framework.TestCase.assertNotSame;
-import static junit.framework.TestCase.assertSame;
-
@RunWith(AndroidJUnit4.class)
public class LoaderLifecycleTest {
@Rule
@@ -203,6 +207,16 @@
// Test that the fragments are in the configuration we expect
final Fragment restoredOne = fm2.findFragmentByTag("one");
+ try {
+ restoredOne.getLoaderManager();
+ fail("A restored fragment on the back stack doesn't have a host, so it should "
+ + "throw an exception");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ fm2.popBackStackImmediate();
+ // Now restoredOne should be added and should be in a good state.
+ assertTrue(restoredOne.isAdded());
final LoaderManager lm2 = restoredOne.getLoaderManager();
assertSame("didn't get same LoaderManager instance back", lm2, lm1);
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 33a0493..1ffc1b3 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -1317,24 +1317,8 @@
return;
}
Runtime.getRuntime().gc();
-
- final String packageName = ip.pkg.packageName;
- Log.i(TAG, "Deleting package : " + packageName);
-
- ApplicationInfo info = null;
try {
- info = getPm().getApplicationInfo(packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES);
- } catch (NameNotFoundException ignored) {
- }
-
- DeleteObserver observer = new DeleteObserver(packageName);
- getPm().deletePackage(packageName, observer, PackageManager.DELETE_ALL_USERS);
- observer.waitForCompletion(MAX_WAIT_TIME);
-
- try {
- if (info != null) {
- assertUninstalled(info);
- }
+ cleanUpInstall(ip.pkg.packageName);
} finally {
File outFile = new File(ip.pkg.codePath);
if (outFile != null && outFile.exists()) {
@@ -1349,16 +1333,15 @@
}
Log.i(TAG, "Deleting package : " + pkgName);
try {
- ApplicationInfo info = getPm().getApplicationInfo(pkgName,
+ final ApplicationInfo info = getPm().getApplicationInfo(pkgName,
PackageManager.MATCH_UNINSTALLED_PACKAGES);
-
if (info != null) {
DeleteObserver observer = new DeleteObserver(pkgName);
getPm().deletePackage(pkgName, observer, PackageManager.DELETE_ALL_USERS);
observer.waitForCompletion(MAX_WAIT_TIME);
assertUninstalled(info);
}
- } catch (NameNotFoundException e) {
+ } catch (IllegalArgumentException | NameNotFoundException e) {
}
}
diff --git a/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java b/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
index 5dc07c2..906d7e9 100644
--- a/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
@@ -16,7 +16,7 @@
package com.android.internal.widget;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
@@ -111,6 +111,9 @@
mTextView.measure(widthMeasureSpec, heightMeasureSpec);
mView.measure(widthMeasureSpec, heightMeasureSpec);
- assertEquals(mTextView.getMeasuredHeight(), mView.getMeasuredHeight());
+ // We're at most allowed to be the same height as the regular textview and maybe a bit
+ // smaller since our layout snaps to full textlines.
+ assertTrue("The measured view should never be taller then the normal textview!",
+ mView.getMeasuredHeight() <= mTextView.getMeasuredHeight());
}
}
diff --git a/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
index 75b2c1d..20fd4d3 100644
--- a/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
@@ -21,7 +21,6 @@
import static org.junit.Assert.assertTrue;
import android.content.Context;
-import android.os.Debug;
import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.core.deps.guava.base.Function;
import android.support.test.filters.SmallTest;
@@ -46,8 +45,7 @@
@Before
public void setup() {
mContext = InstrumentationRegistry.getTargetContext();
- // maxHeight: 300px
- // spacing: 50px
+ // spacing: 5px
mView = (MessagingLinearLayout) LayoutInflater.from(mContext).inflate(
R.layout.messaging_linear_layout_test, null);
}
@@ -81,8 +79,8 @@
assertEquals(3, child1.getNumIndentLines());
assertEquals(0, child2.getNumIndentLines());
- assertFalse(child1.isHidden());
- assertFalse(child2.isHidden());
+ assertFalse("child1 should not be hidden", child1.isHidden());
+ assertFalse("child2 should not be hidden", child2.isHidden());
assertEquals(205, mView.getMeasuredHeight());
}
@@ -100,8 +98,8 @@
assertEquals(2, child1.getNumIndentLines());
assertEquals(1, child2.getNumIndentLines());
- assertFalse(child1.isHidden());
- assertFalse(child2.isHidden());
+ assertFalse("child1 should not be hidden", child1.isHidden());
+ assertFalse("child2 should not be hidden", child2.isHidden());
assertEquals(105, mView.getMeasuredHeight());
}
@@ -118,14 +116,14 @@
mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
assertEquals(3, child2.getNumIndentLines());
- assertTrue(child1.isHidden());
- assertFalse(child2.isHidden());
- assertEquals(300, mView.getMeasuredHeight());
+ assertTrue("child1 should be hidden", child1.isHidden());
+ assertFalse("child2 should not be hidden", child2.isHidden());
+ assertEquals(350, mView.getMeasuredHeight());
}
@Test
- public void testLargeSmall_largeWrapsWith3indentbutnot3_andHitsMax() {
- FakeImageFloatingTextView child1 = fakeChild((i) -> i > 2 ? 5 : 4);
+ public void testLargeSmall_largeWrapsWith3indentbutNotFullHeight_andHitsMax() {
+ FakeImageFloatingTextView child1 = fakeChild((i) -> i > 2 ? 7 : 6);
FakeImageFloatingTextView child2 = fakeChild((i) -> 1);
mView.setNumIndentLines(2);
@@ -135,10 +133,11 @@
mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
- assertTrue(child1.isHidden());
- assertFalse(child2.isHidden());
- assertEquals(50, mView.getMeasuredHeight());
- assertEquals(2, child2.getNumIndentLines());
+ assertFalse("child1 should not be hidden", child1.isHidden());
+ assertFalse("child2 should not be hidden", child2.isHidden());
+ assertEquals(355, mView.getMeasuredHeight());
+ assertEquals(3, child1.getNumIndentLines());
+ assertEquals(0, child2.getNumIndentLines());
}
@Test
@@ -153,8 +152,8 @@
mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
- assertFalse(child1.isHidden());
- assertFalse(child2.isHidden());
+ assertFalse("child1 should not be hidden", child1.isHidden());
+ assertFalse("child2 should not be hidden", child2.isHidden());
assertEquals(255, mView.getMeasuredHeight());
assertEquals(3, child1.getNumIndentLines());
assertEquals(0, child2.getNumIndentLines());
@@ -184,10 +183,23 @@
}
@Override
+ public int getLayoutHeight() {
+ return Math.max(LINE_HEIGHT, getMeasuredHeight());
+ }
+
+ @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(
getDefaultSize(500, widthMeasureSpec),
- resolveSize(getDesiredHeight(), heightMeasureSpec));
+ clampToMultiplesOfLineHeight(resolveSize(getDesiredHeight(),
+ heightMeasureSpec)));
+ }
+
+ private int clampToMultiplesOfLineHeight(int size) {
+ if (size <= LINE_HEIGHT) {
+ return size;
+ }
+ return (size / LINE_HEIGHT) * LINE_HEIGHT;
}
@Override
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index b0e486d..d765584 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -16,7 +16,6 @@
#include "Bitmap.h"
#include "Caches.h"
-#include "pipeline/skia/SkiaOpenGLPipeline.h"
#include "renderthread/EglManager.h"
#include "renderthread/RenderThread.h"
#include "renderthread/RenderProxy.h"
@@ -35,15 +34,11 @@
#include <private/gui/ComposerService.h>
#include <binder/IServiceManager.h>
#include <ui/PixelFormat.h>
-#include <GrTexture.h>
#include <SkCanvas.h>
-#include <SkImagePriv.h>
namespace android {
-Mutex Bitmap::gLock;
-
static bool computeAllocationSize(size_t rowBytes, int height, size_t* size) {
int32_t rowBytes32 = SkToS32(rowBytes);
int64_t bigSize = (int64_t) height * rowBytes32;
@@ -322,7 +317,8 @@
return nullptr;
}
SkImageInfo info = SkImageInfo::Make(graphicBuffer->getWidth(), graphicBuffer->getHeight(),
- kRGBA_8888_SkColorType, kPremul_SkAlphaType, SkColorSpace::MakeSRGB());
+ kRGBA_8888_SkColorType, kPremul_SkAlphaType,
+ SkColorSpace::MakeSRGB());
return sk_sp<Bitmap>(new Bitmap(graphicBuffer.get(), info));
}
@@ -397,7 +393,6 @@
mPixelStorage.hardware.buffer = buffer;
buffer->incStrong(buffer);
mRowBytes = bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride();
- setImmutable(); // HW bitmaps are always immutable
}
Bitmap::~Bitmap() {
@@ -491,13 +486,7 @@
void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
if (isHardware()) {
- if (uirenderer::Properties::isSkiaEnabled()) {
- // TODO: add color correctness for Skia pipeline - pass null color space for now
- outBitmap->allocPixels(SkImageInfo::Make(info().width(), info().height(),
- info().colorType(), info().alphaType(), nullptr));
- } else {
- outBitmap->allocPixels(info());
- }
+ outBitmap->allocPixels(info());
uirenderer::renderthread::RenderProxy::copyGraphicBufferInto(graphicBuffer(), outBitmap);
return;
}
@@ -523,28 +512,4 @@
return nullptr;
}
-sk_sp<SkImage> Bitmap::makeImage(const uirenderer::renderthread::RenderThread* renderThread) {
- AutoMutex _lock(gLock); //TODO: implement lock free solution
- auto image = mImage;
- //TODO: use new API SkImage::isValid() instead of SkImage::getTexture()->getContext()
- if (!image.get() || (image->getTexture() && nullptr == image->getTexture()->getContext())) {
- if (isHardware() && uirenderer::RenderPipelineType::SkiaGL
- == uirenderer::Properties::getRenderPipelineType()) {
- //TODO: add Vulkan support
- if (renderThread) {
- image = uirenderer::skiapipeline::SkiaOpenGLPipeline::makeTextureImage(
- *renderThread, this);
- } else {
- image = uirenderer::renderthread::RenderProxy::makeTextureImage(this);
- }
- } else {
- SkBitmap skiaBitmap;
- getSkBitmapForShaders(&skiaBitmap);
- image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
- }
- mImage = image;
- }
- return image;
-}
-
} // namespace android
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 621e439..da45f76 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -22,8 +22,6 @@
#include <SkPixelRef.h>
#include <cutils/compiler.h>
#include <ui/GraphicBuffer.h>
-#include <utils/Mutex.h>
-#include <SkImage.h>
namespace android {
@@ -113,13 +111,6 @@
}
GraphicBuffer* graphicBuffer();
-
- // makeImage creates or returns a cached SkImage. Can be invoked from UI or render thread.
- // If invoked on the render thread, then RenderThread* argument is required.
- // If not invoked on the render thread, then RenderThread* must be nullptr.
- // makeImage is wrapping a gralloc buffer with an EGLImage and is passing a texture to Skia.
- // This is a temporary implementation until Skia can wrap the gralloc buffer in a SkImage.
- sk_sp<SkImage> makeImage(const uirenderer::renderthread::RenderThread*);
protected:
virtual bool onNewLockPixels(LockRec* rec) override;
virtual void onUnlockPixels() override { };
@@ -154,9 +145,6 @@
GraphicBuffer* buffer;
} hardware;
} mPixelStorage;
-
- sk_sp<SkImage> mImage;
- static Mutex gLock;
};
} //namespace android
\ No newline at end of file
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 4885873..ae13131 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -28,8 +28,6 @@
#include <cutils/properties.h>
#include <strings.h>
-#include <SkImagePriv.h>
-#include <gl/GrGLTypes.h>
using namespace android::uirenderer::renderthread;
@@ -199,87 +197,6 @@
}
}
-static void deleteImageTexture(void* context) {
- EGLImageKHR EGLimage = reinterpret_cast<EGLImageKHR>(context);
- if (EGLimage != EGL_NO_IMAGE_KHR) {
- EGLDisplay display = eglGetCurrentDisplay();
- if (EGL_NO_DISPLAY == display) {
- display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- }
- eglDestroyImageKHR(display, EGLimage);
- }
-}
-
-sk_sp<SkImage> SkiaOpenGLPipeline::makeTextureImage(
- const uirenderer::renderthread::RenderThread& renderThread, Bitmap* bitmap) {
- renderThread.eglManager().initialize();
-
- GraphicBuffer* buffer = bitmap->graphicBuffer();
- EGLDisplay display = eglGetCurrentDisplay();
- if (EGL_NO_DISPLAY == display) {
- display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- }
- LOG_ALWAYS_FATAL_IF(!bitmap->isHardware(),
- "Texture image requires a HW bitmap.");
- // We use an EGLImage to access the content of the GraphicBuffer
- // The EGL image is later bound to a 2D texture
- EGLClientBuffer clientBuffer = (EGLClientBuffer) buffer->getNativeBuffer();
- EGLint imageAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
- EGLImageKHR EGLimage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
- clientBuffer, imageAttrs);
- if (EGLimage == EGL_NO_IMAGE_KHR) {
- ALOGW("Could not create EGL image, err =%s",
- uirenderer::renderthread::EglManager::eglErrorString());
- return nullptr;
- }
-
- GLuint textureId = 0;
- glGenTextures(1, &textureId);
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, EGLimage);
-
- GLenum status = GL_NO_ERROR;
- while ((status = glGetError()) != GL_NO_ERROR) {
- ALOGW("glEGLImageTargetTexture2DOES failed (%#x)", status);
- eglDestroyImageKHR(display, EGLimage);
- return nullptr;
- }
-
- sk_sp<GrContext> grContext = sk_ref_sp(renderThread.getGrContext());
- grContext->resetContext();
-
- GrGLTextureInfo textureInfo;
- textureInfo.fTarget = GL_TEXTURE_EXTERNAL_OES;
- textureInfo.fID = textureId;
-
- GrBackendTextureDesc textureDescription;
- textureDescription.fWidth = bitmap->info().width();
- textureDescription.fHeight = bitmap->info().height();
- textureDescription.fOrigin = kTopLeft_GrSurfaceOrigin;
- textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&textureInfo);
- PixelFormat format = buffer->getPixelFormat();
- switch (format) {
- case PIXEL_FORMAT_RGBA_8888:
- textureDescription.fConfig = kRGBA_8888_GrPixelConfig;
- break;
- case PIXEL_FORMAT_RGBA_FP16:
- textureDescription.fConfig = kRGBA_half_GrPixelConfig;
- break;
- default:
- eglDestroyImageKHR(display, EGLimage);
- return nullptr;
- }
-
- // TODO: add color correctness - pass null color space for now
- sk_sp<SkImage> image = SkImage::MakeFromTexture(grContext.get(), textureDescription,
- bitmap->info().alphaType(), nullptr, deleteImageTexture, EGLimage);
- if (!image.get()) {
- eglDestroyImageKHR(display, EGLimage);
- return nullptr;
- }
- return image;
-}
-
} /* namespace skiapipeline */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
index f3ce189..36685dd 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -46,8 +46,6 @@
bool isContextReady() override;
static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
- static sk_sp<SkImage> makeTextureImage(
- const uirenderer::renderthread::RenderThread& renderThread, Bitmap* bitmap);
private:
renderthread::EglManager& mEglManager;
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
index 1a6e709..a18d264 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
@@ -61,7 +61,6 @@
textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture);
CopyResult copyResult = CopyResult::UnknownError;
- // TODO: add color correctness - pass null color space for now
sk_sp<SkImage> image(SkImage::MakeFromAdoptedTexture(grContext.get(), textureDescription));
if (image) {
SkAutoLockPixels alp(*bitmap);
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 349d4cc..10c1865 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -155,11 +155,11 @@
GrContext* context = thread.getGrContext();
if (context) {
ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
- auto image = bitmap->makeImage(&thread);
- if (image.get() && !bitmap->isHardware()) {
- SkImage_pinAsTexture(image.get(), context);
- SkImage_unpinAsTexture(image.get(), context);
- }
+ SkBitmap skiaBitmap;
+ bitmap->getSkBitmap(&skiaBitmap);
+ sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
+ SkImage_pinAsTexture(image.get(), context);
+ SkImage_unpinAsTexture(image.get(), context);
}
}
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 5d7bbfa..559d268 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -168,8 +168,11 @@
}
void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
- sk_sp<SkImage> image = bitmap.makeImage(nullptr);
- if (!bitmap.isImmutable()) {
+ SkBitmap skBitmap;
+ bitmap.getSkBitmap(&skBitmap);
+
+ sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skBitmap, kNever_SkCopyPixelsMode);
+ if (!skBitmap.isImmutable()) {
mDisplayList->mMutableImages.push_back(image.get());
}
SkPaint tmpPaint;
@@ -178,10 +181,12 @@
void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix,
const SkPaint* paint) {
+ SkBitmap bitmap;
+ hwuiBitmap.getSkBitmap(&bitmap);
SkAutoCanvasRestore acr(&mRecorder, true);
concat(matrix);
- sk_sp<SkImage> image = hwuiBitmap.makeImage(nullptr);
- if (!hwuiBitmap.isImmutable()) {
+ sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+ if (!bitmap.isImmutable()) {
mDisplayList->mMutableImages.push_back(image.get());
}
SkPaint tmpPaint;
@@ -191,10 +196,12 @@
void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight,
float dstBottom, const SkPaint* paint) {
+ SkBitmap bitmap;
+ hwuiBitmap.getSkBitmap(&bitmap);
SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
- sk_sp<SkImage> image = hwuiBitmap.makeImage(nullptr);
- if (!hwuiBitmap.isImmutable()) {
+ sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+ if (!bitmap.isImmutable()) {
mDisplayList->mMutableImages.push_back(image.get());
}
SkPaint tmpPaint;
@@ -203,8 +210,11 @@
void SkiaRecordingCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch& chunk,
float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) {
+ SkBitmap bitmap;
+ hwuiBitmap.getSkBitmap(&bitmap);
+
SkCanvas::Lattice lattice;
- NinePatchUtils::SetLatticeDivs(&lattice, chunk, hwuiBitmap.width(), hwuiBitmap.height());
+ NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height());
lattice.fFlags = nullptr;
int numFlags = 0;
@@ -221,8 +231,8 @@
lattice.fBounds = nullptr;
SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
- sk_sp<SkImage> image = hwuiBitmap.makeImage(nullptr);
- if (!hwuiBitmap.isImmutable()) {
+ sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+ if (!bitmap.isImmutable()) {
mDisplayList->mMutableImages.push_back(image.get());
}
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 5c2ec0e..a1f1717 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -693,18 +693,6 @@
}
}
-CREATE_BRIDGE2(makeTextureImage, RenderThread* thread, Bitmap* bitmap) {
- return args->thread->makeTextureImage(args->bitmap).release();
-}
-
-sk_sp<SkImage> RenderProxy::makeTextureImage(Bitmap* bitmap) {
- SETUP_TASK(makeTextureImage);
- args->bitmap = bitmap;
- args->thread = &RenderThread::getInstance();
- sk_sp<SkImage> hardwareImage(reinterpret_cast<SkImage*>(staticPostAndWait(task)));
- return hardwareImage;
-}
-
void RenderProxy::post(RenderTask* task) {
mRenderThread.queue(task);
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 97ad796..a60ed55 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -135,8 +135,6 @@
static sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& bitmap);
static int copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap);
-
- static sk_sp<SkImage> makeTextureImage(Bitmap* bitmap);
private:
RenderThread& mRenderThread;
CanvasContext* mContext;
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index d62b556..1450ec9 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -17,7 +17,6 @@
#include "RenderThread.h"
#include "../renderstate/RenderState.h"
-#include "../pipeline/skia/SkiaOpenGLPipeline.h"
#include "../pipeline/skia/SkiaOpenGLReadback.h"
#include "CanvasContext.h"
#include "EglManager.h"
@@ -434,24 +433,6 @@
return next;
}
-sk_sp<SkImage> RenderThread::makeTextureImage(Bitmap* bitmap) {
- auto renderType = Properties::getRenderPipelineType();
- sk_sp<SkImage> hardwareImage;
- switch (renderType) {
- case RenderPipelineType::SkiaGL:
- hardwareImage = skiapipeline::SkiaOpenGLPipeline::makeTextureImage(*this, bitmap);
- break;
- case RenderPipelineType::SkiaVulkan:
- //TODO: add Vulkan support
- break;
- default:
- LOG_ALWAYS_FATAL("makeTextureImage: canvas context type %d not supported",
- (int32_t) renderType);
- break;
- }
- return hardwareImage;
-}
-
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 34542c6..9bc5985 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -33,7 +33,6 @@
namespace android {
-class Bitmap;
class DisplayEventReceiver;
namespace uirenderer {
@@ -105,8 +104,6 @@
VulkanManager& vulkanManager() { return *mVkManager; }
- sk_sp<SkImage> makeTextureImage(Bitmap* bitmap);
-
protected:
virtual bool threadLoop() override;
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 789d5e0..ece19e4 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -148,62 +148,60 @@
* </p>
*/
public void connect() {
- if (mState != CONNECT_STATE_DISCONNECTED) {
- throw new IllegalStateException("connect() called while not disconnected (state="
- + getStateLabel(mState) + ")");
- }
- // TODO: remove this extra check.
- if (DBG) {
- if (mServiceConnection != null) {
- throw new RuntimeException("mServiceConnection should be null. Instead it is "
- + mServiceConnection);
- }
- }
- if (mServiceBinder != null) {
- throw new RuntimeException("mServiceBinder should be null. Instead it is "
- + mServiceBinder);
- }
- if (mServiceCallbacks != null) {
- throw new RuntimeException("mServiceCallbacks should be null. Instead it is "
- + mServiceCallbacks);
+ if (mState != CONNECT_STATE_DISCONNECTING && mState != CONNECT_STATE_DISCONNECTED) {
+ throw new IllegalStateException("connect() called while neither disconnecting nor "
+ + "disconnected (state=" + getStateLabel(mState) + ")");
}
mState = CONNECT_STATE_CONNECTING;
-
- final Intent intent = new Intent(MediaBrowserService.SERVICE_INTERFACE);
- intent.setComponent(mServiceComponent);
-
- final ServiceConnection thisConnection = mServiceConnection = new MediaServiceConnection();
-
- boolean bound = false;
- try {
- bound = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
- } catch (Exception ex) {
- Log.e(TAG, "Failed binding to service " + mServiceComponent);
- }
-
- if (!bound) {
- // Tell them that it didn't work. We are already on the main thread,
- // but we don't want to do callbacks inside of connect(). So post it,
- // and then check that we are on the same ServiceConnection. We know
- // we won't also get an onServiceConnected or onServiceDisconnected,
- // so we won't be doing double callbacks.
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- // Ensure that nobody else came in or tried to connect again.
- if (thisConnection == mServiceConnection) {
- forceCloseConnection();
- mCallback.onConnectionFailed();
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mState == CONNECT_STATE_DISCONNECTING) {
+ return;
+ }
+ mState = CONNECT_STATE_CONNECTING;
+ // TODO: remove this extra check.
+ if (DBG) {
+ if (mServiceConnection != null) {
+ throw new RuntimeException("mServiceConnection should be null. Instead it"
+ + " is " + mServiceConnection);
}
}
- });
- }
+ if (mServiceBinder != null) {
+ throw new RuntimeException("mServiceBinder should be null. Instead it is "
+ + mServiceBinder);
+ }
+ if (mServiceCallbacks != null) {
+ throw new RuntimeException("mServiceCallbacks should be null. Instead it is "
+ + mServiceCallbacks);
+ }
- if (DBG) {
- Log.d(TAG, "connect...");
- dump();
- }
+ final Intent intent = new Intent(MediaBrowserService.SERVICE_INTERFACE);
+ intent.setComponent(mServiceComponent);
+
+ mServiceConnection = new MediaServiceConnection();
+
+ boolean bound = false;
+ try {
+ bound = mContext.bindService(intent, mServiceConnection,
+ Context.BIND_AUTO_CREATE);
+ } catch (Exception ex) {
+ Log.e(TAG, "Failed binding to service " + mServiceComponent);
+ }
+
+ if (!bound) {
+ // Tell them that it didn't work.
+ forceCloseConnection();
+ mCallback.onConnectionFailed();
+ }
+
+ if (DBG) {
+ Log.d(TAG, "connect...");
+ dump();
+ }
+ }
+ });
}
/**
@@ -218,6 +216,7 @@
mHandler.post(new Runnable() {
@Override
public void run() {
+ // connect() could be called before this. Then we will disconnect and reconnect.
if (mServiceCallbacks != null) {
try {
mServiceBinder.disconnect(mServiceCallbacks);
@@ -227,7 +226,13 @@
Log.w(TAG, "RemoteException during connect for " + mServiceComponent);
}
}
+ int state = mState;
forceCloseConnection();
+ // If the state was not CONNECT_STATE_DISCONNECTING, keep the state so that
+ // the operation came after disconnect() can be handled properly.
+ if (state != CONNECT_STATE_DISCONNECTING) {
+ mState = state;
+ }
if (DBG) {
Log.d(TAG, "disconnect...");
dump();
@@ -245,6 +250,9 @@
* a call to mCallback.onConnectionFailed(). Disconnect doesn't do that callback
* for a clean shutdown, but everywhere else is a dirty shutdown and should
* notify the app.
+ * <p>
+ * Also, mState should be updated properly. Mostly it should be CONNECT_STATE_DIACONNECTED
+ * except for disconnect().
*/
private void forceCloseConnection() {
if (mServiceConnection != null) {
@@ -684,8 +692,9 @@
* Return true if {@code callback} is the current ServiceCallbacks. Also logs if it's not.
*/
private boolean isCurrent(IMediaBrowserServiceCallbacks callback, String funcName) {
- if (mServiceCallbacks != callback) {
- if (mState != CONNECT_STATE_DISCONNECTED) {
+ if (mServiceCallbacks != callback || mState == CONNECT_STATE_DISCONNECTING
+ || mState == CONNECT_STATE_DISCONNECTED) {
+ if (mState != CONNECT_STATE_DISCONNECTING && mState != CONNECT_STATE_DISCONNECTED) {
Log.i(TAG, funcName + " for " + mServiceComponent + " with mServiceConnection="
+ mServiceCallbacks + " this=" + this);
}
@@ -1040,8 +1049,9 @@
* Return true if this is the current ServiceConnection. Also logs if it's not.
*/
private boolean isCurrent(String funcName) {
- if (mServiceConnection != this) {
- if (mState != CONNECT_STATE_DISCONNECTED) {
+ if (mServiceConnection != this || mState == CONNECT_STATE_DISCONNECTING
+ || mState == CONNECT_STATE_DISCONNECTED) {
+ if (mState != CONNECT_STATE_DISCONNECTING && mState != CONNECT_STATE_DISCONNECTED) {
// Check mState, because otherwise this log is noisy.
Log.i(TAG, funcName + " for " + mServiceComponent + " with mServiceConnection="
+ mServiceConnection + " this=" + this);
diff --git a/media/jni/android_media_MediaCrypto.cpp b/media/jni/android_media_MediaCrypto.cpp
index 2adbfee..cbdb8ce 100644
--- a/media/jni/android_media_MediaCrypto.cpp
+++ b/media/jni/android_media_MediaCrypto.cpp
@@ -51,6 +51,9 @@
}
JCrypto::~JCrypto() {
+ if (mCrypto != NULL) {
+ mCrypto->destroyPlugin();
+ }
mCrypto.clear();
JNIEnv *env = AndroidRuntime::getJNIEnv();
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index 401012f..d4cc3fb 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -86,6 +86,7 @@
case NO_MEMORY:
return AUDIOEFFECT_ERROR_NO_MEMORY;
case DEAD_OBJECT:
+ case FAILED_TRANSACTION: // Hidl crash shows as FAILED_TRANSACTION: -2147483646
return AUDIOEFFECT_ERROR_DEAD_OBJECT;
default:
return AUDIOEFFECT_ERROR;
diff --git a/packages/MtpDocumentsProvider/AndroidManifest.xml b/packages/MtpDocumentsProvider/AndroidManifest.xml
index 843b313..8d79f62 100644
--- a/packages/MtpDocumentsProvider/AndroidManifest.xml
+++ b/packages/MtpDocumentsProvider/AndroidManifest.xml
@@ -22,7 +22,6 @@
android:label="@string/downloads_app_label"
android:icon="@mipmap/ic_launcher_download"
android:theme="@android:style/Theme.NoDisplay"
- android:screenOrientation="locked"
android:excludeFromRecents="true">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java b/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
index c5292b8..fe79266 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
@@ -18,6 +18,8 @@
import android.annotation.NonNull;
import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -27,10 +29,21 @@
* Sends intent to MtpDocumentsService.
*/
class ServiceIntentSender {
+ private final static String CHANNEL_ID = "device_notification_channel";
private Context mContext;
ServiceIntentSender(Context context) {
mContext = context;
+
+ // Create notification channel.
+ final NotificationChannel mChannel = new NotificationChannel(
+ CHANNEL_ID,
+ context.getResources().getString(
+ com.android.internal.R.string.default_notification_channel_label),
+ NotificationManager.IMPORTANCE_LOW);
+ final NotificationManager notificationManager =
+ (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ notificationManager.createNotificationChannel(mChannel);
}
/**
@@ -60,12 +73,11 @@
final String title = context.getResources().getString(
R.string.accessing_notification_title,
device.name);
- return new Notification.Builder(context)
+ return new Notification.Builder(context, CHANNEL_ID)
.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/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 0447c52..aa0becf 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -210,7 +210,7 @@
<string name="dev_settings_warning_title" msgid="7244607768088540165">"Vil du tillade udviklingsindstillinger?"</string>
<string name="dev_settings_warning_message" msgid="2298337781139097964">"Disse indstillinger er kun beregnet til brug i forbindelse med udvikling. De kan forårsage, at din enhed og dens applikationer går ned eller ikke fungerer korrekt."</string>
<string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificer apps via USB"</string>
- <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrollér apps, der er installeret via ADB/ADT, for skadelig adfærd."</string>
+ <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Tjek apps, der er installeret via ADB/ADT, for skadelig adfærd."</string>
<string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Deaktiverer funktionen til absolut lydstyrke via Bluetooth i tilfælde af problemer med lydstyrken på eksterne enheder, f.eks. uacceptabel høj lyd eller manglende kontrol."</string>
<string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"Tillad, at ringetoner på telefonen kan afspilles i Bluetooth-headset"</string>
<string name="enable_terminal_title" msgid="95572094356054120">"Lokal terminal"</string>
@@ -298,7 +298,7 @@
<string name="inactive_app_inactive_summary" msgid="5091363706699855725">"Inaktiv. Tryk for at skifte."</string>
<string name="inactive_app_active_summary" msgid="4174921824958516106">"Aktiv. Tryk for at skifte."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"Kørende tjenester"</string>
- <string name="runningservices_settings_summary" msgid="854608995821032748">"Vis og kontrollér kørende tjenester"</string>
+ <string name="runningservices_settings_summary" msgid="854608995821032748">"Vis og administrer kørende tjenester"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Konfigurer WebView-implementering"</string>
<string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Dette valg er ikke længere gyldigt. Prøv igen."</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 41a116e..3ed642d 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -294,7 +294,7 @@
<item msgid="8280754435979370728">"നമ്മൾ കാണുന്നത് പോലെയുള്ള സ്വാഭാവിക വർണ്ണങ്ങൾ"</item>
<item msgid="5363960654009010371">"ഡിജിറ്റൽ ഉള്ളടക്കത്തിനായി വർണ്ണങ്ങൾ ഒപ്റ്റിമൈസ് ചെയ്തു"</item>
</string-array>
- <string name="inactive_apps_title" msgid="1317817863508274533">"നിഷ്ക്രിയ ആപ്പ്സ്"</string>
+ <string name="inactive_apps_title" msgid="1317817863508274533">"നിഷ്ക്രിയ ആപ്പുകൾ"</string>
<string name="inactive_app_inactive_summary" msgid="5091363706699855725">"നിഷ്ക്രിയം. മാറ്റുന്നതിനു ടാപ്പുചെയ്യുക."</string>
<string name="inactive_app_active_summary" msgid="4174921824958516106">"സജീവം. മാറ്റുന്നതിന് ടാപ്പുചെയ്യുക."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index 24ede16..db9f7b8 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -19,6 +19,8 @@
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothCodecStatus;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
@@ -26,16 +28,22 @@
import android.os.ParcelUuid;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.R;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
-public final class A2dpProfile implements LocalBluetoothProfile {
+public class A2dpProfile implements LocalBluetoothProfile {
private static final String TAG = "A2dpProfile";
private static boolean V = false;
+ private Context mContext;
+
private BluetoothA2dp mService;
+ BluetoothA2dpWrapper.Factory mWrapperFactory;
+ private BluetoothA2dpWrapper mServiceWrapper;
private boolean mIsProfileReady;
private final LocalBluetoothAdapter mLocalAdapter;
@@ -59,6 +67,7 @@
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (V) Log.d(TAG,"Bluetooth service connected");
mService = (BluetoothA2dp) proxy;
+ mServiceWrapper = mWrapperFactory.getInstance(mService);
// We just bound to the service, so refresh the UI for any connected A2DP devices.
List<BluetoothDevice> deviceList = mService.getConnectedDevices();
while (!deviceList.isEmpty()) {
@@ -88,11 +97,18 @@
A2dpProfile(Context context, LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager,
LocalBluetoothProfileManager profileManager) {
+ mContext = context;
mLocalAdapter = adapter;
mDeviceManager = deviceManager;
mProfileManager = profileManager;
mLocalAdapter.getProfileProxy(context, new A2dpServiceListener(),
BluetoothProfile.A2DP);
+ mWrapperFactory = new BluetoothA2dpWrapperImpl.Factory();
+ }
+
+ @VisibleForTesting
+ void setWrapperFactory(BluetoothA2dpWrapper.Factory factory) {
+ mWrapperFactory = factory;
}
public boolean isConnectable() {
@@ -173,6 +189,72 @@
return false;
}
+ public boolean supportsHighQualityAudio(BluetoothDevice device) {
+ int support = mServiceWrapper.supportsOptionalCodecs(device);
+ return support == BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED;
+ }
+
+ public boolean isHighQualityAudioEnabled(BluetoothDevice device) {
+ int enabled = mServiceWrapper.getOptionalCodecsEnabled(device);
+ if (enabled != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN) {
+ return enabled == BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED;
+ } else if (getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED &&
+ supportsHighQualityAudio(device)) {
+ // Since we don't have a stored preference and the device isn't connected, just return
+ // true since the default behavior when the device gets connected in the future would be
+ // to have optional codecs enabled.
+ return true;
+ }
+ BluetoothCodecConfig codecConfig = null;
+ if (mServiceWrapper.getCodecStatus() != null) {
+ codecConfig = mServiceWrapper.getCodecStatus().getCodecConfig();
+ }
+ if (codecConfig != null) {
+ return !codecConfig.isMandatoryCodec();
+ } else {
+ return false;
+ }
+ }
+
+ public void setHighQualityAudioEnabled(BluetoothDevice device, boolean enabled) {
+ int prefValue = enabled
+ ? BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED
+ : BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED;
+ mServiceWrapper.setOptionalCodecsEnabled(device, prefValue);
+ if (getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED) {
+ return;
+ }
+ if (enabled) {
+ mService.enableOptionalCodecs();
+ } else {
+ mService.disableOptionalCodecs();
+ }
+ }
+
+ public String getHighQualityAudioOptionLabel(BluetoothDevice device) {
+ int unknownCodecId = R.string.bluetooth_profile_a2dp_high_quality_unknown_codec;
+ if (!supportsHighQualityAudio(device) ||
+ getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED) {
+ return mContext.getString(unknownCodecId);
+ }
+ // We want to get the highest priority codec, since that's the one that will be used with
+ // this device, and see if it is high-quality (ie non-mandatory).
+ BluetoothCodecConfig[] selectable = null;
+ if (mServiceWrapper.getCodecStatus() != null) {
+ selectable = mServiceWrapper.getCodecStatus().getCodecsSelectableCapabilities();
+ // To get the highest priority, we sort in reverse.
+ Arrays.sort(selectable,
+ (a, b) -> {
+ return b.getCodecPriority() - a.getCodecPriority();
+ });
+ }
+ if (selectable == null || selectable.length < 1 || selectable[0].isMandatoryCodec()) {
+ return mContext.getString(unknownCodecId);
+ }
+ return mContext.getString(R.string.bluetooth_profile_a2dp_high_quality,
+ selectable[0].getCodecName());
+ }
+
public String toString() {
return NAME;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapper.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapper.java
new file mode 100644
index 0000000..aa3e835
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapper.java
@@ -0,0 +1,58 @@
+/*
+ * 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.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothCodecStatus;
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * This interface replicates some methods of android.bluetooth.BluetoothA2dp that are new and not
+ * yet available in our current version of Robolectric. It provides a thin wrapper to call the real
+ * methods in production and a mock in tests.
+ */
+public interface BluetoothA2dpWrapper {
+
+ static interface Factory {
+ BluetoothA2dpWrapper getInstance(BluetoothA2dp service);
+ }
+
+ /**
+ * @return the real {@code BluetoothA2dp} object
+ */
+ BluetoothA2dp getService();
+
+ /**
+ * Wraps {@code BluetoothA2dp.getCodecStatus}
+ */
+ public BluetoothCodecStatus getCodecStatus();
+
+ /**
+ * Wraps {@code BluetoothA2dp.supportsOptionalCodecs}
+ */
+ int supportsOptionalCodecs(BluetoothDevice device);
+
+ /**
+ * Wraps {@code BluetoothA2dp.getOptionalCodecsEnabled}
+ */
+ int getOptionalCodecsEnabled(BluetoothDevice device);
+
+ /**
+ * Wraps {@code BluetoothA2dp.setOptionalCodecsEnabled}
+ */
+ void setOptionalCodecsEnabled(BluetoothDevice device, int value);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapperImpl.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapperImpl.java
new file mode 100644
index 0000000..14fa796
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapperImpl.java
@@ -0,0 +1,62 @@
+/*
+ * 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.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothCodecStatus;
+import android.bluetooth.BluetoothDevice;
+
+public class BluetoothA2dpWrapperImpl implements BluetoothA2dpWrapper {
+
+ public static class Factory implements BluetoothA2dpWrapper.Factory {
+ @Override
+ public BluetoothA2dpWrapper getInstance(BluetoothA2dp service) {
+ return new BluetoothA2dpWrapperImpl(service);
+ }
+ }
+
+ private BluetoothA2dp mService;
+
+ public BluetoothA2dpWrapperImpl(BluetoothA2dp service) {
+ mService = service;
+ }
+
+ @Override
+ public BluetoothA2dp getService() {
+ return mService;
+ }
+
+ @Override
+ public BluetoothCodecStatus getCodecStatus() {
+ return mService.getCodecStatus();
+ }
+
+ @Override
+ public int supportsOptionalCodecs(BluetoothDevice device) {
+ return mService.supportsOptionalCodecs(device);
+ }
+
+ @Override
+ public int getOptionalCodecsEnabled(BluetoothDevice device) {
+ return mService.getOptionalCodecsEnabled(device);
+ }
+
+ @Override
+ public void setOptionalCodecsEnabled(BluetoothDevice device, int value) {
+ mService.setOptionalCodecsEnabled(device, value);
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 5a9a749..0750dc7 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -42,7 +42,7 @@
* LocalBluetoothProfileManager provides access to the LocalBluetoothProfile
* objects for the available Bluetooth profiles.
*/
-public final class LocalBluetoothProfileManager {
+public class LocalBluetoothProfileManager {
private static final String TAG = "LocalBluetoothProfileManager";
private static final boolean DEBUG = Utils.D;
/** Singleton instance. */
diff --git a/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java b/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java
new file mode 100644
index 0000000..656ab86
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java
@@ -0,0 +1,25 @@
+/*
+ * 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.bluetooth;
+
+/**
+ * A placeholder class to prevent ClassNotFound exceptions caused by lack of visibility.
+ */
+public class BluetoothCodecConfig {
+ public boolean isMandatoryCodec() { return true; }
+ public String getCodecName() { return null;}
+}
diff --git a/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecStatus.java b/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecStatus.java
new file mode 100644
index 0000000..919ec3f
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecStatus.java
@@ -0,0 +1,25 @@
+/*
+ * 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.bluetooth;
+
+/**
+ * A placeholder class to prevent ClassNotFound exceptions caused by lack of visibility.
+ */
+public class BluetoothCodecStatus {
+ public BluetoothCodecConfig getCodecConfig() { return null; }
+ public BluetoothCodecConfig[] getCodecsSelectableCapabilities() { return null; }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
new file mode 100644
index 0000000..07a0e11
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
@@ -0,0 +1,203 @@
+/*
+ * 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.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothCodecStatus;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import com.android.settingslib.R;
+import com.android.settingslib.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+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.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class A2dpProfileTest {
+
+ @Mock Context mContext;
+ @Mock LocalBluetoothAdapter mAdapter;
+ @Mock CachedBluetoothDeviceManager mDeviceManager;
+ @Mock LocalBluetoothProfileManager mProfileManager;
+ @Mock BluetoothDevice mDevice;
+ @Mock BluetoothA2dp mBluetoothA2dp;
+ @Mock BluetoothA2dpWrapper mBluetoothA2dpWrapper;
+ BluetoothProfile.ServiceListener mServiceListener;
+
+ A2dpProfile mProfile;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ // Capture the A2dpServiceListener our A2dpProfile will pass during its constructor, so that
+ // we can call its onServiceConnected method and get it to use our mock BluetoothA2dp
+ // object.
+ doAnswer((invocation) -> {
+ mServiceListener = (BluetoothProfile.ServiceListener) invocation.getArguments()[1];
+ return null;
+ }).when(mAdapter).getProfileProxy(any(Context.class), any(), eq(BluetoothProfile.A2DP));
+
+ mProfile = new A2dpProfile(mContext, mAdapter, mDeviceManager, mProfileManager);
+ mProfile.setWrapperFactory((service) -> { return mBluetoothA2dpWrapper; });
+ mServiceListener.onServiceConnected(BluetoothProfile.A2DP, mBluetoothA2dp);
+ }
+
+ @Test
+ public void supportsHighQualityAudio() {
+ when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+ BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
+ assertThat(mProfile.supportsHighQualityAudio(mDevice)).isTrue();
+
+ when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+ BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
+ assertThat(mProfile.supportsHighQualityAudio(mDevice)).isFalse();
+
+ when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+ BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN);
+ assertThat(mProfile.supportsHighQualityAudio(mDevice)).isFalse();
+ }
+
+ @Test
+ public void isHighQualityAudioEnabled() {
+ when(mBluetoothA2dpWrapper.getOptionalCodecsEnabled(any())).thenReturn(
+ BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED);
+ assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isTrue();
+
+ when(mBluetoothA2dpWrapper.getOptionalCodecsEnabled(any())).thenReturn(
+ BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED);
+ assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isFalse();
+
+ // If we don't have a stored pref for whether optional codecs should be enabled or not,
+ // then isHighQualityAudioEnabled() should return true or false based on whether optional
+ // codecs are supported. If the device is connected then we should ask it directly, but if
+ // the device isn't connected then rely on the stored pref about such support.
+ when(mBluetoothA2dpWrapper.getOptionalCodecsEnabled(any())).thenReturn(
+ BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN);
+ when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
+ BluetoothProfile.STATE_DISCONNECTED);
+
+ when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+ BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
+ assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isFalse();
+
+ when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+ BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
+ assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isTrue();
+
+ when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
+ BluetoothProfile.STATE_CONNECTED);
+ BluetoothCodecStatus status = mock(BluetoothCodecStatus.class);
+ when(mBluetoothA2dpWrapper.getCodecStatus()).thenReturn(status);
+ BluetoothCodecConfig config = mock(BluetoothCodecConfig.class);
+ when(status.getCodecConfig()).thenReturn(config);
+ when(config.isMandatoryCodec()).thenReturn(false);
+ assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isTrue();
+ when(config.isMandatoryCodec()).thenReturn(true);
+ assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isFalse();
+ }
+
+ // Strings to use in fake resource lookups.
+ private static String KNOWN_CODEC_LABEL = "Use high quality audio: %1$s";
+ private static String UNKNOWN_CODEC_LABEL = "Use high quality audio";
+
+ /**
+ * Helper for setting up several tests of getHighQualityAudioOptionLabel
+ */
+ private void setupLabelTest() {
+ // SettingsLib doesn't have string resource lookup working for robotests, so fake our own
+ // string loading.
+ when(mContext.getString(eq(R.string.bluetooth_profile_a2dp_high_quality),
+ any(String.class))).thenAnswer((invocation) -> {
+ return String.format(KNOWN_CODEC_LABEL, invocation.getArguments()[1]);
+ });
+ when(mContext.getString(eq(R.string.bluetooth_profile_a2dp_high_quality_unknown_codec)))
+ .thenReturn(UNKNOWN_CODEC_LABEL);
+
+ // Most tests want to simulate optional codecs being supported by the device, so do that
+ // by default here.
+ when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+ BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
+ }
+
+ @Test
+ public void getLableCodecsNotSupported() {
+ setupLabelTest();
+ when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+ BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
+ assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(UNKNOWN_CODEC_LABEL);
+ }
+
+ @Test
+ public void getLabelDeviceDisconnected() {
+ setupLabelTest();
+ when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
+ BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(UNKNOWN_CODEC_LABEL);
+ }
+
+ @Test
+ public void getLabelDeviceConnectedButNotHighQualityCodec() {
+ setupLabelTest();
+ when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
+ BluetoothProfile.STATE_CONNECTED);
+ BluetoothCodecStatus status = mock(BluetoothCodecStatus.class);
+ BluetoothCodecConfig config = mock(BluetoothCodecConfig.class);
+ BluetoothCodecConfig[] configs = {config};
+ when(mBluetoothA2dpWrapper.getCodecStatus()).thenReturn(status);
+ when(status.getCodecsSelectableCapabilities()).thenReturn(configs);
+
+ when(config.isMandatoryCodec()).thenReturn(true);
+ assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(UNKNOWN_CODEC_LABEL);
+ }
+
+ @Test
+ public void getLabelDeviceConnectedWithHighQualityCodec() {
+ setupLabelTest();
+ when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
+ BluetoothProfile.STATE_CONNECTED);
+ BluetoothCodecStatus status = mock(BluetoothCodecStatus.class);
+ BluetoothCodecConfig config = mock(BluetoothCodecConfig.class);
+ BluetoothCodecConfig[] configs = {config};
+ when(mBluetoothA2dpWrapper.getCodecStatus()).thenReturn(status);
+ when(status.getCodecsSelectableCapabilities()).thenReturn(configs);
+
+ when(config.isMandatoryCodec()).thenReturn(false);
+ when(config.getCodecName()).thenReturn("PiedPiper");
+ assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(
+ String.format(KNOWN_CODEC_LABEL, config.getCodecName()));
+ }
+}
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 6fe00c0..bbd315e 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -71,51 +71,51 @@
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:layout_marginEnd="@*android:dimen/notification_content_margin_end"
- android:orientation="horizontal">
+ android:orientation="vertical">
<!-- Channel Text -->
<LinearLayout
- android:layout_width="0dp"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_weight="1"
- android:orientation="vertical">
+ android:orientation="horizontal">
<!-- Channel Name -->
<TextView
android:id="@+id/channel_name"
- android:layout_width="wrap_content"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
+ android:layout_weight="1"
android:layout_marginBottom="6dp"
style="@style/TextAppearance.NotificationInfo.Primary" />
- <!-- Secondary Text - only one shows at a time -->
- <TextView
- android:id="@+id/channel_disabled"
+ <!-- Ban Channel Switch -->
+ <Switch
+ android:id="@+id/channel_enabled_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/notification_channel_disabled"
- style="@style/TextAppearance.NotificationInfo.Secondary.Warning" />
- <TextView
- android:id="@+id/num_channels_desc"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/notification_channel_disabled"
- style="@style/TextAppearance.NotificationInfo.Secondary" />
- <!-- Optional link to app. Only appears if the channel is not disabled -->
- <TextView
- android:id="@+id/app_settings"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone"
- android:ellipsize="end"
- android:maxLines="1"
- style="@style/TextAppearance.NotificationInfo.Secondary.Link"/>
+ android:layout_gravity="end|center_vertical"
+ android:contentDescription="@string/notification_channel_switch_accessibility"
+ android:background="@null" />
</LinearLayout>
- <!-- Ban Channel Switch -->
- <Switch
- android:id="@+id/channel_enabled_switch"
+ <!-- Secondary Text - only one shows at a time -->
+ <TextView
+ android:id="@+id/channel_disabled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="end|center_vertical"
- android:contentDescription="@string/notification_channel_switch_accessibility"
- android:background="@null" />
+ android:text="@string/notification_channel_disabled"
+ style="@style/TextAppearance.NotificationInfo.Secondary.Warning" />
+ <TextView
+ android:id="@+id/num_channels_desc"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/notification_channel_disabled"
+ style="@style/TextAppearance.NotificationInfo.Secondary" />
+ <!-- Optional link to app. Only appears if the channel is not disabled -->
+ <TextView
+ android:id="@+id/app_settings"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:ellipsize="end"
+ android:maxLines="1"
+ style="@style/TextAppearance.NotificationInfo.Secondary.Link"/>
</LinearLayout>
<!-- Settings and Done buttons -->
diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml
index 7367a10..629e306 100644
--- a/packages/SystemUI/res/values-it/strings_tv.xml
+++ b/packages/SystemUI/res/values-it/strings_tv.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture-in-picture"</string>
+ <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture-in-Picture"</string>
<string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Programma senza titolo)"</string>
<string name="pip_close" msgid="3480680679023423574">"Chiudi PIP"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"Schermo intero"</string>
diff --git a/packages/SystemUI/res/values-pa/strings_tv.xml b/packages/SystemUI/res/values-pa/strings_tv.xml
index bdd8bee..245fc44 100644
--- a/packages/SystemUI/res/values-pa/strings_tv.xml
+++ b/packages/SystemUI/res/values-pa/strings_tv.xml
@@ -20,7 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="notification_channel_tv_pip" msgid="134047986446577723">"ਤਸਵੀਰ-ਵਿੱਚ-ਤਸਵੀਰ"</string>
- <string name="pip_notification_unknown_title" msgid="6289156118095849438">"(ਕੋਈ ਸਿਰਲੇਖ ਪ੍ਰੋਗਰਾਮ ਨਹੀਂ)"</string>
+ <string name="pip_notification_unknown_title" msgid="6289156118095849438">"(ਸਿਰਲੇਖ-ਰਹਿਤ ਪ੍ਰੋਗਰਾਮ)"</string>
<string name="pip_close" msgid="3480680679023423574">"PIP ਬੰਦ ਕਰੋ"</string>
<string name="pip_fullscreen" msgid="8604643018538487816">"ਪੂਰੀ ਸਕ੍ਰੀਨ"</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 2d30476..ad82840 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -164,7 +164,7 @@
private int mRingMode;
private int mPhoneState;
private boolean mKeyguardIsVisible;
-
+ private boolean mKeyguardGoingAway;
private boolean mGoingToSleep;
private boolean mBouncer;
private boolean mBootCompleted;
@@ -406,6 +406,14 @@
}
}
+ /**
+ * Updates KeyguardUpdateMonitor's internal state to know if keyguard is goingAway
+ * @param goingAway
+ */
+ public void setKeyguardGoingAway(boolean goingAway) {
+ mKeyguardGoingAway = goingAway;
+ }
+
private void onFingerprintAuthenticated(int userId) {
Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated");
mUserFingerprintAuthenticated.put(userId, true);
@@ -1113,7 +1121,8 @@
}
private boolean shouldListenForFingerprint() {
- return (mKeyguardIsVisible || !mDeviceInteractive || mBouncer || mGoingToSleep)
+ return (mKeyguardIsVisible || !mDeviceInteractive ||
+ (mBouncer && !mKeyguardGoingAway) || mGoingToSleep)
&& !mSwitchingUser && !isFingerprintDisabled(getCurrentUser());
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 2504e36..f618a2c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -162,6 +162,7 @@
private static final int NOTIFY_SCREEN_TURNED_ON = 15;
private static final int NOTIFY_SCREEN_TURNED_OFF = 16;
private static final int NOTIFY_STARTED_GOING_TO_SLEEP = 17;
+ private static final int SET_SWITCHING_USER = 18;
/**
* The default amount of time we stay awake (used for all key input)
@@ -1398,7 +1399,11 @@
}
public void setSwitchingUser(boolean switching) {
- KeyguardUpdateMonitor.getInstance(mContext).setSwitchingUser(switching);
+ Trace.beginSection("KeyguardViewMediator#setSwitchingUser");
+ mHandler.removeMessages(SET_SWITCHING_USER);
+ Message msg = mHandler.obtainMessage(SET_SWITCHING_USER, switching ? 1 : 0, 0);
+ mHandler.sendMessage(msg);
+ Trace.endSection();
}
/**
@@ -1538,6 +1543,11 @@
Log.w(TAG, "Timeout while waiting for activity drawn!");
Trace.endSection();
break;
+ case SET_SWITCHING_USER:
+ Trace.beginSection("KeyguardViewMediator#handleMessage SET_SWITCHING_USER");
+ KeyguardUpdateMonitor.getInstance(mContext).setSwitchingUser(msg.arg1 != 0);
+ Trace.endSection();
+ break;
}
}
};
@@ -1696,7 +1706,6 @@
mHideAnimationRun = false;
adjustStatusBarLocked();
userActivity();
-
mShowKeyguardWakeLock.release();
}
mKeyguardDisplayManager.show();
@@ -1723,6 +1732,7 @@
flags |= WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
}
+ mUpdateMonitor.setKeyguardGoingAway(true /* goingAway */);
// Don't actually hide the Keyguard at the moment, wait for window
// manager until it tells us it's safe to do so with
// startKeyguardExitAnimation.
@@ -1804,6 +1814,7 @@
adjustStatusBarLocked();
mDismissCallbackRegistry.notifyDismissSucceeded();
sendUserPresentBroadcast();
+ mUpdateMonitor.setKeyguardGoingAway(false /* goingAway */);
}
Trace.endSection();
}
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 da2d38f..0da4681 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -16,9 +16,11 @@
package com.android.systemui.pip.phone;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.view.Display.DEFAULT_DISPLAY;
import android.app.ActivityManager;
+import android.app.ActivityManager.StackInfo;
import android.app.IActivityManager;
import android.content.ComponentName;
import android.content.Context;
@@ -33,6 +35,8 @@
import android.view.WindowManagerGlobal;
import com.android.systemui.pip.BasePipManager;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.component.ExpandPipEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
import com.android.systemui.statusbar.CommandQueue;
@@ -65,7 +69,7 @@
*/
TaskStackListener mTaskStackListener = new TaskStackListener() {
@Override
- public void onActivityPinned(String packageName) {
+ public void onActivityPinned(String packageName, int taskId) {
if (!checkCurrentUserId(false /* debug */)) {
return;
}
@@ -186,6 +190,7 @@
mInputConsumerController);
mNotificationController = new PipNotificationController(context, mActivityManager,
mTouchHandler.getMotionHelper());
+ EventBus.getDefault().register(this);
}
/**
@@ -196,6 +201,26 @@
}
/**
+ * Expands the PIP.
+ */
+ public final void onBusEvent(ExpandPipEvent event) {
+ if (event.clearThumbnailWindows) {
+ try {
+ StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
+ if (stackInfo != null && stackInfo.taskIds != null) {
+ SystemServicesProxy ssp = SystemServicesProxy.getInstance(mContext);
+ for (int taskId : stackInfo.taskIds) {
+ ssp.cancelThumbnailTransition(taskId);
+ }
+ }
+ } catch (RemoteException e) {
+ // Do nothing
+ }
+ }
+ mTouchHandler.getMotionHelper().expandPip(false /* skipAnimation */);
+ }
+
+ /**
* Sent from KEYCODE_WINDOW handler in PhoneWindowManager, to request the menu to be shown.
*/
public void showPictureInPictureMenu() {
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 766914c..fbb97b6 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -63,6 +63,8 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.component.HidePipMenuEvent;
import java.util.ArrayList;
import java.util.Collections;
@@ -231,6 +233,7 @@
super.onStop();
cancelDelayedFinish();
+ EventBus.getDefault().unregister(this);
}
@Override
@@ -290,6 +293,19 @@
// Do nothing
}
+ public final void onBusEvent(HidePipMenuEvent event) {
+ if (mMenuState != MENU_STATE_NONE) {
+ // If the menu is visible in either the closed or full state, then hide the menu and
+ // trigger the animation trigger afterwards
+ event.getAnimationTrigger().increment();
+ hideMenu(() -> {
+ mHandler.post(() -> {
+ event.getAnimationTrigger().decrement();
+ });
+ }, true /* notifyMenuVisibility */);
+ }
+ }
+
private void showMenu(int menuState, Rect stackBounds, Rect movementBounds,
boolean allowMenuTimeout) {
mAllowMenuTimeout = allowMenuTimeout;
@@ -373,11 +389,16 @@
private void updateFromIntent(Intent intent) {
mToControllerMessenger = intent.getParcelableExtra(EXTRA_CONTROLLER_MESSENGER);
notifyActivityCallback(mMessenger);
+
+ // Register for HidePipMenuEvents once we notify the controller of this activity
+ EventBus.getDefault().register(this);
+
ParceledListSlice actions = intent.getParcelableExtra(EXTRA_ACTIONS);
if (actions != null) {
mActions.clear();
mActions.addAll(actions.getList());
}
+
final int menuState = intent.getIntExtra(EXTRA_MENU_STATE, MENU_STATE_NONE);
if (menuState != MENU_STATE_NONE) {
Rect stackBounds = intent.getParcelableExtra(EXTRA_STACK_BOUNDS);
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 5afa53f..1ccea6f 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -36,6 +36,9 @@
import android.view.IWindowManager;
import com.android.systemui.pip.phone.PipMediaController.ActionListener;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.component.HidePipMenuEvent;
+import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -119,6 +122,7 @@
// The dismiss fraction update is sent frequently, so use a temporary bundle for the message
private Bundle mTmpDismissFractionData = new Bundle();
+ private ReferenceCountedTrigger mOnAttachDecrementTrigger;
private boolean mStartActivityRequested;
private Messenger mToActivityMessenger;
private Messenger mMessenger = new Messenger(new Handler() {
@@ -157,6 +161,10 @@
case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
mToActivityMessenger = msg.replyTo;
mStartActivityRequested = false;
+ if (mOnAttachDecrementTrigger != null) {
+ mOnAttachDecrementTrigger.decrement();
+ mOnAttachDecrementTrigger = null;
+ }
// Mark the menu as invisible once the activity finishes as well
if (mToActivityMessenger == null) {
onMenuStateChanged(MENU_STATE_NONE, true /* resize */);
@@ -181,6 +189,8 @@
mActivityManager = activityManager;
mMediaController = mediaController;
mInputConsumerController = inputConsumerController;
+
+ EventBus.getDefault().register(this);
}
public void onActivityPinned() {
@@ -435,6 +445,15 @@
mMenuState = menuState;
}
+ public final void onBusEvent(HidePipMenuEvent event) {
+ if (mStartActivityRequested) {
+ // If the menu has been start-requested, but not actually started, then we defer the
+ // trigger callback until the menu has started and called back to the controller
+ mOnAttachDecrementTrigger = event.getAnimationTrigger();
+ mOnAttachDecrementTrigger.increment();
+ }
+ }
+
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
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 6667b71..1c5da4d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -34,7 +34,6 @@
import android.os.Debug;
import android.os.Handler;
import android.os.RemoteException;
-import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
@@ -43,7 +42,6 @@
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
-import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.pip.BasePipManager;
import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -109,7 +107,7 @@
private IWindowManager mWindowManager;
private MediaSessionManager mMediaSessionManager;
private int mState = STATE_NO_PIP;
- private int mResumeResizePinnedStackRunnable = STATE_NO_PIP;
+ private int mResumeResizePinnedStackRunnableState = STATE_NO_PIP;
private final Handler mHandler = new Handler();
private List<Listener> mListeners = new ArrayList<>();
private List<MediaListener> mMediaListeners = new ArrayList<>();
@@ -130,7 +128,7 @@
private final Runnable mResizePinnedStackRunnable = new Runnable() {
@Override
public void run() {
- resizePinnedStack(mResumeResizePinnedStackRunnable);
+ resizePinnedStack(mResumeResizePinnedStackRunnableState);
}
};
private final Runnable mClosePipRunnable = new Runnable() {
@@ -278,7 +276,7 @@
* Shows the picture-in-picture menu if an activity is in picture-in-picture mode.
*/
public void showPictureInPictureMenu() {
- if (mState == STATE_PIP) {
+ if (getState() == STATE_PIP) {
resizePinnedStack(STATE_PIP_MENU);
}
}
@@ -352,14 +350,15 @@
void resizePinnedStack(int state) {
if (DEBUG) Log.d(TAG, "resizePinnedStack() state=" + state, new Exception());
boolean wasStateNoPip = (mState == STATE_NO_PIP);
- mResumeResizePinnedStackRunnable = state;
for (int i = mListeners.size() - 1; i >= 0; --i) {
mListeners.get(i).onPipResizeAboutToStart();
}
if (mSuspendPipResizingReason != 0) {
+ mResumeResizePinnedStackRunnableState = state;
if (DEBUG) Log.d(TAG, "resizePinnedStack() deferring"
+ " mSuspendPipResizingReason=" + mSuspendPipResizingReason
- + " mResumeResizePinnedStackRunnable=" + mResumeResizePinnedStackRunnable);
+ + " mResumeResizePinnedStackRunnableState="
+ + mResumeResizePinnedStackRunnableState);
return;
}
mState = state;
@@ -392,6 +391,16 @@
}
/**
+ * @return the current state, or the pending state if the state change was previously suspended.
+ */
+ private int getState() {
+ if (mSuspendPipResizingReason != 0) {
+ return mResumeResizePinnedStackRunnableState;
+ }
+ return mState;
+ }
+
+ /**
* Returns the default PIP bound.
*/
public Rect getPipBounds() {
@@ -459,7 +468,7 @@
}
private void handleMediaResourceGranted(String[] packageNames) {
- if (mState == STATE_NO_PIP) {
+ if (getState() == STATE_NO_PIP) {
mLastPackagesResourceGranted = packageNames;
} else {
boolean requestedFromLastPackages = false;
@@ -482,7 +491,7 @@
private void updateMediaController(List<MediaController> controllers) {
MediaController mediaController = null;
- if (controllers != null && mState != STATE_NO_PIP && mPipComponentName != null) {
+ if (controllers != null && getState() != STATE_NO_PIP && mPipComponentName != null) {
for (int i = controllers.size() - 1; i >= 0; i--) {
MediaController controller = controllers.get(i);
// We assumes that an app with PIPable activity
@@ -571,7 +580,7 @@
if (!checkCurrentUserId(DEBUG)) {
return;
}
- if (mState != STATE_NO_PIP) {
+ if (getState() != STATE_NO_PIP) {
boolean hasPip = false;
StackInfo stackInfo = getPinnedStackInfo();
@@ -593,7 +602,7 @@
return;
}
}
- if (mState == STATE_PIP) {
+ if (getState() == STATE_PIP) {
Rect bounds = isSettingsShown() ? mSettingsPipBounds : mDefaultPipBounds;
if (mPipBounds != bounds) {
mPipBounds = bounds;
@@ -603,7 +612,7 @@
}
@Override
- public void onActivityPinned(String packageName) {
+ public void onActivityPinned(String packageName, int taskId) {
if (DEBUG) Log.d(TAG, "onActivityPinned()");
if (!checkCurrentUserId(DEBUG)) {
return;
@@ -645,7 +654,7 @@
if (!checkCurrentUserId(DEBUG)) {
return;
}
- switch (mState) {
+ switch (getState()) {
case STATE_PIP_MENU:
showPipMenu();
break;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index c0e4b99..dbf0724 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -62,6 +62,7 @@
import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
+import com.android.systemui.recents.events.component.ActivityUnpinnedEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
@@ -203,8 +204,12 @@
Recents.getSystemServices().removeTask(task.persistentId);
}
}
- Settings.Secure.putLongForUser(RecentsActivity.this.getContentResolver(),
- Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, currentTime, currentUser);
+ Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync(
+ currentTime, currentUser);
+
+ // Clear the last PiP task time, it's an edge case and we'd rather it
+ // not relaunch the PiP task if the user double taps
+ RecentsImpl.clearLastPipTime();
}
}
}
@@ -395,6 +400,7 @@
* Reloads the stack views upon launching Recents.
*/
private void reloadStackView() {
+
// If the Recents component has preloaded a load plan, then use that to prevent
// reconstructing the task stack
RecentsTaskLoader loader = Recents.getTaskLoader();
@@ -501,28 +507,7 @@
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
super.onMultiWindowModeChanged(isInMultiWindowMode);
- // Reload the task stack completely
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
- RecentsTaskLoader loader = Recents.getTaskLoader();
- RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(this);
- loader.preloadTasks(loadPlan, -1 /* runningTaskId */,
- false /* includeFrontMostExcludedTask */);
-
- RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
- loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
- loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
- loader.loadTasks(this, loadPlan, loadOpts);
-
- TaskStack stack = loadPlan.getTaskStack();
- int numStackTasks = stack.getStackTaskCount();
- boolean showDeferredAnimation = numStackTasks > 0;
-
- EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */,
- false /* fromDeviceOrientationChange */, false /* fromDisplayDensityChange */,
- numStackTasks > 0));
- EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode,
- showDeferredAnimation, stack));
+ reloadTaskStack(isInMultiWindowMode, true /* sendConfigChangedEvent */);
}
@Override
@@ -821,6 +806,41 @@
mRecentsView.invalidate();
}
+ public final void onBusEvent(final ActivityUnpinnedEvent event) {
+ if (mIsVisible) {
+ // Skip the configuration change event as the PiP activity does not actually affect the
+ // config of recents
+ reloadTaskStack(isInMultiWindowMode(), false /* sendConfigChangedEvent */);
+ }
+ }
+
+ private void reloadTaskStack(boolean isInMultiWindowMode, boolean sendConfigChangedEvent) {
+ // Reload the task stack completely
+ RecentsConfiguration config = Recents.getConfiguration();
+ RecentsActivityLaunchState launchState = config.getLaunchState();
+ RecentsTaskLoader loader = Recents.getTaskLoader();
+ RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(this);
+ loader.preloadTasks(loadPlan, -1 /* runningTaskId */,
+ false /* includeFrontMostExcludedTask */);
+
+ RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
+ loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
+ loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
+ loader.loadTasks(this, loadPlan, loadOpts);
+
+ TaskStack stack = loadPlan.getTaskStack();
+ int numStackTasks = stack.getStackTaskCount();
+ boolean showDeferredAnimation = numStackTasks > 0;
+
+ if (sendConfigChangedEvent) {
+ EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */,
+ false /* fromDeviceOrientationChange */, false /* fromDisplayDensityChange */,
+ numStackTasks > 0));
+ }
+ EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode,
+ showDeferredAnimation, stack));
+ }
+
@Override
public boolean onPreDraw() {
mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
index a7f6b70..5b8ed94 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
@@ -29,6 +29,10 @@
public boolean launchedWithAltTab;
public boolean launchedFromApp;
+ // Set if the activity that we launched from entered PiP during the transition into Recents
+ public boolean launchedFromPipApp;
+ // Set if the next activity that quick-switch will launch is the PiP activity
+ public boolean launchedWithNextPipApp;
public boolean launchedFromBlacklistedApp;
public boolean launchedFromHome;
public boolean launchedViaDragGesture;
@@ -41,6 +45,8 @@
launchedFromHome = false;
launchedFromApp = false;
launchedFromBlacklistedApp = false;
+ launchedFromPipApp = false;
+ launchedWithNextPipApp = false;
launchedToTaskId = -1;
launchedWithAltTab = false;
launchedViaDragGesture = false;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 2b812a5..e229c90 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -35,15 +35,18 @@
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.util.Log;
import android.util.MutableBoolean;
+import android.util.Pair;
import android.view.AppTransitionAnimationSpec;
import android.view.LayoutInflater;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.widget.Toast;
+
+import com.google.android.collect.Lists;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.policy.DockedDividerUtils;
import com.android.systemui.R;
@@ -57,6 +60,9 @@
import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
+import com.android.systemui.recents.events.component.ActivityPinnedEvent;
+import com.android.systemui.recents.events.component.ActivityUnpinnedEvent;
+import com.android.systemui.recents.events.component.HidePipMenuEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
@@ -71,6 +77,8 @@
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskGrouping;
import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.views.RecentsTransitionHelper;
+import com.android.systemui.recents.views.RecentsTransitionHelper.AppTransitionAnimationSpecsFuture;
import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
import com.android.systemui.recents.views.TaskStackLayoutAlgorithm.VisibilityReport;
import com.android.systemui.recents.views.TaskStackView;
@@ -127,6 +135,7 @@
// previous one.
VisibilityReport visibilityReport;
synchronized (mDummyStackView) {
+ mDummyStackView.getStack().removeAllTasks(false /* notifyStackChanges */);
mDummyStackView.setTasks(plan.getTaskStack(), false /* allowNotify */);
updateDummyStackViewLayout(plan.getTaskStack(),
getWindowRect(null /* windowRectOverride */));
@@ -151,12 +160,31 @@
}
@Override
+ public void onActivityPinned(String packageName, int taskId) {
+ // This time needs to be fetched the same way the last active time is fetched in
+ // {@link TaskRecord#touchActiveTime}
+ Recents.getConfiguration().getLaunchState().launchedFromPipApp = true;
+ Recents.getConfiguration().getLaunchState().launchedWithNextPipApp = false;
+ EventBus.getDefault().send(new ActivityPinnedEvent(taskId));
+ consumeInstanceLoadPlan();
+ sLastPipTime = System.currentTimeMillis();
+ }
+
+ @Override
+ public void onActivityUnpinned() {
+ EventBus.getDefault().send(new ActivityUnpinnedEvent());
+ sLastPipTime = -1;
+ }
+
+ @Override
public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) {
EventBus.getDefault().send(new TaskSnapshotChangedEvent(taskId, snapshot));
}
}
protected static RecentsTaskLoadPlan sInstanceLoadPlan;
+ // Stores the last pinned task time
+ protected static long sLastPipTime = -1;
protected Context mContext;
protected Handler mHandler;
@@ -477,7 +505,8 @@
// Launch the task
ssp.startActivityFromRecents(
- mContext, toTask.key, toTask.title, launchOpts, INVALID_STACK_ID);
+ mContext, toTask.key, toTask.title, launchOpts, INVALID_STACK_ID,
+ null /* resultListener */);
}
/**
@@ -550,7 +579,8 @@
// Launch the task
ssp.startActivityFromRecents(
- mContext, toTask.key, toTask.title, launchOpts, INVALID_STACK_ID);
+ mContext, toTask.key, toTask.title, launchOpts, INVALID_STACK_ID,
+ null /* resultListener */);
}
public void showNextAffiliatedTask() {
@@ -593,6 +623,20 @@
}
/**
+ * @return the time at which a task last entered picture-in-picture.
+ */
+ public static long getLastPipTime() {
+ return sLastPipTime;
+ }
+
+ /**
+ * Clears the time at which a task last entered picture-in-picture.
+ */
+ public static void clearLastPipTime() {
+ sLastPipTime = -1;
+ }
+
+ /**
* Reloads all the resources for the current configuration.
*/
private void reloadResources() {
@@ -632,7 +676,7 @@
windowRect.bottom -= systemInsets.bottom;
systemInsets.bottom = 0;
}
- calculateWindowStableInsets(systemInsets, windowRect);
+ calculateWindowStableInsets(systemInsets, windowRect, displayRect);
windowRect.offsetTo(0, 0);
synchronized (mDummyStackView) {
@@ -674,6 +718,7 @@
updateDummyStackViewLayout(stack, windowRect);
if (stack != null) {
TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm();
+ mDummyStackView.getStack().removeAllTasks(false /* notifyStackChanges */);
mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */);
// Get the width of a task view so that we know how wide to draw the header bar.
if (useGridLayout) {
@@ -721,8 +766,7 @@
* Given the stable insets and the rect for our window, calculates the insets that affect our
* window.
*/
- private void calculateWindowStableInsets(Rect inOutInsets, Rect windowRect) {
- Rect displayRect = Recents.getSystemServices().getDisplayRect();
+ private void calculateWindowStableInsets(Rect inOutInsets, Rect windowRect, Rect displayRect) {
// Display rect without insets - available app space
Rect appRect = new Rect(displayRect);
@@ -772,8 +816,9 @@
/**
* Creates the activity options for an app->recents transition.
*/
- private ActivityOptions getThumbnailTransitionActivityOptions(
- ActivityManager.RunningTaskInfo runningTask, Rect windowOverrideRect) {
+ private Pair<ActivityOptions, AppTransitionAnimationSpecsFuture>
+ getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo runningTask,
+ Rect windowOverrideRect) {
if (runningTask != null && runningTask.stackId == FREEFORM_WORKSPACE_STACK_ID) {
ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>();
ArrayList<Task> tasks;
@@ -804,23 +849,27 @@
}
AppTransitionAnimationSpec[] specsArray = new AppTransitionAnimationSpec[specs.size()];
specs.toArray(specsArray);
- return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
- specsArray, mHandler, null, this);
+ return new Pair<>(ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
+ specsArray, mHandler, null, this), null);
} else {
// Update the destination rect
Task toTask = new Task();
TaskViewTransform toTransform = getThumbnailTransitionTransform(mDummyStackView, toTask,
windowOverrideRect);
- Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform,
- mThumbTransitionBitmapCache);
- if (thumbnail != null) {
- RectF toTaskRect = toTransform.rect;
- return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
- thumbnail, (int) toTaskRect.left, (int) toTaskRect.top,
- (int) toTaskRect.width(), (int) toTaskRect.height(), mHandler, null);
- }
- // If both the screenshot and thumbnail fails, then just fall back to the default transition
- return getUnknownTransitionActivityOptions();
+
+ RectF toTaskRect = toTransform.rect;
+ AppTransitionAnimationSpecsFuture future =
+ new RecentsTransitionHelper(mContext).getAppTransitionFuture(
+ () -> {
+ Rect rect = new Rect();
+ toTaskRect.round(rect);
+ Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform,
+ mThumbTransitionBitmapCache);
+ return Lists.newArrayList(new AppTransitionAnimationSpec(
+ toTask.key.id, thumbnail, rect));
+ });
+ return new Pair<>(ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(mContext,
+ mHandler, future.getFuture(), null, false /* scaleUp */), future);
}
}
@@ -919,6 +968,9 @@
launchState.launchedFromHome = !useThumbnailTransition && !mLaunchedWhileDocking;
launchState.launchedFromApp = useThumbnailTransition || mLaunchedWhileDocking;
launchState.launchedFromBlacklistedApp = launchState.launchedFromApp && isBlacklisted;
+ launchState.launchedFromPipApp = false;
+ launchState.launchedWithNextPipApp =
+ stack.isNextLaunchTargetPip(RecentsImpl.getLastPipTime());
launchState.launchedViaDockGesture = mLaunchedWhileDocking;
launchState.launchedViaDragGesture = mDraggingInRecents;
launchState.launchedToTaskId = runningTaskId;
@@ -943,30 +995,31 @@
launchState.launchedNumVisibleThumbnails = stackVr.numVisibleThumbnails;
if (!animate) {
- startRecentsActivity(ActivityOptions.makeCustomAnimation(mContext, -1, -1));
+ startRecentsActivity(ActivityOptions.makeCustomAnimation(mContext, -1, -1),
+ null /* future */);
return;
}
- ActivityOptions opts;
+ Pair<ActivityOptions, AppTransitionAnimationSpecsFuture> pair;
if (isBlacklisted) {
- opts = getUnknownTransitionActivityOptions();
+ pair = new Pair<>(getUnknownTransitionActivityOptions(), null);
} else if (useThumbnailTransition) {
// Try starting with a thumbnail transition
- opts = getThumbnailTransitionActivityOptions(runningTask, windowOverrideRect);
+ pair = getThumbnailTransitionActivityOptions(runningTask, windowOverrideRect);
} else {
// If there is no thumbnail transition, but is launching from home into recents, then
// use a quick home transition
- opts = hasRecentTasks
- ? getHomeTransitionActivityOptions()
- : getUnknownTransitionActivityOptions();
+ pair = new Pair<>(hasRecentTasks
+ ? getHomeTransitionActivityOptions()
+ : getUnknownTransitionActivityOptions(), null);
}
- startRecentsActivity(opts);
+ startRecentsActivity(pair.first, pair.second);
mLastToggleTime = SystemClock.elapsedRealtime();
}
private Rect getWindowRectOverride(int growTarget) {
if (growTarget == DividerView.INVALID_RECENTS_GROW_TARGET) {
- return null;
+ return SystemServicesProxy.getInstance(mContext).getWindowRect();
}
Rect result = new Rect();
Rect displayRect = Recents.getSystemServices().getDisplayRect();
@@ -979,19 +1032,23 @@
/**
* Starts the recents activity.
*/
- private void startRecentsActivity(ActivityOptions opts) {
+ private void startRecentsActivity(ActivityOptions opts,
+ final AppTransitionAnimationSpecsFuture future) {
Intent intent = new Intent();
intent.setClassName(RECENTS_PACKAGE, RECENTS_ACTIVITY);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
| Intent.FLAG_ACTIVITY_TASK_ON_HOME);
-
- if (opts != null) {
- mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT);
- } else {
- mContext.startActivityAsUser(intent, UserHandle.CURRENT);
- }
- EventBus.getDefault().send(new RecentsActivityStartingEvent());
+ Recents.getSystemServices().startActivityAsUserAsync(intent, opts);
+ HidePipMenuEvent hideMenuEvent = new HidePipMenuEvent();
+ hideMenuEvent.addPostAnimationCallback(() -> {
+ Recents.getSystemServices().startActivityAsUserAsync(intent, opts);
+ EventBus.getDefault().send(new RecentsActivityStartingEvent());
+ if (future != null) {
+ future.precacheSpecs();
+ }
+ });
+ EventBus.getDefault().send(hideMenuEvent);
}
/**** OnAnimationFinishedListener Implementation ****/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
index a737505..d7abb38 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
@@ -810,6 +810,11 @@
private void queueEvent(final Event event) {
ArrayList<EventHandler> eventHandlers = mEventTypeMap.get(event.getClass());
if (eventHandlers == null) {
+ // This is just an optimization to return early if there are no handlers. However, we
+ // should still ensure that we call pre/post dispatch callbacks so that AnimatedEvents
+ // are still cleaned up correctly if a listener has not been registered to handle them
+ event.onPreDispatch();
+ event.onPostDispatch();
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java
new file mode 100644
index 0000000..75bfd7b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.recents.events.activity;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * Sent when the stack should be hidden and the empty view shown.
+ */
+public class ShowEmptyViewEvent extends EventBus.Event {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java
new file mode 100644
index 0000000..f4d2fcf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.component;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when an activity is pinned.
+ */
+public class ActivityPinnedEvent extends EventBus.Event {
+
+ public final int taskId;
+
+ public ActivityPinnedEvent(int taskId) {
+ this.taskId = taskId;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java
new file mode 100644
index 0000000..48c5f0b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.component;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when an activity is unpinned.
+ */
+public class ActivityUnpinnedEvent extends EventBus.Event {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ExpandPipEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/ExpandPipEvent.java
new file mode 100644
index 0000000..8fe4975
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/ExpandPipEvent.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.component;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when the PiP should be expanded due to being relaunched.
+ */
+public class ExpandPipEvent extends EventBus.Event {
+ public final boolean clearThumbnailWindows = true;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java
new file mode 100644
index 0000000..ce4f207
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.component;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when the PiP menu should be hidden.
+ */
+public class HidePipMenuEvent extends EventBus.AnimatedEvent {
+ // Simple event
+}
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 8594ec62..6707c15 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -26,6 +26,7 @@
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityManager.TaskSnapshot;
@@ -57,15 +58,18 @@
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.IRemoteCallback;
-import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.provider.Settings.Secure;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
import android.util.ArraySet;
import android.util.IconDrawableFactory;
import android.util.Log;
@@ -127,6 +131,8 @@
PackageManager mPm;
IconDrawableFactory mDrawableFactory;
IPackageManager mIpm;
+ private final IDreamManager mDreamManager;
+ private final Context mContext;
AssistUtils mAssistUtils;
WindowManager mWm;
IWindowManager mIwm;
@@ -160,7 +166,7 @@
public void onTaskStackChangedBackground() { }
public void onTaskStackChanged() { }
public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
- public void onActivityPinned(String packageName) { }
+ public void onActivityPinned(String packageName, int taskId) { }
public void onActivityUnpinned() { }
public void onPinnedActivityRestartAttempt(boolean clearedTask) { }
public void onPinnedStackAnimationStarted() { }
@@ -215,9 +221,9 @@
}
@Override
- public void onActivityPinned(String packageName) throws RemoteException {
+ public void onActivityPinned(String packageName, int taskId) throws RemoteException {
mHandler.removeMessages(H.ON_ACTIVITY_PINNED);
- mHandler.obtainMessage(H.ON_ACTIVITY_PINNED, packageName).sendToTarget();
+ mHandler.obtainMessage(H.ON_ACTIVITY_PINNED, taskId, 0, packageName).sendToTarget();
}
@Override
@@ -282,6 +288,7 @@
/** Private constructor */
private SystemServicesProxy(Context context) {
+ mContext = context.getApplicationContext();
mAccm = AccessibilityManager.getInstance(context);
mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
mIam = ActivityManager.getService();
@@ -293,6 +300,8 @@
mIwm = WindowManagerGlobal.getWindowManagerService();
mKgm = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
mUm = UserManager.get(context);
+ mDreamManager = IDreamManager.Stub.asInterface(
+ ServiceManager.checkService(DreamService.DREAM_SERVICE));
mDisplay = mWm.getDefaultDisplay();
mRecentsPackage = context.getPackageName();
mHasFreeformWorkspaceSupport =
@@ -446,9 +455,18 @@
* Returns the top running task.
*/
public ActivityManager.RunningTaskInfo getRunningTask() {
- List<ActivityManager.RunningTaskInfo> tasks = mAm.getRunningTasks(1);
+ // Note: The set of running tasks from the system is ordered by recency
+ List<ActivityManager.RunningTaskInfo> tasks = mAm.getRunningTasks(10);
if (tasks != null && !tasks.isEmpty()) {
- return tasks.get(0);
+ // Find the first task in a valid stack, we ignore everything from the Recents and PiP
+ // stacks
+ for (int i = 0; i < tasks.size(); i++) {
+ ActivityManager.RunningTaskInfo task = tasks.get(i);
+ int stackId = task.stackId;
+ if (stackId != RECENTS_STACK_ID && stackId != PINNED_STACK_ID) {
+ return task;
+ }
+ }
}
return null;
}
@@ -1011,7 +1029,12 @@
* Returns the current user id.
*/
public int getCurrentUser() {
- return KeyguardUpdateMonitor.getCurrentUser();
+ if (mAm == null) return 0;
+
+ // This must call through ActivityManager, as the SystemServicesProxy can be called in a
+ // secondary user's SystemUI process, and KeyguardUpdateMonitor is only updated in the
+ // primary user's SystemUI process
+ return mAm.getCurrentUser();
}
/**
@@ -1115,32 +1138,50 @@
}
}
+ public void startActivityAsUserAsync(Intent intent, ActivityOptions opts) {
+ mOnewayExecutor.submit(() -> mContext.startActivityAsUser(intent,
+ opts != null ? opts.toBundle() : null, UserHandle.CURRENT));
+ }
+
/** Starts an activity from recents. */
- public boolean startActivityFromRecents(Context context, Task.TaskKey taskKey, String taskName,
- ActivityOptions options, int stackId) {
- if (mIam != null) {
- try {
- if (taskKey.stackId == DOCKED_STACK_ID) {
- // We show non-visible docked tasks in Recents, but we always want to launch
- // them in the fullscreen stack.
- if (options == null) {
- options = ActivityOptions.makeBasic();
- }
- options.setLaunchStackId(FULLSCREEN_WORKSPACE_STACK_ID);
- } else if (stackId != INVALID_STACK_ID){
- if (options == null) {
- options = ActivityOptions.makeBasic();
- }
- options.setLaunchStackId(stackId);
- }
- mIam.startActivityFromRecents(
- taskKey.id, options == null ? null : options.toBundle());
- return true;
- } catch (Exception e) {
- Log.e(TAG, context.getString(R.string.recents_launch_error_message, taskName), e);
- }
+ public void startActivityFromRecents(Context context, Task.TaskKey taskKey, String taskName,
+ ActivityOptions options, int stackId,
+ @Nullable final StartActivityFromRecentsResultListener resultListener) {
+ if (mIam == null) {
+ return;
}
- return false;
+ if (taskKey.stackId == DOCKED_STACK_ID) {
+ // We show non-visible docked tasks in Recents, but we always want to launch
+ // them in the fullscreen stack.
+ if (options == null) {
+ options = ActivityOptions.makeBasic();
+ }
+ options.setLaunchStackId(FULLSCREEN_WORKSPACE_STACK_ID);
+ } else if (stackId != INVALID_STACK_ID) {
+ if (options == null) {
+ options = ActivityOptions.makeBasic();
+ }
+ options.setLaunchStackId(stackId);
+ }
+ final ActivityOptions finalOptions = options;
+
+ // Execute this from another thread such that we can do other things (like caching the
+ // bitmap for the thumbnail) while AM is busy starting our activity.
+ mOnewayExecutor.submit(() -> {
+ try {
+ mIam.startActivityFromRecents(
+ taskKey.id, finalOptions == null ? null : finalOptions.toBundle());
+ if (resultListener != null) {
+ mHandler.post(() -> resultListener.onStartActivityResult(true));
+ }
+ } catch (Exception e) {
+ Log.e(TAG, context.getString(
+ R.string.recents_launch_error_message, taskName), e);
+ if (resultListener != null) {
+ mHandler.post(() -> resultListener.onStartActivityResult(false));
+ }
+ }
+ });
}
/** Starts an in-place animation on the front most application windows. */
@@ -1258,6 +1299,37 @@
}
}
+ public boolean isDreaming() {
+ try {
+ return mDreamManager.isDreaming();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to query dream manager.", e);
+ }
+ return false;
+ }
+
+ public void awakenDreamsAsync() {
+ mOnewayExecutor.submit(() -> {
+ try {
+ mDreamManager.awaken();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ public void updateOverviewLastStackActiveTimeAsync(long newLastStackActiveTime,
+ int currentUserId) {
+ mOnewayExecutor.submit(() -> {
+ Settings.Secure.putLongForUser(mContext.getContentResolver(),
+ Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, newLastStackActiveTime, currentUserId);
+ });
+ }
+
+ public interface StartActivityFromRecentsResultListener {
+ void onStartActivityResult(boolean succeeded);
+ }
+
private final class H extends Handler {
private static final int ON_TASK_STACK_CHANGED = 1;
private static final int ON_TASK_SNAPSHOT_CHANGED = 2;
@@ -1294,7 +1366,7 @@
}
case ON_ACTIVITY_PINNED: {
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
- mTaskStackListeners.get(i).onActivityPinned((String) msg.obj);
+ mTaskStackListeners.get(i).onActivityPinned((String) msg.obj, msg.arg1);
}
break;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 7ee0906..ed09640 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -87,7 +87,7 @@
mCurrentQuietProfiles.clear();
if (currentUserId == UserHandle.USER_CURRENT) {
- currentUserId = KeyguardUpdateMonitor.getCurrentUser();
+ currentUserId = SystemServicesProxy.getInstance(mContext).getCurrentUser();
}
UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
List<UserInfo> profiles = userManager.getProfiles(currentUserId);
@@ -218,8 +218,8 @@
affiliatedTasks.put(taskKey.id, taskKey);
}
if (newLastStackActiveTime != -1) {
- Settings.Secure.putLongForUser(mContext.getContentResolver(),
- Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, newLastStackActiveTime, currentUserId);
+ Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync(
+ newLastStackActiveTime, currentUserId);
}
// Initialize the stacks
@@ -316,9 +316,8 @@
for (int i = 0; i < users.size(); i++) {
int userId = users.get(i).id;
if (userId != currentUserId) {
- Settings.Secure.putLongForUser(mContext.getContentResolver(),
- Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, legacyLastStackActiveTime,
- userId);
+ Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync(
+ legacyLastStackActiveTime, userId);
}
}
return legacyLastStackActiveTime;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 97a9659..c5a292f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -28,6 +28,7 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
+import android.os.Trace;
import android.util.Log;
import android.util.LruCache;
@@ -351,7 +352,12 @@
/** Preloads recents tasks using the specified plan to store the output. */
public synchronized void preloadTasks(RecentsTaskLoadPlan plan, int runningTaskId,
boolean includeFrontMostExcludedTask) {
- plan.preloadPlan(this, runningTaskId, includeFrontMostExcludedTask);
+ try {
+ Trace.beginSection("preloadPlan");
+ plan.preloadPlan(this, runningTaskId, includeFrontMostExcludedTask);
+ } finally {
+ Trace.endSection();
+ }
}
/** Begins loading the heavy task data according to the specified options. */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 9b25ef8..6e3be09 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -229,7 +229,8 @@
* Notifies when a task has been removed from the stack.
*/
void onStackTaskRemoved(TaskStack stack, Task removedTask, Task newFrontMostTask,
- AnimationProps animation, boolean fromDockGesture);
+ AnimationProps animation, boolean fromDockGesture,
+ boolean dismissRecentsIfAllRemoved);
/**
* Notifies when all tasks have been removed from the stack.
@@ -631,13 +632,22 @@
* how they should update themselves.
*/
public void removeTask(Task t, AnimationProps animation, boolean fromDockGesture) {
+ removeTask(t, animation, fromDockGesture, true /* dismissRecentsIfAllRemoved */);
+ }
+
+ /**
+ * Removes a task from the stack, with an additional {@param animation} hint to the callbacks on
+ * how they should update themselves.
+ */
+ public void removeTask(Task t, AnimationProps animation, boolean fromDockGesture,
+ boolean dismissRecentsIfAllRemoved) {
if (mStackTaskList.contains(t)) {
removeTaskImpl(mStackTaskList, t);
Task newFrontMostTask = getStackFrontMostTask(false /* includeFreeform */);
if (mCb != null) {
// Notify that a task has been removed
mCb.onStackTaskRemoved(this, t, newFrontMostTask, animation,
- fromDockGesture);
+ fromDockGesture, dismissRecentsIfAllRemoved);
}
}
mRawTaskList.remove(t);
@@ -646,19 +656,27 @@
/**
* Removes all tasks from the stack.
*/
- public void removeAllTasks() {
+ public void removeAllTasks(boolean notifyStackChanges) {
ArrayList<Task> tasks = mStackTaskList.getTasks();
for (int i = tasks.size() - 1; i >= 0; i--) {
Task t = tasks.get(i);
removeTaskImpl(mStackTaskList, t);
mRawTaskList.remove(t);
}
- if (mCb != null) {
+ if (mCb != null && notifyStackChanges) {
// Notify that all tasks have been removed
mCb.onStackTasksRemoved(this);
}
}
+
+ /**
+ * @see #setTasks(Context, List, boolean, boolean)
+ */
+ public void setTasks(Context context, TaskStack stack, boolean notifyStackChanges) {
+ setTasks(context, stack.mRawTaskList, notifyStackChanges);
+ }
+
/**
* Sets a few tasks in one go, without calling any callbacks.
*
@@ -723,7 +741,8 @@
Task newFrontMostTask = getStackFrontMostTask(false);
for (int i = 0; i < removedTaskCount; i++) {
mCb.onStackTaskRemoved(this, removedTasks.get(i), newFrontMostTask,
- AnimationProps.IMMEDIATE, false /* fromDockGesture */);
+ AnimationProps.IMMEDIATE, false /* fromDockGesture */,
+ true /* dismissRecentsIfAllRemoved */);
}
// Only callback for the newly added tasks after this stack has been updated
@@ -854,21 +873,46 @@
}
/**
+ * Returns whether the next launch target should actually be the PiP task.
+ */
+ public boolean isNextLaunchTargetPip(long lastPipTime) {
+ Task launchTarget = getLaunchTarget();
+ Task nextLaunchTarget = getNextLaunchTargetRaw();
+ if (nextLaunchTarget != null && lastPipTime > 0) {
+ // If the PiP time is more recent than the next launch target, then launch the PiP task
+ return lastPipTime > nextLaunchTarget.key.lastActiveTime;
+ } else if (launchTarget != null && lastPipTime > 0 && getTaskCount() == 1) {
+ // Otherwise, if there is no next launch target, but there is a PiP, then launch
+ // the PiP task
+ return true;
+ }
+ return false;
+ }
+
+ /**
* Returns the task in stack tasks which should be launched next if Recents are toggled
- * again, or null if there is no task to be launched.
+ * again, or null if there is no task to be launched. Callers should check
+ * {@link #isNextLaunchTargetPip(long)} before fetching the next raw launch target from the
+ * stack.
*/
public Task getNextLaunchTarget() {
+ Task nextLaunchTarget = getNextLaunchTargetRaw();
+ if (nextLaunchTarget != null) {
+ return nextLaunchTarget;
+ }
+ return getStackTasks().get(getTaskCount() - 1);
+ }
+
+ private Task getNextLaunchTargetRaw() {
int taskCount = getTaskCount();
if (taskCount == 0) {
return null;
}
int launchTaskIndex = indexOfStackTask(getLaunchTarget());
- if (launchTaskIndex != -1) {
- launchTaskIndex = Math.max(0, launchTaskIndex - 1);
- } else {
- launchTaskIndex = getTaskCount() - 1;
+ if (launchTaskIndex != -1 && launchTaskIndex > 0) {
+ return getStackTasks().get(launchTaskIndex - 1);
}
- return getStackTasks().get(launchTaskIndex);
+ return null;
}
/** Returns the index of this task in this current task stack */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 8882cab..d7d264e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -101,57 +101,49 @@
*/
public void launchTaskFromRecents(final TaskStack stack, @Nullable final Task task,
final TaskStackView stackView, final TaskView taskView,
- final boolean screenPinningRequested, final Rect bounds, final int destinationStack) {
- final ActivityOptions opts = ActivityOptions.makeBasic();
- if (bounds != null) {
- opts.setLaunchBounds(bounds.isEmpty() ? null : bounds);
- }
+ final boolean screenPinningRequested, final int destinationStack) {
final ActivityOptions.OnAnimationStartedListener animStartedListener;
- final IAppTransitionAnimationSpecsFuture transitionFuture;
+ final AppTransitionAnimationSpecsFuture transitionFuture;
if (taskView != null) {
- transitionFuture = getAppTransitionFuture(new AnimationSpecComposer() {
- @Override
- public List<AppTransitionAnimationSpec> composeSpecs() {
- return composeAnimationSpecs(task, stackView, destinationStack);
- }
- });
- animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
- @Override
- public void onAnimationStarted() {
- // If we are launching into another task, cancel the previous task's
- // window transition
- EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
- EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
- stackView.cancelAllTaskViewAnimations();
- if (screenPinningRequested) {
- // Request screen pinning after the animation runs
- mStartScreenPinningRunnable.taskId = task.key.id;
- mHandler.postDelayed(mStartScreenPinningRunnable, 350);
- }
+ // Fetch window rect here already in order not to be blocked on lock contention in WM
+ // when the future calls it.
+ final Rect windowRect = Recents.getSystemServices().getWindowRect();
+ transitionFuture = getAppTransitionFuture(
+ () -> composeAnimationSpecs(task, stackView, destinationStack, windowRect));
+ animStartedListener = () -> {
+ // If we are launching into another task, cancel the previous task's
+ // window transition
+ EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
+ EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
+ stackView.cancelAllTaskViewAnimations();
+
+ if (screenPinningRequested) {
+ // Request screen pinning after the animation runs
+ mStartScreenPinningRunnable.taskId = task.key.id;
+ mHandler.postDelayed(mStartScreenPinningRunnable, 350);
}
};
} else {
// This is only the case if the task is not on screen (scrolled offscreen for example)
transitionFuture = null;
- animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
- @Override
- public void onAnimationStarted() {
- // If we are launching into another task, cancel the previous task's
- // window transition
- EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
- EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
- stackView.cancelAllTaskViewAnimations();
- }
+ animStartedListener = () -> {
+ // If we are launching into another task, cancel the previous task's
+ // window transition
+ EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
+ EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
+ stackView.cancelAllTaskViewAnimations();
};
}
+ final ActivityOptions opts = ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(mContext,
+ mHandler, transitionFuture != null ? transitionFuture.future : null,
+ animStartedListener, true /* scaleUp */);
if (taskView == null) {
// If there is no task view, then we do not need to worry about animating out occluding
// task views, and we can launch immediately
- startTaskActivity(stack, task, taskView, opts, transitionFuture, animStartedListener,
- destinationStack);
+ startTaskActivity(stack, task, taskView, opts, transitionFuture, destinationStack);
} else {
LaunchTaskStartedEvent launchStartedEvent = new LaunchTaskStartedEvent(taskView,
screenPinningRequested);
@@ -160,14 +152,13 @@
@Override
public void run() {
startTaskActivity(stack, task, taskView, opts, transitionFuture,
- animStartedListener, destinationStack);
+ destinationStack);
}
});
EventBus.getDefault().send(launchStartedEvent);
} else {
EventBus.getDefault().send(launchStartedEvent);
- startTaskActivity(stack, task, taskView, opts, transitionFuture,
- animStartedListener, destinationStack);
+ startTaskActivity(stack, task, taskView, opts, transitionFuture, destinationStack);
}
}
Recents.getSystemServices().sendCloseSystemWindows(
@@ -199,30 +190,31 @@
* @param destinationStack id of the stack to put the task into.
*/
private void startTaskActivity(TaskStack stack, Task task, @Nullable TaskView taskView,
- ActivityOptions opts, IAppTransitionAnimationSpecsFuture transitionFuture,
- final OnAnimationStartedListener animStartedListener, int destinationStack) {
+ ActivityOptions opts, AppTransitionAnimationSpecsFuture transitionFuture,
+ int destinationStack) {
SystemServicesProxy ssp = Recents.getSystemServices();
- if (ssp.startActivityFromRecents(mContext, task.key, task.title, opts, destinationStack)) {
- // Keep track of the index of the task launch
- int taskIndexFromFront = 0;
- int taskIndex = stack.indexOfStackTask(task);
- if (taskIndex > -1) {
- taskIndexFromFront = stack.getTaskCount() - taskIndex - 1;
- }
- EventBus.getDefault().send(new LaunchTaskSucceededEvent(taskIndexFromFront));
- } else {
- // Dismiss the task if we fail to launch it
- if (taskView != null) {
- taskView.dismissTask();
- }
+ ssp.startActivityFromRecents(mContext, task.key, task.title, opts, destinationStack,
+ succeeded -> {
+ if (succeeded) {
+ // Keep track of the index of the task launch
+ int taskIndexFromFront = 0;
+ int taskIndex = stack.indexOfStackTask(task);
+ if (taskIndex > -1) {
+ taskIndexFromFront = stack.getTaskCount() - taskIndex - 1;
+ }
+ EventBus.getDefault().send(new LaunchTaskSucceededEvent(taskIndexFromFront));
+ } else {
+ // Dismiss the task if we fail to launch it
+ if (taskView != null) {
+ taskView.dismissTask();
+ }
- // Keep track of failed launches
- EventBus.getDefault().send(new LaunchTaskFailedEvent());
- }
-
+ // Keep track of failed launches
+ EventBus.getDefault().send(new LaunchTaskFailedEvent());
+ }
+ });
if (transitionFuture != null) {
- ssp.overridePendingAppTransitionMultiThumbFuture(transitionFuture,
- wrapStartedListener(animStartedListener), true /* scaleUp */);
+ mHandler.post(transitionFuture::precacheSpecs);
}
}
@@ -231,21 +223,18 @@
*
* @param composer The implementation that composes the specs on the UI thread.
*/
- public IAppTransitionAnimationSpecsFuture getAppTransitionFuture(
+ public AppTransitionAnimationSpecsFuture getAppTransitionFuture(
final AnimationSpecComposer composer) {
synchronized (this) {
mAppTransitionAnimationSpecs = SPECS_WAITING;
}
- return new IAppTransitionAnimationSpecsFuture.Stub() {
+ IAppTransitionAnimationSpecsFuture future = new IAppTransitionAnimationSpecsFuture.Stub() {
@Override
public AppTransitionAnimationSpec[] get() throws RemoteException {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- synchronized (RecentsTransitionHelper.this) {
- mAppTransitionAnimationSpecs = composer.composeSpecs();
- RecentsTransitionHelper.this.notifyAll();
- }
+ mHandler.post(() -> {
+ synchronized (RecentsTransitionHelper.this) {
+ mAppTransitionAnimationSpecs = composer.composeSpecs();
+ RecentsTransitionHelper.this.notifyAll();
}
});
synchronized (RecentsTransitionHelper.this) {
@@ -265,6 +254,7 @@
}
}
};
+ return new AppTransitionAnimationSpecsFuture(composer, future);
}
/**
@@ -283,7 +273,7 @@
* Composes the animation specs for all the tasks in the target stack.
*/
private List<AppTransitionAnimationSpec> composeAnimationSpecs(final Task task,
- final TaskStackView stackView, final int destinationStack) {
+ final TaskStackView stackView, final int destinationStack, Rect windowRect) {
// Ensure we have a valid target stack id
final int targetStackId = destinationStack != INVALID_STACK_ID ?
destinationStack : task.key.stackId;
@@ -309,8 +299,7 @@
specs.add(composeOffscreenAnimationSpec(task, offscreenTaskRect));
} else {
mTmpTransform.fillIn(taskView);
- stackLayout.transformToScreenCoordinates(mTmpTransform,
- null /* windowOverrideRect */);
+ stackLayout.transformToScreenCoordinates(mTmpTransform, windowRect);
AppTransitionAnimationSpec spec = composeAnimationSpec(stackView, taskView,
mTmpTransform, true /* addHeaderBitmap */);
if (spec != null) {
@@ -430,4 +419,34 @@
public interface AnimationSpecComposer {
List<AppTransitionAnimationSpec> composeSpecs();
}
+
+ /**
+ * Class to be returned from {@link #composeAnimationSpec} that gives access to both the future
+ * and the anonymous class used for composing.
+ */
+ public class AppTransitionAnimationSpecsFuture {
+
+ private final AnimationSpecComposer composer;
+ private final IAppTransitionAnimationSpecsFuture future;
+
+ private AppTransitionAnimationSpecsFuture(AnimationSpecComposer composer,
+ IAppTransitionAnimationSpecsFuture future) {
+ this.composer = composer;
+ this.future = future;
+ }
+
+ public IAppTransitionAnimationSpecsFuture getFuture() {
+ return future;
+ }
+
+ /**
+ * Manually generates and caches the spec such that they are already available when the
+ * future needs.
+ */
+ public void precacheSpecs() {
+ synchronized (RecentsTransitionHelper.this) {
+ mAppTransitionAnimationSpecs = composer.composeSpecs();
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 8f9c457..a0ad782 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -24,19 +24,16 @@
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.Outline;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.ArraySet;
import android.util.AttributeSet;
import android.view.AppTransitionAnimationSpec;
-import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewDebug;
-import android.view.ViewOutlineProvider;
import android.view.ViewPropertyAnimator;
import android.view.WindowInsets;
import android.widget.FrameLayout;
@@ -58,7 +55,9 @@
import com.android.systemui.recents.events.activity.HideStackActionButtonEvent;
import com.android.systemui.recents.events.activity.LaunchTaskEvent;
import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
+import com.android.systemui.recents.events.activity.ShowEmptyViewEvent;
import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent;
+import com.android.systemui.recents.events.component.ExpandPipEvent;
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
@@ -73,10 +72,10 @@
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.views.RecentsTransitionHelper.AnimationSpecComposer;
+import com.android.systemui.recents.views.RecentsTransitionHelper.AppTransitionAnimationSpecsFuture;
import com.android.systemui.stackdivider.WindowManagerProxy;
import com.android.systemui.statusbar.FlingAnimationUtils;
-import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -253,6 +252,12 @@
/** Launches the task that recents was launched from if possible */
public boolean launchPreviousTask() {
+ if (Recents.getConfiguration().getLaunchState().launchedFromPipApp) {
+ // If the app auto-entered PiP on the way to Recents, then just re-expand it
+ EventBus.getDefault().send(new ExpandPipEvent());
+ return true;
+ }
+
if (mTaskStackView != null) {
Task task = getStack().getLaunchTarget();
if (task != null) {
@@ -440,8 +445,7 @@
public final void onBusEvent(LaunchTaskEvent event) {
mLastTaskLaunchedWasFreeform = event.task.isFreeformTask();
mTransitionHelper.launchTaskFromRecents(getStack(), event.task, mTaskStackView,
- event.taskView, event.screenPinningRequested, event.targetTaskBounds,
- event.targetTaskStack);
+ event.taskView, event.screenPinningRequested, event.targetTaskStack);
}
public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
@@ -523,7 +527,7 @@
};
final Rect taskRect = getTaskRect(event.taskView);
- IAppTransitionAnimationSpecsFuture future =
+ AppTransitionAnimationSpecsFuture future =
mTransitionHelper.getAppTransitionFuture(
new AnimationSpecComposer() {
@Override
@@ -532,7 +536,7 @@
event.taskView, taskRect);
}
});
- ssp.overridePendingAppTransitionMultiThumbFuture(future,
+ ssp.overridePendingAppTransitionMultiThumbFuture(future.getFuture(),
mTransitionHelper.wrapStartedListener(startedListener),
true /* scaleUp */);
@@ -639,6 +643,10 @@
updateStack(event.stack, false /* setStackViewTasks */);
}
+ public final void onBusEvent(ShowEmptyViewEvent event) {
+ showEmptyView(R.string.recents_empty_message);
+ }
+
/**
* Shows the stack action button.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 7ba705e..8135034 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -562,7 +562,8 @@
mMinScrollP = 0;
mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
Math.max(0, mFocusedRange.getAbsoluteX(maxBottomNormX)));
- if (launchState.launchedFromHome) {
+ if (launchState.launchedFromHome || launchState.launchedFromPipApp
+ || launchState.launchedWithNextPipApp) {
mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
} else {
mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
@@ -581,8 +582,8 @@
mMinScrollP = 0;
mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
Math.max(0, mUnfocusedRange.getAbsoluteX(maxBottomNormX)));
- boolean scrollToFront = launchState.launchedFromHome ||
- launchState.launchedViaDockGesture;
+ boolean scrollToFront = launchState.launchedFromHome || launchState.launchedFromPipApp
+ || launchState.launchedWithNextPipApp || launchState.launchedViaDockGesture;
if (launchState.launchedFromBlacklistedApp) {
mInitialScrollP = mMaxScrollP;
} else if (launchState.launchedWithAltTab) {
@@ -608,6 +609,8 @@
mTaskIndexOverrideMap.clear();
boolean scrollToFront = launchState.launchedFromHome ||
+ launchState.launchedFromPipApp ||
+ launchState.launchedWithNextPipApp ||
launchState.launchedFromBlacklistedApp ||
launchState.launchedViaDockGesture;
if (getInitialFocusState() == STATE_UNFOCUSED && mNumStackTasks > 1) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 18a9bab..5f9a8f5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -57,6 +57,7 @@
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsDebugFlags;
+import com.android.systemui.recents.RecentsImpl;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
@@ -72,7 +73,11 @@
import com.android.systemui.recents.events.activity.LaunchTaskStartedEvent;
import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
import com.android.systemui.recents.events.activity.PackagesChangedEvent;
+import com.android.systemui.recents.events.activity.ShowEmptyViewEvent;
import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent;
+import com.android.systemui.recents.events.component.ActivityPinnedEvent;
+import com.android.systemui.recents.events.component.ExpandPipEvent;
+import com.android.systemui.recents.events.component.HidePipMenuEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
@@ -379,8 +384,7 @@
// Only notify if we are already initialized, otherwise, everything will pick up all the
// new and old tasks when we next layout
- mStack.setTasks(getContext(), stack.computeAllTasksList(),
- allowNotifyStackChanges && isInitialized);
+ mStack.setTasks(getContext(), stack, allowNotifyStackChanges && isInitialized);
}
/** Returns the task stack. */
@@ -1496,7 +1500,7 @@
*/
@Override
public void onStackTaskRemoved(TaskStack stack, Task removedTask, Task newFrontMostTask,
- AnimationProps animation, boolean fromDockGesture) {
+ AnimationProps animation, boolean fromDockGesture, boolean dismissRecentsIfAllRemoved) {
if (mFocusedTask == removedTask) {
resetFocusedTask(removedTask);
}
@@ -1527,9 +1531,13 @@
// If there are no remaining tasks, then just close recents
if (mStack.getTaskCount() == 0) {
- EventBus.getDefault().send(new AllTaskViewsDismissedEvent(fromDockGesture
- ? R.string.recents_empty_message
- : R.string.recents_empty_message_dismissed_all));
+ if (dismissRecentsIfAllRemoved) {
+ EventBus.getDefault().send(new AllTaskViewsDismissedEvent(fromDockGesture
+ ? R.string.recents_empty_message
+ : R.string.recents_empty_message_dismissed_all));
+ } else {
+ EventBus.getDefault().send(new ShowEmptyViewEvent());
+ }
}
}
@@ -1802,14 +1810,36 @@
return;
}
- final Task launchTask = mStack.getNextLaunchTarget();
- if (launchTask != null) {
- launchTask(launchTask);
- MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
- launchTask.key.getComponent().toString());
- } else if (mStack.getTaskCount() == 0) {
- // If there are no tasks, then just hide recents back to home.
- EventBus.getDefault().send(new HideRecentsEvent(false, true));
+ if (mStack.getTaskCount() == 0) {
+ if (RecentsImpl.getLastPipTime() != -1) {
+ EventBus.getDefault().send(new ExpandPipEvent());
+ MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
+ "pip");
+ } else {
+ // If there are no tasks, then just hide recents back to home.
+ EventBus.getDefault().send(new HideRecentsEvent(false, true));
+ }
+ return;
+ }
+
+ if (!Recents.getConfiguration().getLaunchState().launchedFromPipApp
+ && mStack.isNextLaunchTargetPip(RecentsImpl.getLastPipTime())) {
+ // If the launch task is in the pinned stack, then expand the PiP now
+ EventBus.getDefault().send(new ExpandPipEvent());
+ MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK, "pip");
+ } else {
+ final Task launchTask = mStack.getNextLaunchTarget();
+ if (launchTask != null) {
+ // Defer launching the task until the PiP menu has been dismissed (if it is
+ // showing at all)
+ HidePipMenuEvent hideMenuEvent = new HidePipMenuEvent();
+ hideMenuEvent.addPostAnimationCallback(() -> {
+ launchTask(launchTask);
+ });
+ EventBus.getDefault().send(hideMenuEvent);
+ MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
+ launchTask.key.getComponent().toString());
+ }
}
}
@@ -1871,7 +1901,7 @@
R.string.accessibility_recents_all_items_dismissed));
// Remove all tasks and delete the task data for all tasks
- mStack.removeAllTasks();
+ mStack.removeAllTasks(true /* notifyStackChanges */);
for (int i = tasks.size() - 1; i >= 0; i--) {
EventBus.getDefault().send(new DeleteTaskDataEvent(tasks.get(i)));
}
@@ -2217,11 +2247,23 @@
}
}
+ public final void onBusEvent(ActivityPinnedEvent event) {
+ // If an activity enters PiP while Recents is open, remove the stack task associated with
+ // the new PiP task
+ Task removeTask = mStack.findTaskWithId(event.taskId);
+ if (removeTask != null) {
+ // In this case, we remove the task, but if the last task is removed, don't dismiss
+ // Recents to home
+ mStack.removeTask(removeTask, AnimationProps.IMMEDIATE, false /* fromDockGesture */,
+ false /* dismissRecentsIfAllRemoved */);
+ }
+ updateLayoutAlgorithm(false /* boundScroll */);
+ updateToInitialState();
+ }
+
public void reloadOnConfigurationChange() {
mStableLayoutAlgorithm.reloadOnConfigurationChange(getContext());
mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
-
- boolean hasDockedTask = Recents.getSystemServices().hasDockedTask();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 24a2927..0c77036 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -1169,7 +1169,7 @@
}
public final void onBusEvent(RecentsActivityStartingEvent recentsActivityStartingEvent) {
- if (mGrowRecents && getWindowManagerProxy().getDockSide() == WindowManager.DOCKED_TOP
+ if (mGrowRecents && mDockSide == WindowManager.DOCKED_TOP
&& getSnapAlgorithm().getMiddleTarget() != getSnapAlgorithm().getLastSplitTarget()
&& getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position) {
mState.growAfterRecentsDrawn = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index be221bb..bf89b01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -279,7 +279,9 @@
public void toggleRecentApps() {
synchronized (mLock) {
mHandler.removeMessages(MSG_TOGGLE_RECENT_APPS);
- mHandler.obtainMessage(MSG_TOGGLE_RECENT_APPS, 0, 0, null).sendToTarget();
+ Message msg = mHandler.obtainMessage(MSG_TOGGLE_RECENT_APPS, 0, 0, null);
+ msg.setAsynchronous(true);
+ msg.sendToTarget();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
index 9a3de61..80854ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
@@ -24,7 +24,6 @@
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.support.annotation.VisibleForTesting;
-import android.support.v4.graphics.ColorUtils;
import android.support.v7.graphics.Palette;
import android.util.LayoutDirection;
@@ -41,10 +40,31 @@
/**
* The fraction below which we select the vibrant instead of the light/dark vibrant color
*/
- private static final float POPULATION_FRACTION_FOR_MORE_VIBRANT = 0.75f;
+ private static final float POPULATION_FRACTION_FOR_MORE_VIBRANT = 1.0f;
+
+ /**
+ * Minimum saturation that a muted color must have if there exists if deciding between two
+ * colors
+ */
+ private static final float MIN_SATURATION_WHEN_DECIDING = 0.19f;
+
+ /**
+ * Minimum fraction that any color must have to be picked up as a text color
+ */
+ private static final double MINIMUM_IMAGE_FRACTION = 0.002;
+
+ /**
+ * The population fraction to select the dominant color as the text color over a the colored
+ * ones.
+ */
+ private static final float POPULATION_FRACTION_FOR_DOMINANT = 0.01f;
+
+ /**
+ * The population fraction to select a white or black color as the background over a color.
+ */
private static final float POPULATION_FRACTION_FOR_WHITE_OR_BLACK = 2.5f;
private static final float BLACK_MAX_LIGHTNESS = 0.08f;
- private static final float WHITE_MIN_LIGHTNESS = 0.92f;
+ private static final float WHITE_MIN_LIGHTNESS = 0.90f;
private static final int RESIZE_BITMAP_AREA = 150 * 150;
private final ImageGradientColorizer mColorizer;
private final Context mContext;
@@ -109,8 +129,11 @@
.resizeBitmapArea(RESIZE_BITMAP_AREA);
Palette palette = paletteBuilder.generate();
backgroundColor = findBackgroundColorAndFilter(palette);
- // we want the full region again
- paletteBuilder.setRegion(0, 0, bitmap.getWidth(), bitmap.getHeight());
+ // we want most of the full region again, slightly shifted to the right
+ float textColorStartWidthFraction = 0.4f;
+ paletteBuilder.setRegion((int) (bitmap.getWidth() * textColorStartWidthFraction), 0,
+ bitmap.getWidth(),
+ bitmap.getHeight());
if (mFilteredBackgroundHsl != null) {
paletteBuilder.addFilter((rgb, hsl) -> {
// at least 10 degrees hue difference
@@ -120,78 +143,7 @@
}
paletteBuilder.addFilter(mBlackWhiteFilter);
palette = paletteBuilder.generate();
- int foregroundColor;
- if (NotificationColorUtil.isColorLight(backgroundColor)) {
- Palette.Swatch first = palette.getDarkVibrantSwatch();
- Palette.Swatch second = palette.getVibrantSwatch();
- if (first != null && second != null) {
- int firstPopulation = first.getPopulation();
- int secondPopulation = second.getPopulation();
- if (firstPopulation / secondPopulation
- < POPULATION_FRACTION_FOR_MORE_VIBRANT) {
- foregroundColor = second.getRgb();
- } else {
- foregroundColor = first.getRgb();
- }
- } else if (first != null) {
- foregroundColor = first.getRgb();
- } else if (second != null) {
- foregroundColor = second.getRgb();
- } else {
- first = palette.getMutedSwatch();
- second = palette.getDarkMutedSwatch();
- if (first != null && second != null) {
- float firstSaturation = first.getHsl()[1];
- float secondSaturation = second.getHsl()[1];
- if (firstSaturation > secondSaturation) {
- foregroundColor = first.getRgb();
- } else {
- foregroundColor = second.getRgb();
- }
- } else if (first != null) {
- foregroundColor = first.getRgb();
- } else if (second != null) {
- foregroundColor = second.getRgb();
- } else {
- foregroundColor = Color.BLACK;
- }
- }
- } else {
- Palette.Swatch first = palette.getLightVibrantSwatch();
- Palette.Swatch second = palette.getVibrantSwatch();
- if (first != null && second != null) {
- int firstPopulation = first.getPopulation();
- int secondPopulation = second.getPopulation();
- if (firstPopulation / secondPopulation
- < POPULATION_FRACTION_FOR_MORE_VIBRANT) {
- foregroundColor = second.getRgb();
- } else {
- foregroundColor = first.getRgb();
- }
- } else if (first != null) {
- foregroundColor = first.getRgb();
- } else if (second != null) {
- foregroundColor = second.getRgb();
- } else {
- first = palette.getMutedSwatch();
- second = palette.getLightMutedSwatch();
- if (first != null && second != null) {
- float firstSaturation = first.getHsl()[1];
- float secondSaturation = second.getHsl()[1];
- if (firstSaturation > secondSaturation) {
- foregroundColor = first.getRgb();
- } else {
- foregroundColor = second.getRgb();
- }
- } else if (first != null) {
- foregroundColor = first.getRgb();
- } else if (second != null) {
- foregroundColor = second.getRgb();
- } else {
- foregroundColor = Color.WHITE;
- }
- }
- }
+ int foregroundColor = selectForegroundColor(backgroundColor, palette);
builder.setColorPalette(backgroundColor, foregroundColor);
} else {
int id = mIsLowPriority
@@ -206,6 +158,95 @@
}
}
+ private int selectForegroundColor(int backgroundColor, Palette palette) {
+ if (NotificationColorUtil.isColorLight(backgroundColor)) {
+ return selectForegroundColorForSwatches(palette.getDarkVibrantSwatch(),
+ palette.getVibrantSwatch(),
+ palette.getDarkMutedSwatch(),
+ palette.getMutedSwatch(),
+ palette.getDominantSwatch(),
+ Color.BLACK);
+ } else {
+ return selectForegroundColorForSwatches(palette.getLightVibrantSwatch(),
+ palette.getVibrantSwatch(),
+ palette.getLightMutedSwatch(),
+ palette.getMutedSwatch(),
+ palette.getDominantSwatch(),
+ Color.WHITE);
+ }
+ }
+
+ private int selectForegroundColorForSwatches(Palette.Swatch moreVibrant,
+ Palette.Swatch vibrant, Palette.Swatch moreMutedSwatch, Palette.Swatch mutedSwatch,
+ Palette.Swatch dominantSwatch, int fallbackColor) {
+ Palette.Swatch coloredCandidate = selectVibrantCandidate(moreVibrant, vibrant);
+ if (coloredCandidate == null) {
+ coloredCandidate = selectMutedCandidate(mutedSwatch, moreMutedSwatch);
+ }
+ if (coloredCandidate != null) {
+ if (dominantSwatch == coloredCandidate) {
+ return coloredCandidate.getRgb();
+ } else if ((float) coloredCandidate.getPopulation() / dominantSwatch.getPopulation()
+ < POPULATION_FRACTION_FOR_DOMINANT
+ && dominantSwatch.getHsl()[1] > MIN_SATURATION_WHEN_DECIDING) {
+ return dominantSwatch.getRgb();
+ } else {
+ return coloredCandidate.getRgb();
+ }
+ } else if (hasEnoughPopulation(dominantSwatch)) {
+ return dominantSwatch.getRgb();
+ } else {
+ return fallbackColor;
+ }
+ }
+
+ private Palette.Swatch selectMutedCandidate(Palette.Swatch first,
+ Palette.Swatch second) {
+ boolean firstValid = hasEnoughPopulation(first);
+ boolean secondValid = hasEnoughPopulation(second);
+ if (firstValid && secondValid) {
+ float firstSaturation = first.getHsl()[1];
+ float secondSaturation = second.getHsl()[1];
+ float populationFraction = first.getPopulation() / (float) second.getPopulation();
+ if (firstSaturation * populationFraction > secondSaturation) {
+ return first;
+ } else {
+ return second;
+ }
+ } else if (firstValid) {
+ return first;
+ } else if (secondValid) {
+ return second;
+ }
+ return null;
+ }
+
+ private Palette.Swatch selectVibrantCandidate(Palette.Swatch first, Palette.Swatch second) {
+ boolean firstValid = hasEnoughPopulation(first);
+ boolean secondValid = hasEnoughPopulation(second);
+ if (firstValid && secondValid) {
+ int firstPopulation = first.getPopulation();
+ int secondPopulation = second.getPopulation();
+ if (firstPopulation / (float) secondPopulation
+ < POPULATION_FRACTION_FOR_MORE_VIBRANT) {
+ return second;
+ } else {
+ return first;
+ }
+ } else if (firstValid) {
+ return first;
+ } else if (secondValid) {
+ return second;
+ }
+ return null;
+ }
+
+ private boolean hasEnoughPopulation(Palette.Swatch swatch) {
+ // We want a fraction that is at least 1% of the image
+ return swatch != null
+ && (swatch.getPopulation() / (float) RESIZE_BITMAP_AREA > MINIMUM_IMAGE_FRACTION);
+ }
+
private int findBackgroundColorAndFilter(Palette palette) {
// by default we use the dominant palette
Palette.Swatch dominantSwatch = palette.getDominantSwatch();
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 fc73c0f..01bcd61 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -149,6 +149,7 @@
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
import com.android.systemui.recents.events.activity.UndockingTaskEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.stackdivider.WindowManagerProxy;
import com.android.systemui.statusbar.ActivatableNotificationView;
@@ -220,8 +221,6 @@
import android.content.pm.UserInfo;
import android.os.Build;
import android.os.Handler;
-import android.service.dreams.DreamService;
-import android.service.dreams.IDreamManager;
import android.service.notification.NotificationListenerService;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
@@ -778,8 +777,6 @@
mAccessibilityManager = (AccessibilityManager)
mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
- mDreamManager = IDreamManager.Stub.asInterface(
- ServiceManager.checkService(DreamService.DREAM_SERVICE));
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
@@ -1532,13 +1529,7 @@
}
void awakenDreams() {
- if (mDreamManager != null) {
- try {
- mDreamManager.awaken();
- } catch (RemoteException e) {
- // fine, stay asleep then
- }
- }
+ SystemServicesProxy.getInstance(mContext).awakenDreamsAsync();
}
public UserHandle getCurrentUserHandle() {
@@ -5173,7 +5164,6 @@
protected boolean mDisableNotificationAlerts = false;
protected DevicePolicyManager mDevicePolicyManager;
- protected IDreamManager mDreamManager;
protected PowerManager mPowerManager;
protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@@ -6816,12 +6806,8 @@
return false;
}
- boolean inUse = mPowerManager.isScreenOn();
- try {
- inUse = inUse && !mDreamManager.isDreaming();
- } catch (RemoteException e) {
- Log.d(TAG, "failed to query dream manager", e);
- }
+ boolean inUse = mPowerManager.isScreenOn()
+ && !SystemServicesProxy.getInstance(mContext).isDreaming();
if (!inUse && !isDozing()) {
if (DEBUG) {
diff --git a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
index 0e30fb2..de8a518 100644
--- a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
+++ b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
@@ -26,6 +26,7 @@
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
import com.android.internal.annotations.GuardedBy;
+import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@@ -96,7 +97,7 @@
mNodeFromOriginalWindow = info;
} else {
Slog.e(LOG_TAG, "Callback with unexpected interactionId");
- throw new RuntimeException("Callback with unexpected interactionId"); // Remove
+ return;
}
mSingleNodeCallbackHappened = true;
@@ -119,7 +120,7 @@
mNodesWithReplacementActions = infos;
} else {
Slog.e(LOG_TAG, "Callback with unexpected interactionId");
- throw new RuntimeException("Callback with unexpected interactionId"); // Remove
+ return;
}
callbackForSingleNode = mSingleNodeCallbackHappened;
callbackForMultipleNodes = mMultiNodeCallbackHappened;
@@ -147,7 +148,7 @@
if (DEBUG) {
Slog.e(LOG_TAG, "Extra callback");
}
- throw new RuntimeException("Extra callback"); // Replace with return before submit
+ return;
}
if (mNodeFromOriginalWindow != null) {
replaceActionsOnInfoLocked(mNodeFromOriginalWindow);
@@ -172,7 +173,7 @@
if (DEBUG) {
Slog.e(LOG_TAG, "Extra callback");
}
- throw new RuntimeException("Extra callback"); // Replace with return before submit
+ return;
}
if (mNodesFromOriginalWindow != null) {
for (int i = 0; i < mNodesFromOriginalWindow.size(); i++) {
@@ -180,7 +181,8 @@
}
}
recycleReplaceActionNodesLocked();
- nodesToReturn = mNodesFromOriginalWindow;
+ nodesToReturn = (mNodesFromOriginalWindow == null)
+ ? null : new ArrayList<>(mNodesFromOriginalWindow);
mDone = true;
}
try {
@@ -195,6 +197,12 @@
@GuardedBy("mLock")
private void replaceActionsOnInfoLocked(AccessibilityNodeInfo info) {
info.removeAllActions();
+ info.setClickable(false);
+ info.setFocusable(false);
+ info.setContextClickable(false);
+ info.setScrollable(false);
+ info.setLongClickable(false);
+ info.setDismissable(false);
// We currently only replace actions for the root node
if ((info.getSourceNodeId() == AccessibilityNodeInfo.ROOT_NODE_ID)
&& mNodesWithReplacementActions != null) {
@@ -213,6 +221,12 @@
info.addAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
info.addAction(AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
}
+ info.setClickable(nodeWithReplacementActions.isClickable());
+ info.setFocusable(nodeWithReplacementActions.isFocusable());
+ info.setContextClickable(nodeWithReplacementActions.isContextClickable());
+ info.setScrollable(nodeWithReplacementActions.isScrollable());
+ info.setLongClickable(nodeWithReplacementActions.isLongClickable());
+ info.setDismissable(nodeWithReplacementActions.isDismissable());
}
}
}
@@ -220,6 +234,7 @@
@GuardedBy("mLock")
private void recycleReplaceActionNodesLocked() {
+ if (mNodesWithReplacementActions == null) return;
for (int i = mNodesWithReplacementActions.size() - 1; i >= 0; i--) {
AccessibilityNodeInfo nodeWithReplacementAction = mNodesWithReplacementActions.get(i);
nodeWithReplacementAction.recycle();
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index 6e87f88..e380f2c 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -938,7 +938,12 @@
if (pointerIdBits == ALL_POINTER_ID_BITS) {
event = prototype;
} else {
- event = prototype.split(pointerIdBits);
+ try {
+ event = prototype.split(pointerIdBits);
+ } catch (IllegalArgumentException e) {
+ Slog.e(LOG_TAG, "sendMotionEvent: Failed to split motion event: " + e);
+ return;
+ }
}
if (action == MotionEvent.ACTION_DOWN) {
event.setDownTime(event.getEventTime());
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
index f5bae7c..fe9bfd0 100644
--- a/services/core/java/com/android/server/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -26,6 +26,7 @@
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;
import android.os.UserManager;
+import android.os.storage.StorageManager;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
@@ -336,8 +337,11 @@
synchronized (mFileWriteLock) {
RandomAccessFile raf = null;
try {
- // Write the hash to file
- raf = new RandomAccessFile(name, "rw");
+ // Write the hash to file, requiring each write to be synchronized to the
+ // underlying storage device immediately to avoid data loss in case of power loss.
+ // This also ensures future secdiscard operation on the file succeeds since the
+ // file would have been allocated on flash.
+ raf = new RandomAccessFile(name, "rws");
// Truncate the file if pattern is null, to clear the lock
if (hash == null || hash.length == 0) {
raf.setLength(0);
@@ -432,12 +436,17 @@
return readFile(getSynthenticPasswordStateFilePathForUser(userId, handle, name));
}
- public void deleteSyntheticPasswordState(int userId, long handle, String name, boolean secure) {
+ public void deleteSyntheticPasswordState(int userId, long handle, String name) {
String path = getSynthenticPasswordStateFilePathForUser(userId, handle, name);
File file = new File(path);
if (file.exists()) {
- //TODO: (b/34600579) invoke secdiscardable
- file.delete();
+ try {
+ mContext.getSystemService(StorageManager.class).secdiscard(file.getAbsolutePath());
+ } catch (Exception e) {
+ Slog.w(TAG, "Failed to secdiscard " + path, e);
+ } finally {
+ file.delete();
+ }
mCache.putFile(path, null);
}
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 452fe1d..cffb158 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3009,6 +3009,18 @@
}
}
+ @Override
+ public void secdiscard(String path) {
+ enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
+ waitForReady();
+
+ try {
+ mCryptConnector.execute("cryptfs", "secdiscard", escapeNull(path));
+ } catch (NativeDaemonConnectorException e) {
+ throw e.rethrowAsParcelableException();
+ }
+ }
+
class AppFuseMountScope extends AppFuseBridge.MountScope {
boolean opened = false;
diff --git a/services/core/java/com/android/server/SyntheticPasswordManager.java b/services/core/java/com/android/server/SyntheticPasswordManager.java
index f797517..1d17ff7 100644
--- a/services/core/java/com/android/server/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/SyntheticPasswordManager.java
@@ -283,7 +283,7 @@
// Nuke the SP handle (and as a result, its SID) for the given user.
public void clearSidForUser(int userId) {
- destroyState(SP_HANDLE_NAME, true, DEFAULT_HANDLE, userId);
+ destroyState(SP_HANDLE_NAME, DEFAULT_HANDLE, userId);
}
public boolean hasSidForUser(int userId) {
@@ -318,8 +318,8 @@
}
public void destroyEscrowData(int userId) {
- destroyState(SP_E0_NAME, true, DEFAULT_HANDLE, userId);
- destroyState(SP_P1_NAME, true, DEFAULT_HANDLE, userId);
+ destroyState(SP_E0_NAME, DEFAULT_HANDLE, userId);
+ destroyState(SP_P1_NAME, DEFAULT_HANDLE, userId);
}
/**
@@ -584,17 +584,17 @@
public void destroyTokenBasedSyntheticPassword(long handle, int userId) {
destroySyntheticPassword(handle, userId);
- destroyState(SECDISCARDABLE_NAME, true, handle, userId);
+ destroyState(SECDISCARDABLE_NAME, handle, userId);
}
public void destroyPasswordBasedSyntheticPassword(long handle, int userId) {
destroySyntheticPassword(handle, userId);
- destroyState(SECDISCARDABLE_NAME, true, handle, userId);
- destroyState(PASSWORD_DATA_NAME, true, handle, userId);
+ destroyState(SECDISCARDABLE_NAME, handle, userId);
+ destroyState(PASSWORD_DATA_NAME, handle, userId);
}
private void destroySyntheticPassword(long handle, int userId) {
- destroyState(SP_BLOB_NAME, true, handle, userId);
+ destroyState(SP_BLOB_NAME, handle, userId);
destroySPBlobKey(getHandleName(handle));
}
@@ -629,8 +629,8 @@
mStorage.writeSyntheticPasswordState(userId, handle, stateName, data);
}
- private void destroyState(String stateName, boolean secure, long handle, int userId) {
- mStorage.deleteSyntheticPasswordState(userId, handle, stateName, secure);
+ private void destroyState(String stateName, long handle, int userId) {
+ mStorage.deleteSyntheticPasswordState(userId, handle, stateName);
}
protected byte[] decryptSPBlob(String blobKeyName, byte[] blob, byte[] applicationId) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 2bd55e2..36c3f7d 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -5922,6 +5922,13 @@
return;
}
+ int visibility =
+ resolveAccountVisibility(account, packageName, getUserAccounts(userId));
+ if (visibility == AccountManager.VISIBILITY_NOT_VISIBLE) {
+ Slog.w(TAG, "requestAccountAccess: account is hidden");
+ return;
+ }
+
if (AccountManagerService.this.hasAccountAccess(account, packageName,
new UserHandle(userId))) {
Bundle result = new Bundle();
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index df32089..54b28d1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7914,12 +7914,6 @@
final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
// Adjust the source bounds by the insets for the transition down
final Rect sourceBounds = new Rect(r.pictureInPictureArgs.getSourceRectHint());
- final Rect insets = r.pictureInPictureArgs.getSourceRectHintInsets();
- if (insets != null) {
- sourceBounds.offsetTo(Math.max(0, sourceBounds.left - insets.left),
- Math.max(0, sourceBounds.top - insets.top));
- }
-
mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, aspectRatio,
true /* moveHomeStackToFront */, "enterPictureInPictureMode");
final PinnedActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 4e00f2d..55ec3b0 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -149,6 +149,7 @@
import android.util.Slog;
import android.util.TimeUtils;
import android.view.AppTransitionAnimationSpec;
+import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.IApplicationToken;
import android.view.WindowManager.LayoutParams;
@@ -1437,7 +1438,13 @@
case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
- if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
+ final IAppTransitionAnimationSpecsFuture specsFuture =
+ pendingOptions.getSpecsFuture();
+ if (specsFuture != null) {
+ service.mWindowManager.overridePendingAppTransitionMultiThumbFuture(
+ specsFuture, pendingOptions.getOnAnimationStartListener(),
+ animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP);
+ } else if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
&& specs != null) {
service.mWindowManager.overridePendingAppTransitionMultiThumb(
specs, pendingOptions.getOnAnimationStartListener(),
@@ -2165,7 +2172,8 @@
final boolean shown = mWindowContainerController.addStartingWindow(packageName, theme,
compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
- allowTaskSnapshot());
+ allowTaskSnapshot(),
+ state.ordinal() >= RESUMED.ordinal() && state.ordinal() <= STOPPED.ordinal());
if (shown) {
mStartingWindowState = STARTING_WINDOW_SHOWN;
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 8210c07..79ea7ba 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2998,7 +2998,8 @@
stack.animateResizePinnedStack(sourceHintBounds, destBounds, -1 /* animationDuration */,
true /* schedulePipModeChangedOnAnimationEnd */);
- mService.mTaskChangeNotificationController.notifyActivityPinned(r.packageName);
+ mService.mTaskChangeNotificationController.notifyActivityPinned(r.packageName,
+ r.getTask().taskId);
}
/** Move activity with its stack to front and make the stack focused. */
diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
index f5d7b68..ea9ff59 100644
--- a/services/core/java/com/android/server/am/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
@@ -96,7 +96,7 @@
};
private final TaskStackConsumer mNotifyActivityPinned = (l, m) -> {
- l.onActivityPinned((String) m.obj);
+ l.onActivityPinned((String) m.obj, m.arg1);
};
private final TaskStackConsumer mNotifyActivityUnpinned = (l, m) -> {
@@ -279,10 +279,10 @@
}
/** Notifies all listeners when an Activity is pinned. */
- void notifyActivityPinned(String packageName) {
+ void notifyActivityPinned(String packageName, int taskId) {
mHandler.removeMessages(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG);
final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG,
- packageName);
+ taskId, 0, packageName);
forAllLocalListeners(mNotifyActivityPinned, msg);
msg.sendToTarget();
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
index d38beb3..44c61f0 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -16,6 +16,7 @@
package com.android.server.connectivity.tethering;
+import static android.content.Context.TELEPHONY_SERVICE;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
@@ -47,9 +48,9 @@
public class TetheringConfiguration {
private static final String TAG = TetheringConfiguration.class.getSimpleName();
- private static final int DUN_NOT_REQUIRED = 0;
- private static final int DUN_REQUIRED = 1;
- private static final int DUN_UNSPECIFIED = 2;
+ public static final int DUN_NOT_REQUIRED = 0;
+ public static final int DUN_REQUIRED = 1;
+ public static final int DUN_UNSPECIFIED = 2;
// USB is 192.168.42.1 and 255.255.255.0
// Wifi is 192.168.43.1 and 255.255.255.0
@@ -81,8 +82,9 @@
tetherableBluetoothRegexs = ctx.getResources().getStringArray(
com.android.internal.R.array.config_tether_bluetooth_regexs);
- isDunRequired = checkDunRequired(ctx);
- preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(ctx, isDunRequired);
+ final int dunCheck = checkDunRequired(ctx);
+ preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(ctx, dunCheck);
+ isDunRequired = preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN);
dhcpRanges = getDhcpRanges(ctx);
defaultIPv4DNS = copy(DEFAULT_IPV4_DNS);
@@ -138,14 +140,12 @@
pw.println();
}
- private static boolean checkDunRequired(Context ctx) {
- final TelephonyManager tm = ctx.getSystemService(TelephonyManager.class);
- final int secureSetting =
- (tm != null) ? tm.getTetherApnRequired() : DUN_UNSPECIFIED;
- return (secureSetting == DUN_REQUIRED);
+ private static int checkDunRequired(Context ctx) {
+ final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE);
+ return (tm != null) ? tm.getTetherApnRequired() : DUN_UNSPECIFIED;
}
- private static Collection<Integer> getUpstreamIfaceTypes(Context ctx, boolean requiresDun) {
+ private static Collection<Integer> getUpstreamIfaceTypes(Context ctx, int dunCheck) {
final int ifaceTypes[] = ctx.getResources().getIntArray(
com.android.internal.R.array.config_tether_upstream_types);
final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length);
@@ -153,10 +153,10 @@
switch (i) {
case TYPE_MOBILE:
case TYPE_MOBILE_HIPRI:
- if (requiresDun) continue;
+ if (dunCheck == DUN_REQUIRED) continue;
break;
case TYPE_MOBILE_DUN:
- if (!requiresDun) continue;
+ if (dunCheck == DUN_NOT_REQUIRED) continue;
break;
}
upstreamIfaceTypes.add(i);
@@ -166,7 +166,7 @@
// of the value of |requiresDun|, cell data of one form or another is
// *always* an upstream, regardless of the upstream interface types
// specified by configuration resources.
- if (requiresDun) {
+ if (dunCheck == DUN_REQUIRED) {
if (!upstreamIfaceTypes.contains(TYPE_MOBILE_DUN)) {
upstreamIfaceTypes.add(TYPE_MOBILE_DUN);
}
diff --git a/services/core/java/com/android/server/fingerprint/RemovalClient.java b/services/core/java/com/android/server/fingerprint/RemovalClient.java
index 88a6bdd..8646107 100644
--- a/services/core/java/com/android/server/fingerprint/RemovalClient.java
+++ b/services/core/java/com/android/server/fingerprint/RemovalClient.java
@@ -85,7 +85,6 @@
IFingerprintServiceReceiver receiver = getReceiver();
try {
if (receiver != null) {
- // TODO: plumb remaining
receiver.onRemoved(getHalDeviceId(), fingerId, groupId, remaining);
}
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index c08f866..b0d76e8 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -63,6 +63,7 @@
import android.os.ShellCallback;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.os.UserManagerInternal;
import android.provider.Settings;
import android.util.KeyValueListParser;
import android.util.Slog;
@@ -751,6 +752,13 @@
}
}
+ private void cancelJobsForNonExistentUsers() {
+ UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
+ synchronized (mLock) {
+ mJobs.removeJobsOfNonUsers(umi.getUserIds());
+ }
+ }
+
void cancelJobsForPackageAndUid(String pkgName, int uid) {
synchronized (mLock) {
final List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
@@ -941,6 +949,8 @@
} catch (RemoteException e) {
// ignored; both services live in system_server
}
+ // Remove any jobs that are not associated with any of the current users.
+ cancelJobsForNonExistentUsers();
} else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
synchronized (mLock) {
// Let's go!
@@ -1270,6 +1280,17 @@
}
}
+ private void stopNonReadyActiveJobsLocked() {
+ for (int i=0; i<mActiveServices.size(); i++) {
+ JobServiceContext serviceContext = mActiveServices.get(i);
+ final JobStatus running = serviceContext.getRunningJobLocked();
+ if (running != null && !running.isReady()) {
+ serviceContext.cancelExecutingJobLocked(
+ JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED);
+ }
+ }
+ }
+
/**
* Run through list of jobs and execute all possible - at least one is expired so we do
* as many as we can.
@@ -1280,6 +1301,7 @@
}
noteJobsNonpending(mPendingJobs);
mPendingJobs.clear();
+ stopNonReadyActiveJobsLocked();
mJobs.forEachJob(mReadyQueueFunctor);
mReadyQueueFunctor.postProcess();
@@ -1306,9 +1328,6 @@
newReadyJobs = new ArrayList<JobStatus>();
}
newReadyJobs.add(job);
- } else if (areJobConstraintsNotSatisfiedLocked(job)) {
- stopJobOnServiceContextLocked(job,
- JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED);
}
}
@@ -1387,9 +1406,6 @@
runnableJobs = new ArrayList<>();
}
runnableJobs.add(job);
- } else if (areJobConstraintsNotSatisfiedLocked(job)) {
- stopJobOnServiceContextLocked(job,
- JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED);
}
}
@@ -1439,6 +1455,7 @@
noteJobsNonpending(mPendingJobs);
mPendingJobs.clear();
+ stopNonReadyActiveJobsLocked();
mJobs.forEachJob(mMaybeQueueFunctor);
mMaybeQueueFunctor.postProcess();
}
@@ -1516,15 +1533,6 @@
}
/**
- * Criteria for cancelling an active job:
- * - It's not ready
- * - It's running on a JSC.
- */
- private boolean areJobConstraintsNotSatisfiedLocked(JobStatus job) {
- return !job.isReady() && isCurrentlyActiveLocked(job);
- }
-
- /**
* Reconcile jobs in the pending queue against available execution contexts.
* A controller can force a job into the pending queue even if it's already running, but
* here is where we decide whether to actually execute it.
@@ -2088,6 +2096,83 @@
}
}
+ int getJobState(PrintWriter pw, String pkgName, int userId, int jobId) {
+ try {
+ final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0,
+ userId != UserHandle.USER_ALL ? userId : UserHandle.USER_SYSTEM);
+ if (uid < 0) {
+ pw.print("unknown("); pw.print(pkgName); pw.println(")");
+ return JobSchedulerShellCommand.CMD_ERR_NO_PACKAGE;
+ }
+
+ synchronized (mLock) {
+ final JobStatus js = mJobs.getJobByUidAndJobId(uid, jobId);
+ if (DEBUG) Slog.d(TAG, "get-job-state " + uid + "/" + jobId + ": " + js);
+ if (js == null) {
+ pw.print("unknown("); UserHandle.formatUid(pw, uid);
+ pw.print("/jid"); pw.print(jobId); pw.println(")");
+ return JobSchedulerShellCommand.CMD_ERR_NO_JOB;
+ }
+
+ boolean printed = false;
+ if (mPendingJobs.contains(js)) {
+ pw.print("pending");
+ printed = true;
+ }
+ if (isCurrentlyActiveLocked(js)) {
+ if (printed) {
+ pw.print(" ");
+ }
+ printed = true;
+ pw.println("active");
+ }
+ if (!ArrayUtils.contains(mStartedUsers, js.getUserId())) {
+ if (printed) {
+ pw.print(" ");
+ }
+ printed = true;
+ pw.println("user-stopped");
+ }
+ if (mBackingUpUids.indexOfKey(js.getSourceUid()) >= 0) {
+ if (printed) {
+ pw.print(" ");
+ }
+ printed = true;
+ pw.println("backing-up");
+ }
+ boolean componentPresent = false;
+ try {
+ componentPresent = (AppGlobals.getPackageManager().getServiceInfo(
+ js.getServiceComponent(),
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+ js.getUserId()) != null);
+ } catch (RemoteException e) {
+ }
+ if (!componentPresent) {
+ if (printed) {
+ pw.print(" ");
+ }
+ printed = true;
+ pw.println("no-component");
+ }
+ if (js.isReady()) {
+ if (printed) {
+ pw.print(" ");
+ }
+ printed = true;
+ pw.println("ready");
+ }
+ if (!printed) {
+ pw.print("waiting");
+ }
+ pw.println();
+ }
+ } catch (RemoteException e) {
+ // can't happen
+ }
+ return 0;
+ }
+
private String printContextIdToJobMap(JobStatus[] map, String initial) {
StringBuilder s = new StringBuilder(initial + ": ");
for (int i=0; i<map.length; i++) {
@@ -2152,7 +2237,8 @@
}
final int filterUidFinal = UserHandle.getAppId(filterUid);
- final long now = SystemClock.elapsedRealtime();
+ final long nowElapsed = SystemClock.elapsedRealtime();
+ final long nowUptime = SystemClock.uptimeMillis();
synchronized (mLock) {
mConstants.dump(pw);
pw.println();
@@ -2184,7 +2270,7 @@
continue;
}
- job.dump(pw, " ", true, now);
+ job.dump(pw, " ", true, nowElapsed);
pw.print(" Ready: ");
pw.print(isReadyToBeExecutedLocked(job));
pw.print(" (job=");
@@ -2254,14 +2340,14 @@
JobStatus job = mPendingJobs.get(i);
pw.print(" Pending #"); pw.print(i); pw.print(": ");
pw.println(job.toShortString());
- job.dump(pw, " ", false, now);
+ job.dump(pw, " ", false, nowElapsed);
int priority = evaluateJobPriorityLocked(job);
if (priority != JobInfo.PRIORITY_DEFAULT) {
pw.print(" Evaluated priority: "); pw.println(priority);
}
pw.print(" Tag: "); pw.println(job.getTag());
pw.print(" Enq: ");
- TimeUtils.formatDuration(job.madePending - now, pw);
+ TimeUtils.formatDuration(job.madePending - nowUptime, pw);
pw.println();
}
pw.println();
@@ -2276,17 +2362,17 @@
} else {
pw.println(job.toShortString());
pw.print(" Running for: ");
- TimeUtils.formatDuration(now - jsc.getExecutionStartTimeElapsed(), pw);
+ TimeUtils.formatDuration(nowElapsed - jsc.getExecutionStartTimeElapsed(), pw);
pw.print(", timeout at: ");
- TimeUtils.formatDuration(jsc.getTimeoutElapsed() - now, pw);
+ TimeUtils.formatDuration(jsc.getTimeoutElapsed() - nowElapsed, pw);
pw.println();
- job.dump(pw, " ", false, now);
+ job.dump(pw, " ", false, nowElapsed);
int priority = evaluateJobPriorityLocked(jsc.getRunningJobLocked());
if (priority != JobInfo.PRIORITY_DEFAULT) {
pw.print(" Evaluated priority: "); pw.println(priority);
}
pw.print(" Active at ");
- TimeUtils.formatDuration(job.madeActive - now, pw);
+ TimeUtils.formatDuration(job.madeActive - nowUptime, pw);
pw.print(", pending for ");
TimeUtils.formatDuration(job.madeActive - job.madePending, pw);
pw.println();
diff --git a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
index fdfb345..2d2f61f 100644
--- a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -60,6 +60,8 @@
return getStorageSeq(pw);
case "get-storage-not-low":
return getStorageNotLow(pw);
+ case "get-job-state":
+ return getJobState(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -83,6 +85,43 @@
}
}
+ private boolean printError(int errCode, String pkgName, int userId, int jobId) {
+ PrintWriter pw;
+ switch (errCode) {
+ case CMD_ERR_NO_PACKAGE:
+ pw = getErrPrintWriter();
+ pw.print("Package not found: ");
+ pw.print(pkgName);
+ pw.print(" / user ");
+ pw.println(userId);
+ return true;
+
+ case CMD_ERR_NO_JOB:
+ pw = getErrPrintWriter();
+ pw.print("Could not find job ");
+ pw.print(jobId);
+ pw.print(" in package ");
+ pw.print(pkgName);
+ pw.print(" / user ");
+ pw.println(userId);
+ return true;
+
+ case CMD_ERR_CONSTRAINTS:
+ pw = getErrPrintWriter();
+ pw.print("Job ");
+ pw.print(jobId);
+ pw.print(" in package ");
+ pw.print(pkgName);
+ pw.print(" / user ");
+ pw.print(userId);
+ pw.println(" has functional constraints but --force not specified");
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
private int runJob(PrintWriter pw) throws Exception {
checkPermission("force scheduled jobs");
@@ -114,42 +153,17 @@
final long ident = Binder.clearCallingIdentity();
try {
int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force);
- switch (ret) {
- case CMD_ERR_NO_PACKAGE:
- pw.print("Package not found: ");
- pw.print(pkgName);
- pw.print(" / user ");
- pw.println(userId);
- break;
-
- case CMD_ERR_NO_JOB:
- pw.print("Could not find job ");
- pw.print(jobId);
- pw.print(" in package ");
- pw.print(pkgName);
- pw.print(" / user ");
- pw.println(userId);
- break;
-
- case CMD_ERR_CONSTRAINTS:
- pw.print("Job ");
- pw.print(jobId);
- pw.print(" in package ");
- pw.print(pkgName);
- pw.print(" / user ");
- pw.print(userId);
- pw.println(" has functional constraints but --force not specified");
- break;
-
- default:
- // success!
- pw.print("Running job");
- if (force) {
- pw.print(" [FORCED]");
- }
- pw.println();
- break;
+ if (printError(ret, pkgName, userId, jobId)) {
+ return ret;
}
+
+ // success!
+ pw.print("Running job");
+ if (force) {
+ pw.print(" [FORCED]");
+ }
+ pw.println();
+
return ret;
} finally {
Binder.restoreCallingIdentity(ident);
@@ -244,6 +258,43 @@
return 0;
}
+ private int getJobState(PrintWriter pw) throws Exception {
+ checkPermission("force timeout jobs");
+
+ int userId = UserHandle.USER_SYSTEM;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "-u":
+ case "--user":
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ break;
+
+ default:
+ pw.println("Error: unknown option '" + opt + "'");
+ return -1;
+ }
+ }
+
+ if (userId == UserHandle.USER_CURRENT) {
+ userId = ActivityManager.getCurrentUser();
+ }
+
+ final String pkgName = getNextArgRequired();
+ final String jobIdStr = getNextArgRequired();
+ final int jobId = Integer.parseInt(jobIdStr);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ int ret = mInternal.getJobState(pw, pkgName, userId, jobId);
+ printError(ret, pkgName, userId, jobId);
+ return ret;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
@Override
public void onHelp() {
final PrintWriter pw = getOutPrintWriter();
@@ -277,6 +328,18 @@
pw.println(" Return the last storage update sequence number that was received.");
pw.println(" get-storage-not-low");
pw.println(" Return whether storage is currently considered to not be low.");
+ pw.println(" get-job-state [-u | --user USER_ID] PACKAGE JOB_ID");
+ pw.println(" Return the current state of a job, may be any combination of:");
+ pw.println(" pending: currently on the pending list, waiting to be active");
+ pw.println(" active: job is actively running");
+ pw.println(" user-stopped: job can't run because its user is stopped");
+ pw.println(" backing-up: job can't run because app is currently backing up its data");
+ pw.println(" no-component: job can't run because its component is not available");
+ pw.println(" ready: job is ready to run (all constraints satisfied or bypassed)");
+ pw.println(" waiting: if nothing else above is printed, job not ready to run");
+ pw.println(" Options:");
+ pw.println(" -u or --user: specify which user's job is to be run; the default is");
+ pw.println(" the primary or system user");
pw.println();
}
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 497d36f..22eed3b 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -35,6 +35,7 @@
import android.util.Xml;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.server.IoThread;
import com.android.server.job.controllers.JobStatus;
@@ -171,6 +172,14 @@
return removed;
}
+ /**
+ * Remove the jobs of users not specified in the whitelist.
+ * @param whitelist Array of User IDs whose jobs are not to be removed.
+ */
+ public void removeJobsOfNonUsers(int[] whitelist) {
+ mJobSet.removeJobsOfNonUsers(whitelist);
+ }
+
@VisibleForTesting
public void clear() {
mJobSet.clear();
@@ -839,6 +848,17 @@
return didRemove;
}
+ // Remove the jobs all users not specified by the whitelist of user ids
+ public void removeJobsOfNonUsers(int[] whitelist) {
+ for (int jobIndex = mJobs.size() - 1; jobIndex >= 0; jobIndex--) {
+ int jobUserId = UserHandle.getUserId(mJobs.keyAt(jobIndex));
+ // check if job's user id is not in the whitelist
+ if (!ArrayUtils.contains(whitelist, jobUserId)) {
+ mJobs.removeAt(jobIndex);
+ }
+ }
+ }
+
public boolean contains(JobStatus job) {
final int uid = job.getUid();
ArraySet<JobStatus> jobs = mJobs.get(uid);
diff --git a/services/core/java/com/android/server/job/controllers/BatteryController.java b/services/core/java/com/android/server/job/controllers/BatteryController.java
index b1f8f6b..d275bd9 100644
--- a/services/core/java/com/android/server/job/controllers/BatteryController.java
+++ b/services/core/java/com/android/server/job/controllers/BatteryController.java
@@ -93,34 +93,31 @@
}
}
- private void maybeReportNewChargingState() {
+ private void maybeReportNewChargingStateLocked() {
final boolean stablePower = mChargeTracker.isOnStablePower();
final boolean batteryNotLow = mChargeTracker.isBatteryNotLow();
if (DEBUG) {
- Slog.d(TAG, "maybeReportNewChargingState: " + stablePower);
+ Slog.d(TAG, "maybeReportNewChargingStateLocked: " + stablePower);
}
boolean reportChange = false;
- synchronized (mLock) {
- for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
- final JobStatus ts = mTrackedTasks.valueAt(i);
- boolean previous = ts.setChargingConstraintSatisfied(stablePower);
- if (previous != stablePower) {
- reportChange = true;
- }
- previous = ts.setBatteryNotLowConstraintSatisfied(batteryNotLow);
- if (previous != batteryNotLow) {
- reportChange = true;
- }
+ for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
+ final JobStatus ts = mTrackedTasks.valueAt(i);
+ boolean previous = ts.setChargingConstraintSatisfied(stablePower);
+ if (previous != stablePower) {
+ reportChange = true;
+ }
+ previous = ts.setBatteryNotLowConstraintSatisfied(batteryNotLow);
+ if (previous != batteryNotLow) {
+ reportChange = true;
}
}
- // Let the scheduler know that state has changed. This may or may not result in an
- // execution.
- if (reportChange) {
- mStateChangedListener.onControllerStateChanged();
- }
- // Also tell the scheduler that any ready jobs should be flushed.
if (stablePower || batteryNotLow) {
+ // If one of our conditions has been satisfied, always schedule any newly ready jobs.
mStateChangedListener.onRunJobNow(null);
+ } else if (reportChange) {
+ // Otherwise, just let the job scheduler know the state has changed and take care of it
+ // as it thinks is best.
+ mStateChangedListener.onControllerStateChanged();
}
}
@@ -201,38 +198,42 @@
@VisibleForTesting
public void onReceiveInternal(Intent intent) {
- final String action = intent.getAction();
- if (Intent.ACTION_BATTERY_LOW.equals(action)) {
- if (DEBUG) {
- Slog.d(TAG, "Battery life too low to do work. @ "
- + SystemClock.elapsedRealtime());
+ synchronized (mLock) {
+ final String action = intent.getAction();
+ if (Intent.ACTION_BATTERY_LOW.equals(action)) {
+ if (DEBUG) {
+ Slog.d(TAG, "Battery life too low to do work. @ "
+ + SystemClock.elapsedRealtime());
+ }
+ // If we get this action, the battery is discharging => it isn't plugged in so
+ // there's no work to cancel. We track this variable for the case where it is
+ // charging, but hasn't been for long enough to be healthy.
+ mBatteryHealthy = false;
+ maybeReportNewChargingStateLocked();
+ } else if (Intent.ACTION_BATTERY_OKAY.equals(action)) {
+ if (DEBUG) {
+ Slog.d(TAG, "Battery life healthy enough to do work. @ "
+ + SystemClock.elapsedRealtime());
+ }
+ mBatteryHealthy = true;
+ maybeReportNewChargingStateLocked();
+ } else if (BatteryManager.ACTION_CHARGING.equals(action)) {
+ if (DEBUG) {
+ Slog.d(TAG, "Received charging intent, fired @ "
+ + SystemClock.elapsedRealtime());
+ }
+ mCharging = true;
+ maybeReportNewChargingStateLocked();
+ } else if (BatteryManager.ACTION_DISCHARGING.equals(action)) {
+ if (DEBUG) {
+ Slog.d(TAG, "Disconnected from power.");
+ }
+ mCharging = false;
+ maybeReportNewChargingStateLocked();
}
- // If we get this action, the battery is discharging => it isn't plugged in so
- // there's no work to cancel. We track this variable for the case where it is
- // charging, but hasn't been for long enough to be healthy.
- mBatteryHealthy = false;
- } else if (Intent.ACTION_BATTERY_OKAY.equals(action)) {
- if (DEBUG) {
- Slog.d(TAG, "Battery life healthy enough to do work. @ "
- + SystemClock.elapsedRealtime());
- }
- mBatteryHealthy = true;
- maybeReportNewChargingState();
- } else if (BatteryManager.ACTION_CHARGING.equals(action)) {
- if (DEBUG) {
- Slog.d(TAG, "Received charging intent, fired @ "
- + SystemClock.elapsedRealtime());
- }
- mCharging = true;
- maybeReportNewChargingState();
- } else if (BatteryManager.ACTION_DISCHARGING.equals(action)) {
- if (DEBUG) {
- Slog.d(TAG, "Disconnected from power.");
- }
- mCharging = false;
- maybeReportNewChargingState();
+ mLastBatterySeq = intent.getIntExtra(BatteryManager.EXTRA_SEQUENCE,
+ mLastBatterySeq);
}
- mLastBatterySeq = intent.getIntExtra(BatteryManager.EXTRA_SEQUENCE, mLastBatterySeq);
}
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index e83d453..e184f83 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -1158,6 +1158,9 @@
public boolean badgingEnabled(UserHandle userHandle) {
int userId = userHandle.getIdentifier();
+ if (userId == UserHandle.USER_ALL) {
+ return false;
+ }
if (mBadgingEnabled.indexOfKey(userId) < 0) {
mBadgingEnabled.put(userId,
Secure.getIntForUser(mContext.getContentResolver(),
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 400ee0c..cdf5047 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2026,15 +2026,17 @@
EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,
getUnknownSourcesSettings());
- // Force a gc to clear up things
- Runtime.getRuntime().gc();
-
// Remove the replaced package's older resources safely now
// We delete after a gc for applications on sdcard.
if (res.removedInfo != null && res.removedInfo.args != null) {
+ Runtime.getRuntime().gc();
synchronized (mInstallLock) {
res.removedInfo.args.doPostDeleteLI(true);
}
+ } else {
+ // Force a gc to clear up things. Ask for a background one, it's fine to go on
+ // and not block here.
+ VMRuntime.getRuntime().requestConcurrentGC();
}
// Notify DexManager that the package was installed for new users.
@@ -3480,6 +3482,31 @@
return cur;
}
+ /**
+ * Returns whether or not a full application can see an instant application.
+ * <p>
+ * Currently, there are three cases in which this can occur:
+ * <ol>
+ * <li>The calling application is a "special" process. The special
+ * processes are {@link Process#SYSTEM_UID}, {@link Process#SHELL_UID}
+ * and {@code 0}</li>
+ * <li>The calling application has the permission
+ * {@link android.Manifest.permission#ACCESS_INSTANT_APPS}</li>
+ * <li>[TODO] The calling application is the default launcher on the
+ * system partition.</li>
+ * </ol>
+ */
+ private boolean canAccessInstantApps(int callingUid) {
+ final boolean isSpecialProcess =
+ callingUid == Process.SYSTEM_UID
+ || callingUid == Process.SHELL_UID
+ || callingUid == 0;
+ final boolean allowMatchInstant =
+ isSpecialProcess
+ || mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_INSTANT_APPS) == PERMISSION_GRANTED;
+ return allowMatchInstant;
+ }
private PackageInfo generatePackageInfo(PackageSetting ps, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
if (ps == null) {
@@ -3489,19 +3516,15 @@
if (p == null) {
return null;
}
+ final int callingUid = Binder.getCallingUid();
// Filter out ephemeral app metadata:
// * The system/shell/root can see metadata for any app
// * An installed app can see metadata for 1) other installed apps
// and 2) ephemeral apps that have explicitly interacted with it
// * Ephemeral apps can only see their own data and exposed installed apps
// * Holding a signature permission allows seeing instant apps
- final int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
- if (callingAppId != Process.SYSTEM_UID
- && callingAppId != Process.SHELL_UID
- && callingAppId != Process.ROOT_UID
- && checkUidPermission(Manifest.permission.ACCESS_INSTANT_APPS,
- Binder.getCallingUid()) != PackageManager.PERMISSION_GRANTED) {
- final String instantAppPackageName = getInstantAppPackageName(Binder.getCallingUid());
+ if (!canAccessInstantApps(callingUid)) {
+ final String instantAppPackageName = getInstantAppPackageName(callingUid);
if (instantAppPackageName != null) {
// ephemeral apps can only get information on themselves or
// installed apps that are exposed.
@@ -3512,6 +3535,7 @@
} else {
if (ps.getInstantApp(userId)) {
// only get access to the ephemeral app if we've been granted access
+ final int callingAppId = UserHandle.getAppId(callingUid);
if (!mInstantAppRegistry.isInstantAccessGranted(
userId, callingAppId, ps.appId)) {
return null;
@@ -3610,8 +3634,7 @@
public PackageInfo getPackageInfoVersioned(VersionedPackage versionedPackage,
int flags, int userId) {
return getPackageInfoInternal(versionedPackage.getPackageName(),
- // TODO: We will change version code to long, so in the new API it is long
- (int) versionedPackage.getVersionCode(), flags, userId);
+ versionedPackage.getVersionCode(), flags, userId);
}
private PackageInfo getPackageInfoInternal(String packageName, int versionCode,
@@ -4334,7 +4357,8 @@
}
@Override
- public ParceledListSlice<SharedLibraryInfo> getSharedLibraries(int flags, int userId) {
+ public ParceledListSlice<SharedLibraryInfo> getSharedLibraries(String packageName,
+ int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
Preconditions.checkArgumentNonnegative(userId, "userId must be >= 0");
@@ -4345,8 +4369,9 @@
== PERMISSION_GRANTED
|| mContext.checkCallingOrSelfPermission(DELETE_PACKAGES)
== PERMISSION_GRANTED
- || mContext.checkCallingOrSelfPermission(REQUEST_INSTALL_PACKAGES)
- == PERMISSION_GRANTED
+ || canRequestPackageInstallsInternal(packageName,
+ PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId,
+ false /* throwIfPermNotDeclared*/)
|| mContext.checkCallingOrSelfPermission(REQUEST_DELETE_PACKAGES)
== PERMISSION_GRANTED;
@@ -4369,7 +4394,8 @@
final long identity = Binder.clearCallingIdentity();
try {
PackageInfo packageInfo = getPackageInfoVersioned(
- libInfo.getDeclaringPackage(), flags, userId);
+ libInfo.getDeclaringPackage(), flags
+ | PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId);
if (packageInfo == null) {
continue;
}
@@ -6489,18 +6515,22 @@
}
} else {
final PackageParser.Package pkg = mPackages.get(pkgName);
+ result = null;
if (pkg != null) {
- return applyPostResolutionFilter(filterIfNotSystemUser(
+ result = filterIfNotSystemUser(
mActivities.queryIntentForPackage(
intent, resolvedType, flags, pkg.activities, userId),
- userId), instantAppPkgName);
- } else {
+ userId);
+ }
+ if (result == null || result.size() == 0) {
// the caller wants to resolve for a particular package; however, there
// were no installed results, so, try to find an ephemeral result
addEphemeral = !ephemeralDisabled
&& isInstantAppAllowed(
intent, null /*result*/, userId, true /*skipPackageCheck*/);
- result = new ArrayList<ResolveInfo>();
+ if (result == null) {
+ result = new ArrayList<>();
+ }
}
}
}
@@ -9268,6 +9298,9 @@
}
if (p != null) {
usesLibraryFiles.addAll(p.getAllCodePaths());
+ if (p.usesLibraryFiles != null) {
+ Collections.addAll(usesLibraryFiles, p.usesLibraryFiles);
+ }
}
}
@@ -17714,14 +17747,12 @@
Integer.MAX_VALUE, "versionCode must be >= -1");
final String packageName = versionedPackage.getPackageName();
- // TODO: We will change version code to long, so in the new API it is long
- final int versionCode = (int) versionedPackage.getVersionCode();
+ final int versionCode = versionedPackage.getVersionCode();
final String internalPackageName;
synchronized (mPackages) {
// Normalize package name to handle renamed packages and static libs
internalPackageName = resolveInternalPackageNameLPr(versionedPackage.getPackageName(),
- // TODO: We will change version code to long, so in the new API it is long
- (int) versionedPackage.getVersionCode());
+ versionedPackage.getVersionCode());
}
final int uid = Binder.getCallingUid();
@@ -17863,8 +17894,7 @@
libEntry.info.getVersion()) < 0) {
continue;
}
- // TODO: We will change version code to long, so in the new API it is long
- final int libVersionCode = (int) libEntry.info.getDeclaringPackage().getVersionCode();
+ final int libVersionCode = libEntry.info.getDeclaringPackage().getVersionCode();
if (versionCode != PackageManager.VERSION_CODE_HIGHEST) {
if (libVersionCode == versionCode) {
return libEntry.apk;
@@ -23838,6 +23868,11 @@
return getUidTargetSdkVersionLockedLPr(uid);
}
}
+
+ @Override
+ public boolean canAccessInstantApps(int callingUid) {
+ return PackageManagerService.this.canAccessInstantApps(callingUid);
+ }
}
@Override
@@ -23944,6 +23979,12 @@
@Override
public boolean canRequestPackageInstalls(String packageName, int userId) {
+ return canRequestPackageInstallsInternal(packageName, 0, userId,
+ true /* throwIfPermNotDeclared*/);
+ }
+
+ private boolean canRequestPackageInstallsInternal(String packageName, int flags, int userId,
+ boolean throwIfPermNotDeclared) {
int callingUid = Binder.getCallingUid();
int uid = getPackageUid(packageName, 0, userId);
if (callingUid != uid && callingUid != Process.ROOT_UID
@@ -23951,18 +23992,23 @@
throw new SecurityException(
"Caller uid " + callingUid + " does not own package " + packageName);
}
- ApplicationInfo info = getApplicationInfo(packageName, 0, userId);
+ ApplicationInfo info = getApplicationInfo(packageName, flags, userId);
if (info == null) {
return false;
}
if (info.targetSdkVersion < Build.VERSION_CODES.O) {
- throw new UnsupportedOperationException(
- "Operation only supported on apps targeting Android O or higher");
+ return false;
}
String appOpPermission = Manifest.permission.REQUEST_INSTALL_PACKAGES;
String[] packagesDeclaringPermission = getAppOpPermissionPackages(appOpPermission);
if (!ArrayUtils.contains(packagesDeclaringPermission, packageName)) {
- throw new SecurityException("Need to declare " + appOpPermission + " to call this api");
+ if (throwIfPermNotDeclared) {
+ throw new SecurityException("Need to declare " + appOpPermission
+ + " to call this api");
+ } else {
+ Slog.e(TAG, "Need to declare " + appOpPermission + " to call this api");
+ return false;
+ }
}
if (sUserManager.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, userId)) {
return false;
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index feeee3f..6d48a05 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1374,7 +1374,7 @@
case Icon.TYPE_ADAPTIVE_BITMAP: {
bitmap = icon.getBitmap(); // Don't recycle in this case.
maxIconDimension *= (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction());
-
+ break;
}
default:
// This shouldn't happen because we've already validated the icon, but
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 30c4009..b115422 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -3684,6 +3684,11 @@
}
@Override
+ public int[] getUserIds() {
+ return UserManagerService.this.getUserIds();
+ }
+
+ @Override
public boolean isUserUnlockingOrUnlocked(int userId) {
synchronized (mUserStates) {
int state = mUserStates.get(userId, -1);
diff --git a/services/core/java/com/android/server/storage/CacheQuotaStrategy.java b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
index 82dd9ac..7a35bf7 100644
--- a/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
+++ b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
@@ -177,7 +177,7 @@
UserInfo info = users.get(i);
List<UsageStats> stats =
mUsageStats.queryUsageStatsForUser(info.id, UsageStatsManager.INTERVAL_BEST,
- oneYearAgo, timeNow);
+ oneYearAgo, timeNow, /*obfuscateInstantApps=*/ false);
if (stats == null) {
continue;
}
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index fb7ccc7..4044fdb 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -368,7 +368,7 @@
// There is an active service, update it if needed
updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
- mCurrentVrService.getUserId(), null);
+ mCurrentVrService.getUserId(), mCurrentVrModeComponent);
}
}
@@ -675,7 +675,7 @@
* @param enabled new state for VR mode.
* @param component new component to be bound as a VR listener.
* @param userId user owning the component to be bound.
- * @param calling the component currently using VR mode, or null to leave unchanged.
+ * @param calling the component currently using VR mode.
*
* @return {@code true} if the component/user combination specified is valid.
*/
diff --git a/services/core/java/com/android/server/wm/AlertWindowNotification.java b/services/core/java/com/android/server/wm/AlertWindowNotification.java
index 7ed3eac..50b1520 100644
--- a/services/core/java/com/android/server/wm/AlertWindowNotification.java
+++ b/services/core/java/com/android/server/wm/AlertWindowNotification.java
@@ -16,15 +16,14 @@
package com.android.server.wm;
-import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
import static android.content.Context.NOTIFICATION_SERVICE;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.provider.Settings.ACTION_MANAGE_OVERLAY_PERMISSION;
+import static com.android.internal.notification.SystemNotificationChannels.ALERT_WINDOW;
import android.app.Notification;
-import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
@@ -41,7 +40,7 @@
/** Displays an ongoing notification for a process displaying an alert window */
class AlertWindowNotification {
- private static final String CHANNEL_PREFIX = "com.android.server.wm.AlertWindowNotification - ";
+ private static final String TAG_PREFIX = "com.android.server.wm.AlertWindowNotification: ";
private static final int NOTIFICATION_ID = 0;
private static int sNextRequestCode = 0;
@@ -58,7 +57,7 @@
mPackageName = packageName;
mNotificationManager =
(NotificationManager) mService.mContext.getSystemService(NOTIFICATION_SERVICE);
- mNotificationTag = CHANNEL_PREFIX + mPackageName;
+ mNotificationTag = TAG_PREFIX + mPackageName;
mRequestCode = sNextRequestCode++;
mIconUtilities = new IconUtilities(mService.mContext);
}
@@ -100,11 +99,9 @@
final String appName = (aInfo != null)
? pm.getApplicationLabel(aInfo).toString() : mPackageName;
- createNotificationChannelIfNeeded(context, appName);
-
final String message = context.getString(R.string.alert_windows_notification_message,
appName);
- final Notification.Builder builder = new Notification.Builder(context, mNotificationTag)
+ final Notification.Builder builder = new Notification.Builder(context, ALERT_WINDOW)
.setOngoing(true)
.setContentTitle(
context.getString(R.string.alert_windows_notification_title, appName))
@@ -134,20 +131,6 @@
return PendingIntent.getActivity(context, mRequestCode, intent, FLAG_CANCEL_CURRENT);
}
- private void createNotificationChannelIfNeeded(Context context, String appName) {
- if (mNotificationManager.getNotificationChannel(mNotificationTag) != null) {
- return;
- }
- final String nameChannel =
- context.getString(R.string.alert_windows_notification_channel_name, appName);
- final NotificationChannel channel =
- new NotificationChannel(mNotificationTag, nameChannel, IMPORTANCE_MIN);
- channel.enableLights(false);
- channel.enableVibration(false);
- mNotificationManager.createNotificationChannel(channel);
- }
-
-
private ApplicationInfo getApplicationInfo(PackageManager pm, String packageName) {
try {
return pm.getApplicationInfo(packageName, 0);
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 16edd35..65e3ec0 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -411,7 +411,9 @@
}
if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + mAppToken
- + ": reportedVisible=" + mAppToken.reportedVisible);
+ + ": reportedVisible=" + mAppToken.reportedVisible
+ + " okToDisplay=" + mService.okToDisplay()
+ + " startingDisplayed=" + mAppToken.startingDisplayed);
transformation.clear();
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index b5e194b..5545e2b 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -447,7 +447,7 @@
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,
- boolean allowTaskSnapshot) {
+ boolean allowTaskSnapshot, boolean activityCreated) {
synchronized(mWindowMap) {
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "setAppStartingWindow: token=" + mToken
+ " pkg=" + pkg + " transferFrom=" + transferFrom);
@@ -475,7 +475,7 @@
}
final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
- allowTaskSnapshot);
+ allowTaskSnapshot, activityCreated);
if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
return createSnapshot();
@@ -546,8 +546,9 @@
}
private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
- boolean allowTaskSnapshot) {
- if (newTask || !processRunning) {
+ boolean allowTaskSnapshot, boolean activityCreated) {
+ if (newTask || !processRunning
+ || (taskSwitch && !activityCreated)) {
return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
} else if (taskSwitch && allowTaskSnapshot) {
return STARTING_WINDOW_TYPE_SNAPSHOT;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 96ea5e5..57b0fe2 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -560,6 +560,9 @@
// with it will be removed as soon as their animations are complete
mAppAnimator.clearAnimation();
mAppAnimator.animating = false;
+ if (stack != null) {
+ stack.mExitingAppTokens.remove(this);
+ }
removeIfPossible();
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 257f285..bbf7d9f 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -520,9 +520,16 @@
}
w.mLayoutNeeded = false;
w.prelayout();
+ final boolean firstLayout = !w.isLaidOut();
mService.mPolicy.layoutWindowLw(w, null);
w.mLayoutSeq = mService.mLayoutSeq;
+ // If this is the first layout, we need to initialize the last inset values as
+ // otherwise we'd immediately cause an unnecessary resize.
+ if (firstLayout) {
+ w.updateLastInsetValues();
+ }
+
// Window frames may have changed. Update dim layer with the new bounds.
final Task task = w.getTask();
if (task != null) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 0a999e6..27661e2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -92,6 +92,12 @@
private TaskDescription mTaskDescription;
+ // If set to true, the task will report that it is not in the floating
+ // state regardless of it's stack affilation. As the floating state drives
+ // production of content insets this can be used to preserve them across
+ // stack moves and we in fact do so when moving from full screen to pinned.
+ private boolean mPreserveNonFloatingState = false;
+
Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
Configuration overrideConfig, int resizeMode, boolean supportsPictureInPicture,
boolean homeTask, TaskDescription taskDescription,
@@ -194,6 +200,16 @@
EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "reParentTask");
final DisplayContent prevDisplayContent = getDisplayContent();
+ // If we are moving from the fullscreen stack to the pinned stack
+ // then we want to preserve our insets so that there will not
+ // be a jump in the area covered by system decorations. We rely
+ // on the pinned animation to later unset this value.
+ if (stack.mStackId == PINNED_STACK_ID) {
+ mPreserveNonFloatingState = true;
+ } else {
+ mPreserveNonFloatingState = false;
+ }
+
getParent().removeChild(this);
stack.addTask(this, position, showForAllUsers(), moveParents);
@@ -593,7 +609,8 @@
* we will have a jump at the end.
*/
boolean isFloating() {
- return StackId.tasksAreFloating(mStack.mStackId) && !mStack.isAnimatingBoundsToFullscreen();
+ return StackId.tasksAreFloating(mStack.mStackId)
+ && !mStack.isAnimatingBoundsToFullscreen() && !mPreserveNonFloatingState;
}
WindowState getTopVisibleAppMainWindow() {
@@ -675,6 +692,10 @@
return toShortString();
}
+ void clearPreserveNonFloatingState() {
+ mPreserveNonFloatingState = false;
+ }
+
@Override
public String toShortString() {
return "Task=" + mTaskId;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 0287070..866bfc0 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -209,11 +209,12 @@
SystemClock.sleep(DELAY_MS);
}
synchronized (mLock) {
- if (!mWriteQueue.isEmpty()) {
+ final boolean writeQueueEmpty = mWriteQueue.isEmpty();
+ if (!writeQueueEmpty && !mPaused) {
continue;
}
try {
- mQueueIdling = true;
+ mQueueIdling = writeQueueEmpty;
mLock.wait();
mQueueIdling = false;
} catch (InterruptedException e) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 2b9e800..5e7b910 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -116,7 +116,6 @@
private final TaskSnapshot mSnapshot;
private final CharSequence mTitle;
private boolean mHasDrawn;
- private boolean mReportNextDraw;
private long mShownTime;
private final Handler mHandler;
private boolean mSizeMismatch;
@@ -263,15 +262,11 @@
} else {
drawSizeMatchSnapshot(buffer);
}
- final boolean reportNextDraw;
synchronized (mService.mWindowMap) {
mShownTime = SystemClock.uptimeMillis();
mHasDrawn = true;
- reportNextDraw = mReportNextDraw;
}
- if (reportNextDraw) {
- reportDrawn();
- }
+ reportDrawn();
}
private void drawSizeMatchSnapshot(GraphicBuffer buffer) {
@@ -356,9 +351,6 @@
}
private void reportDrawn() {
- synchronized (mService.mWindowMap) {
- mReportNextDraw = false;
- }
try {
mSession.finishDrawing(mWindow);
} catch (RemoteException e) {
@@ -376,9 +368,6 @@
final TaskSnapshotSurface surface = (TaskSnapshotSurface) msg.obj;
synchronized (surface.mService.mWindowMap) {
hasDrawn = surface.mHasDrawn;
- if (!hasDrawn) {
- surface.mReportNextDraw = true;
- }
}
if (hasDrawn) {
surface.reportDrawn();
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index da7a9f0..9d48ce5 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -139,6 +139,8 @@
// Will be cleared once the client retrieves the new bounds via getBoundsForNewConfiguration().
private final Rect mBoundsAfterRotation = new Rect();
+ Rect mPreAnimationBounds = new Rect();
+
TaskStack(WindowManagerService service, int stackId) {
mService = service;
mStackId = stackId;
@@ -336,6 +338,8 @@
} else {
mBoundsAnimationSourceHintBounds.setEmpty();
}
+
+ mPreAnimationBounds.set(mBounds);
}
/**
@@ -1530,10 +1534,17 @@
// Hold the lock since this is called from the BoundsAnimator running on the UiThread
synchronized (mService.mWindowMap) {
mBoundsAnimating = false;
+ for (int i = 0; i < mChildren.size(); i++) {
+ final Task t = mChildren.get(i);
+ t.clearPreserveNonFloatingState();
+ }
mService.requestTraversal();
}
if (mStackId == PINNED_STACK_ID) {
+ // Update to the final bounds if requested. This is done here instead of in the bounds
+ // animator to allow us to coordinate this after we notify the PiP mode changed
+
final PinnedStackWindowController controller =
(PinnedStackWindowController) getController();
if (schedulePipModeChangedCallback && controller != null) {
@@ -1543,8 +1554,6 @@
mBoundsAnimationTarget);
}
- // Update to the final bounds if requested. This is done here instead of in the bounds
- // animator to allow us to coordinate this after we notify the PiP mode changed
if (finalStackSize != null) {
setPinnedStackSize(finalStackSize, null);
}
@@ -1584,8 +1593,12 @@
return mBoundsAnimating;
}
+ public boolean lastAnimatingBoundsWasToFullscreen() {
+ return mBoundsAnimatingToFullscreen;
+ }
+
public boolean isAnimatingBoundsToFullscreen() {
- return mBoundsAnimating && mBoundsAnimatingToFullscreen;
+ return isAnimatingBounds() && lastAnimatingBoundsWasToFullscreen();
}
public boolean pinnedStackResizeDisallowed() {
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index d64dc0e..d85dd0c 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -52,6 +52,7 @@
/** Is any window animating? */
private boolean mAnimating;
+ private boolean mLastAnimating;
/** Is any app window animating? */
boolean mAppWindowAnimating;
@@ -158,7 +159,6 @@
*/
private void animate(long frameTimeNs) {
boolean transactionOpen = false;
- boolean wasAnimating = false;
try {
synchronized (mService.mWindowMap) {
if (!mInitialized) {
@@ -167,8 +167,7 @@
mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
- wasAnimating = mAnimating;
- setAnimating(false);
+ mAnimating = false;
mAppWindowAnimating = false;
if (DEBUG_WINDOW_TRACE) {
Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
@@ -269,25 +268,22 @@
mWindowPlacerLocked.requestTraversal();
}
- if (mAnimating && !wasAnimating) {
+ if (mAnimating && !mLastAnimating) {
// Usually app transitions but quite a load onto the system already (with all the
// things happening in app), so pause task snapshot persisting to not increase the
// load.
mService.mTaskSnapshotController.setPersisterPaused(true);
- if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
- Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
- }
+ Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
}
-
- if (!mAnimating && wasAnimating) {
+ if (!mAnimating && mLastAnimating) {
mWindowPlacerLocked.requestTraversal();
mService.mTaskSnapshotController.setPersisterPaused(false);
- if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
- Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
- }
+ Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
}
+ mLastAnimating = mAnimating;
+
if (mRemoveReplacedWindows) {
mService.mRoot.removeReplacedWindows();
mRemoveReplacedWindows = false;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 84ba139..ca8c484 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -16,6 +16,11 @@
package com.android.server.wm;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.res.Configuration.EMPTY;
+
import android.annotation.CallSuper;
import android.content.res.Configuration;
import android.util.Pools;
@@ -27,11 +32,6 @@
import java.util.function.Consumer;
import java.util.function.Predicate;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.content.res.Configuration.EMPTY;
-
/**
* Defines common functionality for classes that can hold windows directly or through their
* children in a hierarchy form.
@@ -52,7 +52,7 @@
// List of children for this window container. List is in z-order as the children appear on
// screen with the top-most window container at the tail of the list.
- protected final LinkedList<E> mChildren = new LinkedList();
+ protected final WindowList<E> mChildren = new WindowList<E>();
/** Contains override configuration settings applied to this window container. */
private Configuration mOverrideConfiguration = new Configuration();
@@ -258,7 +258,7 @@
case POSITION_TOP:
if (mChildren.peekLast() != child) {
mChildren.remove(child);
- mChildren.addLast(child);
+ mChildren.add(child);
}
if (includingParents && getParent() != null) {
getParent().positionChildAt(POSITION_TOP, this /* child */,
@@ -649,7 +649,7 @@
}
if (mParent != null && mParent == other.mParent) {
- final LinkedList<WindowContainer> list = mParent.mChildren;
+ final WindowList<WindowContainer> list = mParent.mChildren;
return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
}
@@ -685,7 +685,7 @@
// The position of the first non-common ancestor in the common ancestor list determines
// which is greater the which.
- final LinkedList<WindowContainer> list = commonAncestor.mChildren;
+ final WindowList<WindowContainer> list = commonAncestor.mChildren;
return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
? 1 : -1;
}
diff --git a/services/core/java/com/android/server/wm/WindowList.java b/services/core/java/com/android/server/wm/WindowList.java
new file mode 100644
index 0000000..dfeba40
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WindowList.java
@@ -0,0 +1,38 @@
+/*
+ * 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 java.util.ArrayList;
+
+/**
+ * An {@link ArrayList} with extended functionality to be used as the children data structure in
+ * {@link WindowContainer}.
+ */
+class WindowList<E> extends ArrayList<E> {
+
+ void addFirst(E e) {
+ add(0, e);
+ }
+
+ E peekLast() {
+ return size() > 0 ? get(size() - 1) : null;
+ }
+
+ E peekFirst() {
+ return size() > 0 ? get(0) : null;
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 424f8a5..6be7900 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1685,6 +1685,10 @@
// re-factor.
atoken.firstWindowDrawn = false;
atoken.clearAllDrawn();
+ final TaskStack stack = atoken.getStack();
+ if (stack != null) {
+ stack.mExitingAppTokens.remove(atoken);
+ }
}
}
@@ -2093,6 +2097,7 @@
outFrame.set(win.mCompatFrame);
outOverscanInsets.set(win.mOverscanInsets);
outContentInsets.set(win.mContentInsets);
+ win.mLastRelayoutContentInsets.set(win.mContentInsets);
outVisibleInsets.set(win.mVisibleInsets);
outStableInsets.set(win.mStableInsets);
outOutsets.set(win.mOutsets);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 25b6561..344c616 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -208,7 +208,7 @@
boolean mHidden; // Used to determine if to show child windows.
boolean mWallpaperVisible; // for wallpaper, what was last vis report?
private boolean mDragResizing;
- private boolean mDragResizingChangeReported;
+ private boolean mDragResizingChangeReported = true;
private int mResizeMode;
private RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks;
@@ -257,6 +257,16 @@
*/
final Rect mContentInsets = new Rect();
final Rect mLastContentInsets = new Rect();
+
+ /**
+ * The last content insets returned to the client in relayout. We use
+ * these in the bounds animation to ensure we only observe inset changes
+ * at the same time that a client resizes it's surface so that we may use
+ * the geometryAppliesWithResize synchronization mechanism to keep
+ * the contents in place.
+ */
+ final Rect mLastRelayoutContentInsets = new Rect();
+
private boolean mContentInsetsChanged;
/**
@@ -1145,11 +1155,7 @@
return;
}
- mLastOverscanInsets.set(mOverscanInsets);
- mLastContentInsets.set(mContentInsets);
- mLastVisibleInsets.set(mVisibleInsets);
- mLastStableInsets.set(mStableInsets);
- mLastOutsets.set(mOutsets);
+ updateLastInsetValues();
mService.makeWindowFreezingScreenIfNeededLocked(this);
// If the orientation is changing, or we're starting or ending a drag resizing action,
@@ -4394,6 +4400,24 @@
return result;
}
+ /**
+ * @return True if this window has been laid out at least once; false otherwise.
+ */
+ boolean isLaidOut() {
+ return mLayoutSeq != -1;
+ }
+
+ /**
+ * Updates the last inset values to the current ones.
+ */
+ void updateLastInsetValues() {
+ mLastOverscanInsets.set(mOverscanInsets);
+ mLastContentInsets.set(mContentInsets);
+ mLastVisibleInsets.set(mVisibleInsets);
+ mLastStableInsets.set(mStableInsets);
+ mLastOutsets.set(mOutsets);
+ }
+
// TODO: Hack to work around the number of states AppWindowToken needs to access without having
// access to its windows children. Need to investigate re-writing
// {@link AppWindowToken#updateReportedVisibilityLocked} so this can be removed.
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 6cb4ddc..e1c6bc3 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -968,10 +968,8 @@
tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
}
- //TODO (multidisplay): Magnification is supported only for the default display.
- if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
- MagnificationSpec spec = mService.mAccessibilityController
- .getMagnificationSpecForWindowLocked(mWin);
+ MagnificationSpec spec = getMagnificationSpec();
+ if (spec != null) {
applyMagnificationSpec(spec, tmpMatrix);
}
@@ -1058,11 +1056,7 @@
TAG, "computeShownFrameLocked: " + this +
" not attached, mAlpha=" + mAlpha);
- MagnificationSpec spec = null;
- //TODO (multidisplay): Magnification is supported only for the default display.
- if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
- spec = mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin);
- }
+ MagnificationSpec spec = getMagnificationSpec();
if (spec != null) {
final Rect frame = mWin.mFrame;
final float tmpFloats[] = mService.mTmpFloats;
@@ -1099,6 +1093,14 @@
}
}
+ private MagnificationSpec getMagnificationSpec() {
+ //TODO (multidisplay): Magnification is supported only for the default display.
+ if (mService.mAccessibilityController != null && mWin.getDisplayId() == DEFAULT_DISPLAY) {
+ return mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin);
+ }
+ return null;
+ }
+
/**
* In some scenarios we use a screen space clip rect (so called, final clip rect)
* to crop to stack bounds. Generally because it's easier to deal with while
@@ -1136,6 +1138,27 @@
if (StackId.tasksAreFloating(stack.mStackId)) {
w.expandForSurfaceInsets(finalClipRect);
}
+
+ // We may be applying a magnification spec to all windows,
+ // simulating a transformation in screen space, in which case
+ // we need to transform all other screen space values...including
+ // the final crop. This is kind of messed up and we should look
+ // in to actually transforming screen-space via a parent-layer.
+ // b/38322835
+ MagnificationSpec spec = getMagnificationSpec();
+ if (spec != null && !spec.isNop()) {
+ Matrix transform = mWin.mTmpMatrix;
+ RectF finalCrop = mService.mTmpRectF;
+ transform.reset();
+ transform.postScale(spec.scale, spec.scale);
+ transform.postTranslate(-spec.offsetX, -spec.offsetY);
+ transform.mapRect(finalCrop);
+ finalClipRect.top = (int)finalCrop.top;
+ finalClipRect.left = (int)finalCrop.left;
+ finalClipRect.right = (int)finalClipRect.right;
+ finalClipRect.bottom = (int)finalClipRect.bottom;
+ }
+
return true;
}
@@ -1374,7 +1397,23 @@
int posX = mTmpSize.left;
int posY = mTmpSize.top;
task.mStack.getDimBounds(mTmpStackBounds);
+
+ boolean allowStretching = false;
task.mStack.getFinalAnimationSourceHintBounds(mTmpSourceBounds);
+ // If we don't have source bounds, we can attempt to use the content insets
+ // in the following scenario:
+ // 1. We have content insets.
+ // 2. We are not transitioning to full screen
+ // We have to be careful to check "lastAnimatingBoundsWasToFullscreen" rather than
+ // the mBoundsAnimating state, as we may have already left it and only be here
+ // because of the force-scale until resize state.
+ if (mTmpSourceBounds.isEmpty() && (mWin.mLastRelayoutContentInsets.width() > 0
+ || mWin.mLastRelayoutContentInsets.height() > 0)
+ && !task.mStack.lastAnimatingBoundsWasToFullscreen()) {
+ mTmpSourceBounds.set(task.mStack.mPreAnimationBounds);
+ mTmpSourceBounds.inset(mWin.mLastRelayoutContentInsets);
+ allowStretching = true;
+ }
if (!mTmpSourceBounds.isEmpty()) {
// Get the final target stack bounds, if we are not animating, this is just the
// current stack bounds
@@ -1384,14 +1423,24 @@
// and source bounds
float finalWidth = mTmpAnimatingBounds.width();
float initialWidth = mTmpSourceBounds.width();
- float t = (surfaceContentWidth - mTmpStackBounds.width())
+ float tw = (surfaceContentWidth - mTmpStackBounds.width())
/ (surfaceContentWidth - mTmpAnimatingBounds.width());
- mExtraHScale = (initialWidth + t * (finalWidth - initialWidth)) / initialWidth;
- mExtraVScale = mExtraHScale;
+ float th = tw;
+ mExtraHScale = (initialWidth + tw * (finalWidth - initialWidth)) / initialWidth;
+ if (allowStretching) {
+ float finalHeight = mTmpAnimatingBounds.height();
+ float initialHeight = mTmpSourceBounds.height();
+ th = (surfaceContentHeight - mTmpStackBounds.height())
+ / (surfaceContentHeight - mTmpAnimatingBounds.height());
+ mExtraVScale = (initialHeight + tw * (finalHeight - initialHeight))
+ / initialHeight;
+ } else {
+ mExtraVScale = mExtraHScale;
+ }
// Adjust the position to account for the inset bounds
- posX -= (int) (t * mExtraHScale * mTmpSourceBounds.left);
- posY -= (int) (t * mExtraVScale * mTmpSourceBounds.top);
+ posX -= (int) (tw * mExtraHScale * mTmpSourceBounds.left);
+ posY -= (int) (th * mExtraVScale * mTmpSourceBounds.top);
// Always clip to the stack bounds since the surface can be larger with the current
// scale
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 0f8c815..cb0ee25 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -1232,6 +1232,15 @@
}
@Test
+ public void testBadgingForUserAll() throws Exception {
+ try {
+ mHelper.badgingEnabled(UserHandle.ALL);
+ } catch (Exception e) {
+ fail("just don't throw");
+ }
+ }
+
+ @Test
public void testBadgingOverrideUserIsolation() throws Exception {
Secure.putIntForUser(getContext().getContentResolver(),
Secure.NOTIFICATION_BADGING, 0,
diff --git a/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java
index ca77528..d9d06ae 100644
--- a/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java
@@ -30,6 +30,7 @@
import android.os.FileUtils;
import android.os.IProgressListener;
import android.os.UserManager;
+import android.os.storage.StorageManager;
import android.security.KeyStore;
import android.test.AndroidTestCase;
@@ -82,7 +83,7 @@
mActivityManager = mock(IActivityManager.class);
mDevicePolicyManager = mock(DevicePolicyManager.class);
mContext = new MockLockSettingsContext(getContext(), mUserManager, mNotificationManager,
- mDevicePolicyManager);
+ mDevicePolicyManager, mock(StorageManager.class));
mStorage = new LockSettingsStorageTestable(mContext,
new File(getContext().getFilesDir(), "locksettings"));
File storageDir = mStorage.mStorageDir;
diff --git a/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java
index 4677904..f242b26 100644
--- a/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/LockSettingsStorageTests.java
@@ -28,6 +28,7 @@
import android.database.sqlite.SQLiteDatabase;
import android.os.FileUtils;
import android.os.UserManager;
+import android.os.storage.StorageManager;
import android.test.AndroidTestCase;
import com.android.internal.widget.LockPatternUtils;
@@ -69,7 +70,8 @@
when(mockUserManager.getProfileParent(eq(3))).thenReturn(new UserInfo(0, "name", 0));
MockLockSettingsContext context = new MockLockSettingsContext(getContext(), mockUserManager,
- mock(NotificationManager.class), mock(DevicePolicyManager.class));
+ mock(NotificationManager.class), mock(DevicePolicyManager.class),
+ mock(StorageManager.class));
mStorage = new LockSettingsStorageTestable(context,
new File(getContext().getFilesDir(), "locksettings"));
mStorage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() {
@@ -336,7 +338,7 @@
assertArrayEquals(data, mStorage.readSyntheticPasswordState(10, 1234L, "state"));
assertEquals(null, mStorage.readSyntheticPasswordState(0, 1234L, "state"));
- mStorage.deleteSyntheticPasswordState(10, 1234L, "state", true);
+ mStorage.deleteSyntheticPasswordState(10, 1234L, "state");
assertEquals(null, mStorage.readSyntheticPasswordState(10, 1234L, "state"));
}
diff --git a/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java b/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java
index 8bceed4..9dede3b 100644
--- a/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java
+++ b/services/tests/servicestests/src/com/android/server/MockLockSettingsContext.java
@@ -21,19 +21,23 @@
import android.content.Context;
import android.content.ContextWrapper;
import android.os.UserManager;
+import android.os.storage.StorageManager;
public class MockLockSettingsContext extends ContextWrapper {
private UserManager mUserManager;
private NotificationManager mNotificationManager;
private DevicePolicyManager mDevicePolicyManager;
+ private StorageManager mStorageManager;
public MockLockSettingsContext(Context base, UserManager userManager,
- NotificationManager notificationManager, DevicePolicyManager devicePolicyManager) {
+ NotificationManager notificationManager, DevicePolicyManager devicePolicyManager,
+ StorageManager storageManager) {
super(base);
mUserManager = userManager;
mNotificationManager = notificationManager;
mDevicePolicyManager = devicePolicyManager;
+ mStorageManager = storageManager;
}
@Override
@@ -44,6 +48,8 @@
return mNotificationManager;
} else if (DEVICE_POLICY_SERVICE.equals(name)) {
return mDevicePolicyManager;
+ } else if (STORAGE_SERVICE.equals(name)) {
+ return mStorageManager;
} else {
throw new RuntimeException("System service not mocked: " + name);
}
diff --git a/services/tests/servicestests/src/com/android/server/MockStorageManager.java b/services/tests/servicestests/src/com/android/server/MockStorageManager.java
index 17c8ec2..3a17718 100644
--- a/services/tests/servicestests/src/com/android/server/MockStorageManager.java
+++ b/services/tests/servicestests/src/com/android/server/MockStorageManager.java
@@ -500,4 +500,9 @@
throw new UnsupportedOperationException();
}
+ @Override
+ public void secdiscard(String path) throws RemoteException {
+ throw new UnsupportedOperationException();
+ }
+
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java b/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java
index 8afe853..72820f1 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java
@@ -25,6 +25,9 @@
import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -45,12 +48,13 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
/**
@@ -63,15 +67,50 @@
private static final int NON_ROOT_NODE_ID = 0xAAAA5555;
private static final long INTERROGATING_TID = 0x1234FACE;
- private static final AccessibilityAction[] ACTIONS_FROM_REPLACER =
- {ACTION_CLICK, ACTION_EXPAND};
- private static final AccessibilityAction[] A11Y_FOCUS_ACTIONS =
- {ACTION_ACCESSIBILITY_FOCUS, ACTION_CLEAR_ACCESSIBILITY_FOCUS};
// We expect both the replacer actions and a11y focus actions to appear
private static final AccessibilityAction[] REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE =
{ACTION_CLICK, ACTION_EXPAND, ACTION_ACCESSIBILITY_FOCUS,
ACTION_CLEAR_ACCESSIBILITY_FOCUS};
+ private static final Matcher<AccessibilityNodeInfo> HAS_NO_ACTIONS =
+ new BaseMatcher<AccessibilityNodeInfo>() {
+ @Override
+ public boolean matches(Object o) {
+ AccessibilityNodeInfo node = (AccessibilityNodeInfo) o;
+ if (!node.getActionList().isEmpty()) return false;
+ return (!node.isScrollable() && !node.isLongClickable() && !node.isClickable()
+ && !node.isContextClickable() && !node.isDismissable() && !node.isFocusable());
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Has no actions");
+ }
+ };
+
+ private static final Matcher<AccessibilityNodeInfo> HAS_EXPECTED_ACTIONS_ON_ROOT =
+ new BaseMatcher<AccessibilityNodeInfo>() {
+ @Override
+ public boolean matches(Object o) {
+ AccessibilityNodeInfo node = (AccessibilityNodeInfo) o;
+ List<AccessibilityAction> actions = node.getActionList();
+ if ((actions.size() != 4) || !actions.contains(ACTION_CLICK)
+ || !actions.contains(ACTION_EXPAND)
+ || !actions.contains(ACTION_ACCESSIBILITY_FOCUS)) {
+ return false;
+ }
+ return (!node.isScrollable() && !node.isLongClickable()
+ && !node.isLongClickable() && node.isClickable()
+ && !node.isContextClickable() && !node.isDismissable()
+ && !node.isFocusable());
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Has only 4 actions expected on root");
+ }
+ };
+
@Mock IAccessibilityInteractionConnectionCallback mMockServiceCallback;
@Mock IAccessibilityInteractionConnection mMockReplacerConnection;
@@ -118,9 +157,10 @@
eq(INTERACTION_ID));
AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
assertEquals(AccessibilityNodeInfo.ROOT_NODE_ID, infoSentToService.getSourceNodeId());
- assertInfoHasExactlyTheseActions(infoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
+ assertThat(infoSentToService, HAS_EXPECTED_ACTIONS_ON_ROOT);
}
+ @Test
public void testCallbacks_singleNonrootNodeThenReplacer_returnsNodeWithNoActions()
throws RemoteException {
AccessibilityNodeInfo infoFromApp = AccessibilityNodeInfo.obtain();
@@ -136,9 +176,10 @@
eq(INTERACTION_ID));
AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
assertEquals(NON_ROOT_NODE_ID, infoSentToService.getSourceNodeId());
- assertTrue(infoSentToService.getActionList().isEmpty());
+ assertThat(infoSentToService, HAS_NO_ACTIONS);
}
+ @Test
public void testCallbacks_replacerThenSingleRootNode_returnsNodeWithReplacedActions()
throws RemoteException {
mActionReplacingCallback.setFindAccessibilityNodeInfosResult(getReplacerNodes(),
@@ -154,9 +195,10 @@
eq(INTERACTION_ID));
AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
assertEquals(AccessibilityNodeInfo.ROOT_NODE_ID, infoSentToService.getSourceNodeId());
- assertInfoHasExactlyTheseActions(infoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
+ assertThat(infoSentToService, HAS_EXPECTED_ACTIONS_ON_ROOT);
}
+ @Test
public void testCallbacks_multipleNodesThenReplacer_clearsActionsAndAddsSomeToRoot()
throws RemoteException {
mActionReplacingCallback
@@ -173,11 +215,11 @@
mInfoListCaptor.getValue(), AccessibilityNodeInfo.ROOT_NODE_ID);
AccessibilityNodeInfo otherInfoSentToService = getNodeWithIdFromList(
mInfoListCaptor.getValue(), NON_ROOT_NODE_ID);
- assertInfoHasExactlyTheseActions(
- rootInfoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
- assertTrue(otherInfoSentToService.getActionList().isEmpty());
+ assertThat(rootInfoSentToService, HAS_EXPECTED_ACTIONS_ON_ROOT);
+ assertThat(otherInfoSentToService, HAS_NO_ACTIONS);
}
+ @Test
public void testCallbacks_replacerThenMultipleNodes_clearsActionsAndAddsSomeToRoot()
throws RemoteException {
mActionReplacingCallback.setFindAccessibilityNodeInfosResult(getReplacerNodes(),
@@ -194,18 +236,18 @@
mInfoListCaptor.getValue(), AccessibilityNodeInfo.ROOT_NODE_ID);
AccessibilityNodeInfo otherInfoSentToService = getNodeWithIdFromList(
mInfoListCaptor.getValue(), NON_ROOT_NODE_ID);
- assertInfoHasExactlyTheseActions(
- rootInfoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
- assertTrue(otherInfoSentToService.getActionList().isEmpty());
+ assertThat(rootInfoSentToService, HAS_EXPECTED_ACTIONS_ON_ROOT);
+ assertThat(otherInfoSentToService, HAS_NO_ACTIONS);
}
+ @Test
public void testConstructor_actionReplacerThrowsException_passesDataToService()
throws RemoteException {
doThrow(RemoteException.class).when(mMockReplacerConnection)
.findAccessibilityNodeInfoByAccessibilityId(eq(AccessibilityNodeInfo.ROOT_NODE_ID),
- (Region) anyObject(), mInteractionIdCaptor.capture(),
- eq(mActionReplacingCallback), eq(0), eq(INTERROGATING_PID),
- eq(INTERROGATING_TID), (MagnificationSpec) anyObject(), eq(null));
+ (Region) anyObject(), anyInt(), (ActionReplacingCallback) anyObject(),
+ eq(0), eq(INTERROGATING_PID), eq(INTERROGATING_TID),
+ (MagnificationSpec) anyObject(), eq(null));
ActionReplacingCallback actionReplacingCallback = new ActionReplacingCallback(
mMockServiceCallback, mMockReplacerConnection, INTERACTION_ID, INTERROGATING_PID,
INTERROGATING_TID);
@@ -214,16 +256,17 @@
AccessibilityNodeInfo infoFromApp = AccessibilityNodeInfo.obtain();
infoFromApp.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID, APP_WINDOW_ID);
infoFromApp.addAction(ACTION_CONTEXT_CLICK);
+ infoFromApp.setContextClickable(true);
actionReplacingCallback.setFindAccessibilityNodeInfoResult(infoFromApp, INTERACTION_ID);
verify(mMockServiceCallback).setFindAccessibilityNodeInfoResult(mInfoCaptor.capture(),
eq(INTERACTION_ID));
AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
assertEquals(AccessibilityNodeInfo.ROOT_NODE_ID, infoSentToService.getSourceNodeId());
- assertEquals(1, infoSentToService.getActionList().size());
- assertEquals(ACTION_CONTEXT_CLICK, infoSentToService.getActionList().get(0));
+ assertThat(infoSentToService, HAS_NO_ACTIONS);
}
+ @Test
public void testSetPerformAccessibilityActionResult_actsAsPassThrough() throws RemoteException {
mActionReplacingCallback.setPerformAccessibilityActionResult(true, INTERACTION_ID);
verify(mMockServiceCallback).setPerformAccessibilityActionResult(true, INTERACTION_ID);
@@ -236,9 +279,9 @@
AccessibilityNodeInfo root = AccessibilityNodeInfo.obtain();
root.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID,
AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
- for (AccessibilityAction action : ACTIONS_FROM_REPLACER) {
- root.addAction(action);
- }
+ root.addAction(ACTION_CLICK);
+ root.addAction(ACTION_EXPAND);
+ root.setClickable(true);
// Second node should have no effect
AccessibilityNodeInfo other = AccessibilityNodeInfo.obtain();
@@ -249,13 +292,6 @@
return Arrays.asList(root, other);
}
- private void assertInfoHasExactlyTheseActions(
- AccessibilityNodeInfo info, AccessibilityAction[] actions) {
- List<AccessibilityAction> nodeActions = info.getActionList();
- assertEquals(new HashSet<AccessibilityAction>(nodeActions),
- new HashSet<AccessibilityAction>(Arrays.asList(actions)));
- }
-
private AccessibilityNodeInfo getNodeWithIdFromList(
List<AccessibilityNodeInfo> infos, long id) {
for (AccessibilityNodeInfo info : infos) {
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
index a8c39c4..6706969 100644
--- a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
+++ b/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
@@ -24,6 +24,7 @@
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.ContextWrapper;
import android.content.pm.IPackageInstallObserver2;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
@@ -32,6 +33,7 @@
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.test.mock.MockContentResolver;
import com.android.internal.util.test.FakeSettingsProvider;
@@ -40,20 +42,20 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.io.File;
import java.util.ArrayList;
-@RunWith(JUnit4.class)
+@RunWith(AndroidJUnit4.class)
@SmallTest
public class PreloadAppsInstallerTest {
private static final int TEST_DEMO_USER = 111;
- private @Mock Context mContext;
+ private Context mContext;
private @Mock IPackageManager mIpm;
private MockContentResolver mContentResolver;
private File mPreloadsAppsDirectory;
@@ -66,6 +68,7 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
mContentResolver = new MockContentResolver(mContext);
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
when(mContext.getContentResolver()).thenReturn(mContentResolver);
@@ -89,7 +92,9 @@
@After
public void tearDown() {
- FileUtils.deleteContentsAndDir(mPreloadsAppsDirectory);
+ if (mPreloadsAppsDirectory != null) {
+ FileUtils.deleteContentsAndDir(mPreloadsAppsDirectory);
+ }
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
index ce5b8cb..2e13d29 100644
--- a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
@@ -38,6 +38,7 @@
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
@@ -59,6 +60,7 @@
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
import android.util.ArrayMap;
@@ -72,9 +74,9 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.compat.ArgumentMatcher;
@@ -82,7 +84,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-@RunWith(JUnit4.class)
+@RunWith(AndroidJUnit4.class)
@SmallTest
public class RetailDemoModeServiceTest {
private static final int TEST_DEMO_USER = 111;
@@ -90,7 +92,7 @@
private static final String TEST_CAMERA_PKG = "test.cameraapp";
private static final String TEST_PRELOADS_DIR_NAME = "test_preloads";
- private @Mock Context mContext;
+ private Context mContext;
private @Mock UserManager mUm;
private @Mock PackageManager mPm;
private @Mock IPackageManager mIpm;
@@ -113,12 +115,11 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- Context originalContext = InstrumentationRegistry.getContext();
- when(mContext.getApplicationInfo()).thenReturn(originalContext.getApplicationInfo());
- when(mContext.getResources()).thenReturn(originalContext.getResources());
+ mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
when(mContext.getSystemServiceName(eq(JobScheduler.class))).thenReturn(
Context.JOB_SCHEDULER_SERVICE);
when(mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE)).thenReturn(mJobScheduler);
+ when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUm);
mContentResolver = new MockContentResolver(mContext);
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
mContactsProvider = new MockContactsProvider(mContext);
@@ -129,12 +130,10 @@
mTestPreloadsDir = new File(InstrumentationRegistry.getContext().getFilesDir(),
TEST_PRELOADS_DIR_NAME);
- Settings.Global.putString(mContentResolver,
- Settings.Global.RETAIL_DEMO_MODE_CONSTANTS, "");
- Settings.Global.putInt(mContentResolver,
- Settings.Global.DEVICE_PROVISIONED, 1);
- Settings.Global.putInt(mContentResolver,
- Settings.Global.DEVICE_DEMO_MODE, 1);
+ Settings.Global.putString(mContentResolver, Settings.Global.RETAIL_DEMO_MODE_CONSTANTS, "");
+ Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED, 1);
+ Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_DEMO_MODE, 1);
+
// Initialize RetailDemoModeService
mInjector = new TestInjector();
mService = new RetailDemoModeService(mInjector);
@@ -143,7 +142,9 @@
@After
public void tearDown() {
- FileUtils.deleteContentsAndDir(mTestPreloadsDir);
+ if (mTestPreloadsDir != null) {
+ FileUtils.deleteContentsAndDir(mTestPreloadsDir);
+ }
}
@Test
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 dcbedb6..da3b9c9 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,8 @@
final WindowTestUtils.TestAppWindowContainerController controller =
createAppWindowController();
controller.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true);
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
+ false);
waitUntilHandlersIdle();
final AppWindowToken atoken = controller.getAppWindowToken(mDisplayContent);
assertHasStartingWindow(atoken);
@@ -113,11 +114,12 @@
final WindowTestUtils.TestAppWindowContainerController controller2 =
createAppWindowController();
controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true);
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
+ false);
waitUntilHandlersIdle();
controller2.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
android.R.style.Theme, null, "Test", 0, 0, 0, 0, controller1.mToken.asBinder(),
- true, true, false, true);
+ true, true, false, true, false);
waitUntilHandlersIdle();
assertNoStartingWindow(controller1.getAppWindowToken(mDisplayContent));
assertHasStartingWindow(controller2.getAppWindowToken(mDisplayContent));
@@ -134,10 +136,11 @@
// 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, true, false, true, false);
});
controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true);
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
+ false);
waitUntilHandlersIdle();
assertNoStartingWindow(controller1.getAppWindowToken(mDisplayContent));
assertHasStartingWindow(controller2.getAppWindowToken(mDisplayContent));
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
index d9349ed..b83532c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -115,11 +115,11 @@
}
WindowState getFirstChild() {
- return mChildren.getFirst();
+ return mChildren.peekFirst();
}
WindowState getLastChild() {
- return mChildren.getLast();
+ return mChildren.peekLast();
}
int positionInParent() {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 4ba457d..0de3c7c 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -39,6 +39,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
@@ -80,6 +81,7 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.LocalServices;
import com.android.server.SystemService;
import java.io.File;
@@ -137,6 +139,7 @@
AppOpsManager mAppOps;
UserManager mUserManager;
PackageManager mPackageManager;
+ PackageManagerInternal mPackageManagerInternal;
AppWidgetManager mAppWidgetManager;
IDeviceIdleController mDeviceIdleController;
private DisplayManager mDisplayManager;
@@ -179,6 +182,7 @@
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
mPackageManager = getContext().getPackageManager();
+ mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mHandler = new H(BackgroundThread.get().getLooper());
File systemDataDir = new File(Environment.getDataDirectory(), "system");
@@ -407,6 +411,10 @@
}
}
+ private boolean shouldObfuscateInstantAppsForCaller(int callingUid) {
+ return !mPackageManagerInternal.canAccessInstantApps(callingUid);
+ }
+
void clearAppIdleForPackage(String packageName, int userId) {
synchronized (mAppIdleLock) {
mAppIdleHistory.clearUsage(packageName, userId);
@@ -704,6 +712,11 @@
final long elapsedRealtime = SystemClock.elapsedRealtime();
convertToSystemTimeLocked(event);
+ if (event.getPackageName() != null
+ && mPackageManagerInternal.isPackageEphemeral(userId, event.getPackageName())) {
+ event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
+ }
+
final UserUsageStatsService service =
getUserDataAndInitializeIfNeededLocked(userId, timeNow);
service.reportEvent(event);
@@ -807,7 +820,8 @@
/**
* Called by the Binder stub.
*/
- List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime) {
+ List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime,
+ boolean obfuscateInstantApps) {
synchronized (mLock) {
final long timeNow = checkAndGetTimeLocked();
if (!validRange(timeNow, beginTime, endTime)) {
@@ -816,7 +830,20 @@
final UserUsageStatsService service =
getUserDataAndInitializeIfNeededLocked(userId, timeNow);
- return service.queryUsageStats(bucketType, beginTime, endTime);
+ List<UsageStats> list = service.queryUsageStats(bucketType, beginTime, endTime);
+
+ // Mangle instant app names *using their current state (not whether they were ephemeral
+ // when the data was recorded)*.
+ if (obfuscateInstantApps) {
+ for (int i = list.size() - 1; i >= 0; i--) {
+ final UsageStats stats = list.get(i);
+ if (mPackageManagerInternal.isPackageEphemeral(userId, stats.mPackageName)) {
+ list.set(i, stats.getObfuscatedForInstantApp());
+ }
+ }
+ }
+
+ return list;
}
}
@@ -840,7 +867,8 @@
/**
* Called by the Binder stub.
*/
- UsageEvents queryEvents(int userId, long beginTime, long endTime) {
+ UsageEvents queryEvents(int userId, long beginTime, long endTime,
+ boolean shouldObfuscateInstantApps) {
synchronized (mLock) {
final long timeNow = checkAndGetTimeLocked();
if (!validRange(timeNow, beginTime, endTime)) {
@@ -849,7 +877,7 @@
final UserUsageStatsService service =
getUserDataAndInitializeIfNeededLocked(userId, timeNow);
- return service.queryEvents(beginTime, endTime);
+ return service.queryEvents(beginTime, endTime, shouldObfuscateInstantApps);
}
}
@@ -884,10 +912,15 @@
}
}
- boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime) {
+ boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime,
+ boolean shouldObfuscateInstantApps) {
if (isParoledOrCharging()) {
return false;
}
+ if (shouldObfuscateInstantApps &&
+ mPackageManagerInternal.isPackageEphemeral(userId, packageName)) {
+ return false;
+ }
return isAppIdleFiltered(packageName, getAppId(packageName), userId, elapsedRealtime);
}
@@ -1353,11 +1386,14 @@
return null;
}
+ final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
+ Binder.getCallingUid());
+
final int userId = UserHandle.getCallingUserId();
final long token = Binder.clearCallingIdentity();
try {
final List<UsageStats> results = UsageStatsService.this.queryUsageStats(
- userId, bucketType, beginTime, endTime);
+ userId, bucketType, beginTime, endTime, obfuscateInstantApps);
if (results != null) {
return new ParceledListSlice<>(results);
}
@@ -1395,10 +1431,14 @@
return null;
}
+ final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
+ Binder.getCallingUid());
+
final int userId = UserHandle.getCallingUserId();
final long token = Binder.clearCallingIdentity();
try {
- return UsageStatsService.this.queryEvents(userId, beginTime, endTime);
+ return UsageStatsService.this.queryEvents(userId, beginTime, endTime,
+ obfuscateInstantApps);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1412,10 +1452,12 @@
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
+ final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
+ Binder.getCallingUid());
final long token = Binder.clearCallingIdentity();
try {
return UsageStatsService.this.isAppIdleFilteredOrParoled(packageName, userId,
- SystemClock.elapsedRealtime());
+ SystemClock.elapsedRealtime(), obfuscateInstantApps);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1647,9 +1689,10 @@
@Override
public List<UsageStats> queryUsageStatsForUser(
- int userId, int intervalType, long beginTime, long endTime) {
+ int userId, int intervalType, long beginTime, long endTime,
+ boolean obfuscateInstantApps) {
return UsageStatsService.this.queryUsageStats(
- userId, intervalType, beginTime, endTime);
+ userId, intervalType, beginTime, endTime, obfuscateInstantApps);
}
}
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index 96f3305..cc53a9c 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -26,7 +26,10 @@
import android.app.usage.UsageEvents;
import android.app.usage.UsageStats;
import android.content.res.Configuration;
+import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.Log;
+import android.util.LogWriter;
import java.io.IOException;
import java.net.ProtocolException;
@@ -35,6 +38,8 @@
* UsageStats reader/writer for version 1 of the XML format.
*/
final class UsageStatsXmlV1 {
+ private static final String TAG = "UsageStatsXmlV1";
+
private static final String PACKAGES_TAG = "packages";
private static final String PACKAGE_TAG = "package";
@@ -51,6 +56,7 @@
// Attributes
private static final String PACKAGE_ATTR = "package";
+ private static final String FLAGS_ATTR = "flags";
private static final String CLASS_ATTR = "class";
private static final String TOTAL_TIME_ACTIVE_ATTR = "timeActive";
private static final String COUNT_ATTR = "count";
@@ -70,7 +76,6 @@
if (pkg == null) {
throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present");
}
-
final UsageStats stats = statsOut.getOrCreateUsageStats(pkg);
// Apply the offset to the beginTime to find the absolute time.
@@ -149,11 +154,12 @@
if (packageName == null) {
throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present");
}
-
final String className = XmlUtils.readStringAttribute(parser, CLASS_ATTR);
final UsageEvents.Event event = statsOut.buildEvent(packageName, className);
+ event.mFlags = XmlUtils.readIntAttribute(parser, FLAGS_ATTR, 0);
+
// Apply the offset to the beginTime to find the absolute time of this event.
event.mTimeStamp = statsOut.beginTime + XmlUtils.readLongAttribute(parser, TIME_ATTR);
@@ -256,6 +262,7 @@
if (event.mClass != null) {
XmlUtils.writeStringAttribute(xml, CLASS_ATTR, event.mClass);
}
+ XmlUtils.writeIntAttribute(xml, FLAGS_ATTR, event.mFlags);
XmlUtils.writeIntAttribute(xml, TYPE_ATTR, event.mEventType);
switch (event.mEventType) {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 8d335a5..0abbb82 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -19,11 +19,8 @@
import android.app.usage.ConfigurationStats;
import android.app.usage.TimeSparseArray;
import android.app.usage.UsageEvents;
-import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.SystemClock;
import android.content.Context;
@@ -312,7 +309,8 @@
return queryStats(bucketType, beginTime, endTime, sConfigStatsCombiner);
}
- UsageEvents queryEvents(final long beginTime, final long endTime) {
+ UsageEvents queryEvents(final long beginTime, final long endTime,
+ boolean obfuscateInstantApps) {
final ArraySet<String> names = new ArraySet<>();
List<UsageEvents.Event> results = queryStats(UsageStatsManager.INTERVAL_DAILY,
beginTime, endTime, new StatCombiner<UsageEvents.Event>() {
@@ -334,7 +332,10 @@
return;
}
- final UsageEvents.Event event = stats.events.valueAt(i);
+ UsageEvents.Event event = stats.events.valueAt(i);
+ if (obfuscateInstantApps) {
+ event = event.getObfuscatedIfInstantApp();
+ }
names.add(event.mPackage);
if (event.mClass != null) {
names.add(event.mClass);
@@ -586,6 +587,7 @@
if (event.mShortcutId != null) {
pw.printPair("shortcutId", event.mShortcutId);
}
+ pw.printHexPair("flags", event.mFlags);
pw.println();
}
pw.decreaseIndent();
diff --git a/tests/UsageStatsTest/Android.mk b/tests/UsageStatsTest/Android.mk
index 5f7467a..6b5c999 100644
--- a/tests/UsageStatsTest/Android.mk
+++ b/tests/UsageStatsTest/Android.mk
@@ -8,6 +8,8 @@
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
+LOCAL_CERTIFICATE := platform
+
LOCAL_PACKAGE_NAME := UsageStatsTest
include $(BUILD_PACKAGE)
diff --git a/tests/UsageStatsTest/AndroidManifest.xml b/tests/UsageStatsTest/AndroidManifest.xml
index 589674a..c27be7b 100644
--- a/tests/UsageStatsTest/AndroidManifest.xml
+++ b/tests/UsageStatsTest/AndroidManifest.xml
@@ -1,7 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Note: Add android:sharedUserId="android.uid.system" to the root element to simulate the system UID
+ caller case.
+-->
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.tests.usagestats">
+ package="com.android.tests.usagestats"
+ >
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
diff --git a/tests/UsageStatsTest/res/menu/main.xml b/tests/UsageStatsTest/res/menu/main.xml
index e781058..4ccbc81 100644
--- a/tests/UsageStatsTest/res/menu/main.xml
+++ b/tests/UsageStatsTest/res/menu/main.xml
@@ -2,4 +2,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/log"
android:title="View Log"/>
+ <item android:id="@+id/call_is_app_inactive"
+ android:title="Call isAppInactive()"/>
</menu>
diff --git a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
index c08c1a3..9429d9b 100644
--- a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
+++ b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
@@ -16,12 +16,16 @@
package com.android.tests.usagestats;
+import android.app.AlertDialog;
import android.app.ListActivity;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
+import android.text.InputType;
+import android.text.TextUtils;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -30,6 +34,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
+import android.widget.EditText;
import android.widget.TextView;
import java.util.ArrayList;
@@ -69,6 +74,9 @@
case R.id.log:
startActivity(new Intent(this, UsageLogActivity.class));
return true;
+ case R.id.call_is_app_inactive:
+ callIsAppInactive();
+ return true;
default:
return super.onOptionsItemSelected(item);
@@ -81,6 +89,41 @@
updateAdapter();
}
+ private void callIsAppInactive() {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("Enter package name");
+ final EditText input = new EditText(this);
+ input.setInputType(InputType.TYPE_CLASS_TEXT);
+ input.setHint("com.android.tests.usagestats");
+ builder.setView(input);
+
+ builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ final String packageName = input.getText().toString().trim();
+ if (!TextUtils.isEmpty(packageName)) {
+ showInactive(packageName);
+ }
+ }
+ });
+ builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.cancel();
+ }
+ });
+
+ builder.show();
+ }
+
+ private void showInactive(String packageName) {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setMessage(
+ "isAppInactive(\"" + packageName + "\") = "
+ + (mUsageStatsManager.isAppInactive(packageName) ? "true" : "false"));
+ builder.show();
+ }
+
private void updateAdapter() {
long now = System.currentTimeMillis();
long beginTime = now - USAGE_STATS_PERIOD;
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
new file mode 100644
index 0000000..9fcd1b5
--- /dev/null
+++ b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.connectivity.tethering;
+
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
+import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
+import static android.net.ConnectivityManager.TYPE_WIFI;
+import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_NOT_REQUIRED;
+import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_REQUIRED;
+import static com.android.server.connectivity.tethering.TetheringConfiguration.DUN_UNSPECIFIED;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.res.Resources;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.util.test.BroadcastInterceptingContext;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class TetheringConfigurationTest {
+ @Mock private Context mContext;
+ @Mock private TelephonyManager mTelephonyManager;
+ @Mock private Resources mResources;
+ private Context mMockContext;
+ private boolean mHasTelephonyManager;
+
+ private class MockContext extends BroadcastInterceptingContext {
+ MockContext(Context base) {
+ super(base);
+ }
+
+ @Override
+ public Resources getResources() { return mResources; }
+
+ @Override
+ public Object getSystemService(String name) {
+ if (Context.TELEPHONY_SERVICE.equals(name)) {
+ return mHasTelephonyManager ? mTelephonyManager : null;
+ }
+ return super.getSystemService(name);
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
+ .thenReturn(new String[0]);
+ when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
+ .thenReturn(new String[0]);
+ when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
+ .thenReturn(new String[]{ "test_wlan\\d" });
+ when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
+ .thenReturn(new String[0]);
+ mMockContext = new MockContext(mContext);
+ }
+
+ @Test
+ public void testDunFromTelephonyManagerMeansDun() {
+ when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
+ .thenReturn(new int[]{TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI});
+ mHasTelephonyManager = true;
+ when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_REQUIRED);
+
+ final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext);
+ assertTrue(cfg.isDunRequired);
+ assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
+ assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
+ assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
+ // Just to prove we haven't clobbered Wi-Fi:
+ assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
+ }
+
+ @Test
+ public void testDunNotRequiredFromTelephonyManagerMeansNoDun() {
+ when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
+ .thenReturn(new int[]{TYPE_MOBILE_DUN, TYPE_WIFI});
+ mHasTelephonyManager = true;
+ when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_NOT_REQUIRED);
+
+ final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext);
+ assertFalse(cfg.isDunRequired);
+ assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
+ assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
+ assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
+ // Just to prove we haven't clobbered Wi-Fi:
+ assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
+ }
+
+ @Test
+ public void testDunFromUpstreamConfigMeansDun() {
+ when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
+ .thenReturn(new int[]{TYPE_MOBILE_DUN, TYPE_WIFI});
+ mHasTelephonyManager = false;
+ when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED);
+
+ final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext);
+ assertTrue(cfg.isDunRequired);
+ assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
+ // Just to prove we haven't clobbered Wi-Fi:
+ assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
+ }
+}
diff --git a/tools/aapt2/filter/ConfigFilter.cpp b/tools/aapt2/filter/ConfigFilter.cpp
index 66aff82..5fbe77e 100644
--- a/tools/aapt2/filter/ConfigFilter.cpp
+++ b/tools/aapt2/filter/ConfigFilter.cpp
@@ -38,6 +38,43 @@
config_mask_ |= diff_mask;
}
+// Returns true if the locale script of the config should be considered matching
+// the locale script of entry.
+//
+// If both the scripts are empty, the scripts are considered matching for
+// backward compatibility reasons.
+//
+// If only one script is empty, we try to compute it based on the provided
+// language and country. If we could not compute it, we assume it's either a
+// new language we don't know about, or a private use language. We return true
+// since we don't know any better and they might as well be a match.
+//
+// Finally, when we have two scripts (one of which could be computed), we return
+// true if and only if they are an exact match.
+static bool ScriptsMatch(const ConfigDescription& config, const ConfigDescription& entry) {
+ const char* config_script = config.localeScript;
+ const char* entry_script = entry.localeScript;
+ if (config_script[0] == '\0' && entry_script[0] == '\0') {
+ return true; // both scripts are empty. We match for backward compatibility reasons.
+ }
+
+ char script_buffer[sizeof(config.localeScript)];
+ if (config_script[0] == '\0') {
+ android::localeDataComputeScript(script_buffer, config.language, config.country);
+ if (script_buffer[0] == '\0') { // We can't compute the script, so we match.
+ return true;
+ }
+ config_script = script_buffer;
+ } else if (entry_script[0] == '\0') {
+ android::localeDataComputeScript(script_buffer, entry.language, entry.country);
+ if (script_buffer[0] == '\0') { // We can't compute the script, so we match.
+ return true;
+ }
+ entry_script = script_buffer;
+ }
+ return memcmp(config_script, entry_script, sizeof(config.localeScript)) == 0;
+}
+
bool AxisConfigFilter::Match(const ConfigDescription& config) const {
const uint32_t mask = ConfigDescription::DefaultConfig().diff(config);
if ((config_mask_ & mask) == 0) {
@@ -57,12 +94,16 @@
// If the locales differ, but the languages are the same and
// the locale we are matching only has a language specified,
// we match.
- if (config.language[0] &&
- memcmp(config.language, target.language, sizeof(config.language)) ==
- 0) {
- if (config.country[0] == 0) {
- matched_axis |= android::ResTable_config::CONFIG_LOCALE;
- }
+ //
+ // Exception: we won't match if a script is specified for at least
+ // one of the locales and it's different from the other locale's
+ // script. (We will compute the other script if at least one of the
+ // scripts were explicitly set. In cases we can't compute an script,
+ // we match.)
+ if (config.language[0] != '\0' && config.country[0] == '\0' &&
+ config.localeVariant[0] == '\0' && config.language[0] == entry.first.language[0] &&
+ config.language[1] == entry.first.language[1] && ScriptsMatch(config, entry.first)) {
+ matched_axis |= android::ResTable_config::CONFIG_LOCALE;
}
} else if ((diff & diff_mask) ==
android::ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE) {
diff --git a/tools/aapt2/filter/ConfigFilter_test.cpp b/tools/aapt2/filter/ConfigFilter_test.cpp
index 586dd5f..4a31080 100644
--- a/tools/aapt2/filter/ConfigFilter_test.cpp
+++ b/tools/aapt2/filter/ConfigFilter_test.cpp
@@ -109,4 +109,20 @@
EXPECT_TRUE(filter.Match(test::ParseConfigOrDie("kok-rIN")));
}
+TEST(ConfigFilterTest, MatchesScripts) {
+ AxisConfigFilter filter;
+
+ // "sr" gets automatically computed the script "Cyrl"
+ filter.AddConfig(test::ParseConfigOrDie("sr"));
+
+ // "sr" -> "b+sr+Cyrl"
+ EXPECT_TRUE(filter.Match(test::ParseConfigOrDie("b+sr+Cyrl")));
+
+ // The incoming "sr" is also auto-computed to "b+sr+Cyrl".
+ EXPECT_TRUE(filter.Match(test::ParseConfigOrDie("sr")));
+
+ // "sr" -> "b+sr+Cyrl", which doesn't match "Latn".
+ EXPECT_FALSE(filter.Match(test::ParseConfigOrDie("b+sr+Latn")));
+}
+
} // namespace aapt
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
index 92c7e36..ebf5c2a 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
@@ -139,7 +139,7 @@
public String getDeviceInfoHex() {
return String.format(
- Locale.US, "%04x%04x%04x%04x", 6, mDeviceInfo, mCtrlPort, mMaxThroughput);
+ Locale.US, "%04x%04x%04x", mDeviceInfo, mCtrlPort, mMaxThroughput);
}
public String toString() {